terminatorlib.editablelabel — terminatorlib 0.98 documentation

# Source code for terminatorlib.editablelabel

    #!/usr/bin/env python
    # vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab
    #
    # Copyright (c) 2009, Emmanuel Bretelle <chantra@debuntu.org>
    #
    #    This program is free software; you can redistribute it and/or modify
    #    it under the terms of the GNU General Public License as published by
    #    the Free Software Foundation, version 2 only.
    #
    #    This program is distributed in the hope that it will be useful,
    #    but WITHOUT ANY WARRANTY; without even the implied warranty of
    #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    #    GNU General Public License for more details.
    #
    #    You should have received a copy of the GNU General Public License
    #    along with this program; if not, write to the Free Software
    #    Foundation, Inc., 51 Franklin Street, Fifth Floor
    #    , Boston, MA  02110-1301  USA

    """ Editable Label class"""
    import gtk
    import gobject

    class EditableLabel(gtk.EventBox):
        # pylint: disable-msg=W0212
        # pylint: disable-msg=R0904
        """
        An eventbox that partialy emulate a gtk.Label
        On double-click, the label is editable, entering an empty will revert back to automatic text
        """
        _label = None
        _ebox = None
        _autotext = None
        _custom = None
        _entry = None
        _entry_handler_id = None

        __gsignals__ = {
                'edit-done': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
        }

        def __init__(self, text = ""):
            """ Class initialiser"""
            gtk.EventBox.__init__(self)
            self.__gobject_init__()

            self._entry_handler_id = []
            self._label = gtk.Label(text)
            self._custom = False
            self.set_visible_window (False)
            self.add (self._label)
            self.connect ("button-press-event", self._on_click_text)

        def set_angle(self, angle ):
            """set angle of the label"""
            self._label.set_angle( angle )

        def editing(self):
            """Return if we are currently editing"""
            return(self._entry != None)

        def set_text(self, text, force=False):
            """set the text of the label"""
            self._autotext = text
            if not self._custom or force:
                self._label.set_text(text)

        def get_text(self):
            """get the text from the label"""
            return(self._label.get_text())

        def _on_click_text(self, widget, event):
            # pylint: disable-msg=W0613
            """event handling text edition"""
            if event.button != 1:
                return False
            if event.type == gtk.gdk._2BUTTON_PRESS:
                self.remove (self._label)
                self._entry = gtk.Entry ()
                self._entry.set_text (self._label.get_text ())
                self._entry.show ()
                self.add (self._entry)
                sig = self._entry.connect ("focus-out-event", self._entry_to_label)
                self._entry_handler_id.append(sig)
                sig = self._entry.connect ("activate", self._on_entry_activated)
                self._entry_handler_id.append(sig)
                sig = self._entry.connect ("key-press-event",
                                             self._on_entry_keypress)
                self._entry_handler_id.append(sig)
                sig = self._entry.connect("button-press-event",
                                          self._on_entry_buttonpress)
                self._entry_handler_id.append(sig)
                self._entry.grab_focus ()
                return(True)
            return(False)

        def _entry_to_label (self, widget, event):
            # pylint: disable-msg=W0613
            """replace gtk.Entry by the gtk.Label"""
            if self._entry and self._entry in self.get_children():
                #disconnect signals to avoid segfault :s
                for sig in self._entry_handler_id:
                    if self._entry.handler_is_connected(sig):
                        self._entry.disconnect(sig)
                self._entry_handler_id = []
                self.remove (self._entry)
                self.add (self._label)
                self._entry = None
                self.show_all ()
                self.emit('edit-done')
                # Returning False will ensure that focus out event will be sent to
                # GtkEntry so it will disconnect 'state-changed' handler
                return(False)
            return(False)

        def _on_entry_activated (self, widget):
            # pylint: disable-msg=W0613
            """get the text entered in gtk.Entry"""
            entry = self._entry.get_text ()
            label = self._label.get_text ()
            if entry == '':
                self._custom = False
                self.set_text (self._autotext)
            elif entry != label:
                self._custom = True
                self._label.set_text (entry)
            self._entry_to_label (None, None)

        def _on_entry_keypress (self, widget, event):
            # pylint: disable-msg=W0613
            """handle keypressed in gtk.Entry"""
            key = gtk.gdk.keyval_name (event.keyval)
            if key == 'Escape':
                self._entry_to_label (None, None)

        def _on_entry_buttonpress (self, widget, event):
            """handle button events in gtk.Entry."""
            # Block right clicks to avoid a deadlock.
            # The correct solution here would be for _entry_to_label to trigger a
            # deferred execution handler and for that handler to check if focus is
            # in a GtkMenu. The problem being that we are unable to get a context
            # menu for the GtkEntry.
            if event.button == 3:
                return True

        def modify_fg(self, state, color):
            """Set the label foreground"""
            self._label.modify_fg(state, color)

        def is_custom(self):
            """Return whether or not we have a custom string set"""
            return(self._custom)

        def set_custom(self):
            """Set the customness of the string to True"""
            self._custom = True

        def modify_font(self, fontdesc):
            """Set the label font using a pango.FontDescription"""
            self._label.modify_font(fontdesc)

    gobject.type_register(EditableLabel)