terminator/terminatorlib/editablelabel.py
Haim Daniel hdaniel@redhat.com 9aab1d8643 Add support for terminal and tab edit title key binding.
Currently the only way of changing either active terminal title or active tab
title is by mouse clicking on them.

The suggested fix adds support for keybinding for each action, thus providing
a potential productivity increase from user's perspective.

The suggested default key layouts are:
* edit terminal title '<Alt>F2'.
* edit tab title '<Alt><Shift>F2'

This fixes issue: https://bugs.launchpad.net/terminator/+bug/1417747
2015-10-26 15:46:39 +02:00

168 lines
5.8 KiB
Python

#!/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 or key binding 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 edit(self):
""" Start editing the widget text """
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()
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.edit()
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)