795ab2aeec
(occurred to me that they might look out of place in f.e. Arabic, Chinese, Cyrillic and (ironically) Greek)
320 lines
12 KiB
Python
Executable File
320 lines
12 KiB
Python
Executable File
#!/usr/bin/python
|
|
# Terminator by Chris Jones <cmsj@tenshu.net>
|
|
# GPL v2 only
|
|
"""titlebar.py - classes necessary to provide a terminal title bar"""
|
|
|
|
from gi.repository import Gtk, Gdk
|
|
from gi.repository import GObject
|
|
from gi.repository import Pango
|
|
import random
|
|
import itertools
|
|
|
|
from version import APP_NAME
|
|
from util import dbg
|
|
from terminator import Terminator
|
|
from editablelabel import EditableLabel
|
|
from translation import _
|
|
|
|
# pylint: disable-msg=R0904
|
|
# pylint: disable-msg=W0613
|
|
class Titlebar(Gtk.EventBox):
|
|
"""Class implementing the Titlebar widget"""
|
|
|
|
terminator = None
|
|
terminal = None
|
|
config = None
|
|
oldtitle = None
|
|
termtext = None
|
|
sizetext = None
|
|
label = None
|
|
ebox = None
|
|
groupicon = None
|
|
grouplabel = None
|
|
groupentry = None
|
|
bellicon = None
|
|
|
|
__gsignals__ = {
|
|
'clicked': (GObject.SignalFlags.RUN_LAST, None, ()),
|
|
'edit-done': (GObject.SignalFlags.RUN_LAST, None, ()),
|
|
'create-group': (GObject.SignalFlags.RUN_LAST, None,
|
|
(GObject.TYPE_STRING,)),
|
|
}
|
|
|
|
def __init__(self, terminal):
|
|
"""Class initialiser"""
|
|
GObject.GObject.__init__(self)
|
|
|
|
self.terminator = Terminator()
|
|
self.terminal = terminal
|
|
self.config = self.terminal.config
|
|
|
|
self.label = EditableLabel()
|
|
self.label.connect('edit-done', self.on_edit_done)
|
|
self.ebox = Gtk.EventBox()
|
|
grouphbox = Gtk.HBox()
|
|
self.grouplabel = Gtk.Label(ellipsize='end')
|
|
self.groupicon = Gtk.Image()
|
|
self.bellicon = Gtk.Image()
|
|
self.bellicon.set_no_show_all(True)
|
|
|
|
self.groupentry = Gtk.Entry()
|
|
self.groupentry.set_no_show_all(True)
|
|
self.groupentry.connect('focus-out-event', self.groupentry_cancel)
|
|
self.groupentry.connect('activate', self.groupentry_activate)
|
|
self.groupentry.connect('key-press-event', self.groupentry_keypress)
|
|
|
|
groupsend_type = self.terminator.groupsend_type
|
|
if self.terminator.groupsend == groupsend_type['all']:
|
|
icon_name = 'all'
|
|
elif self.terminator.groupsend == groupsend_type['group']:
|
|
icon_name = 'group'
|
|
elif self.terminator.groupsend == groupsend_type['off']:
|
|
icon_name = 'off'
|
|
self.set_from_icon_name('_active_broadcast_%s' % icon_name,
|
|
Gtk.IconSize.MENU)
|
|
|
|
grouphbox.pack_start(self.groupicon, False, True, 2)
|
|
grouphbox.pack_start(self.grouplabel, False, True, 2)
|
|
grouphbox.pack_start(self.groupentry, False, True, 2)
|
|
|
|
self.ebox.add(grouphbox)
|
|
self.ebox.show_all()
|
|
|
|
self.bellicon.set_from_icon_name('terminal-bell', Gtk.IconSize.MENU)
|
|
hbox = Gtk.HBox()
|
|
hbox.pack_start(self.ebox, False, True, 0)
|
|
hbox.pack_start(Gtk.VSeparator(), False, True, 0)
|
|
hbox.pack_start(self.label, True, True, 0)
|
|
hbox.pack_end(self.bellicon, False, False, 2)
|
|
|
|
viewport = Gtk.Viewport(hscroll_policy='natural')
|
|
viewport.add(hbox)
|
|
self.add (viewport)
|
|
viewport.show_all()
|
|
self.set_no_show_all(True)
|
|
self.show()
|
|
|
|
self.connect('button-press-event', self.on_clicked)
|
|
|
|
def connect_icon(self, func):
|
|
"""Connect the supplied function to clicking on the group icon"""
|
|
self.ebox.connect('button-press-event', func)
|
|
|
|
def update(self, other=None):
|
|
"""Update our contents"""
|
|
default_bg = False
|
|
if self.config['title_hide_sizetext']:
|
|
self.label.set_text("%s" % self.termtext)
|
|
else:
|
|
self.label.set_text("%s %s" % (self.termtext, self.sizetext))
|
|
|
|
if (not self.config['title_use_system_font']) and self.config['title_font']:
|
|
title_font = Pango.FontDescription(self.config['title_font'])
|
|
else:
|
|
title_font = Pango.FontDescription(self.config.get_system_prop_font())
|
|
self.label.modify_font(title_font)
|
|
self.grouplabel.modify_font(title_font)
|
|
|
|
if other:
|
|
term = self.terminal
|
|
terminator = self.terminator
|
|
if other == 'window-focus-out':
|
|
title_fg = self.config['title_inactive_fg_color']
|
|
title_bg = self.config['title_inactive_bg_color']
|
|
icon = '_receive_off'
|
|
default_bg = True
|
|
group_fg = self.config['title_inactive_fg_color']
|
|
group_bg = self.config['title_inactive_bg_color']
|
|
elif term != other and term.group and term.group == other.group:
|
|
if terminator.groupsend == terminator.groupsend_type['off']:
|
|
title_fg = self.config['title_inactive_fg_color']
|
|
title_bg = self.config['title_inactive_bg_color']
|
|
icon = '_receive_off'
|
|
default_bg = True
|
|
else:
|
|
title_fg = self.config['title_receive_fg_color']
|
|
title_bg = self.config['title_receive_bg_color']
|
|
icon = '_receive_on'
|
|
group_fg = self.config['title_receive_fg_color']
|
|
group_bg = self.config['title_receive_bg_color']
|
|
elif term != other and not term.group or term.group != other.group:
|
|
if terminator.groupsend == terminator.groupsend_type['all']:
|
|
title_fg = self.config['title_receive_fg_color']
|
|
title_bg = self.config['title_receive_bg_color']
|
|
icon = '_receive_on'
|
|
else:
|
|
title_fg = self.config['title_inactive_fg_color']
|
|
title_bg = self.config['title_inactive_bg_color']
|
|
icon = '_receive_off'
|
|
default_bg = True
|
|
group_fg = self.config['title_inactive_fg_color']
|
|
group_bg = self.config['title_inactive_bg_color']
|
|
else:
|
|
# We're the active terminal
|
|
title_fg = self.config['title_transmit_fg_color']
|
|
title_bg = self.config['title_transmit_bg_color']
|
|
if terminator.groupsend == terminator.groupsend_type['all']:
|
|
icon = '_active_broadcast_all'
|
|
elif terminator.groupsend == terminator.groupsend_type['group']:
|
|
icon = '_active_broadcast_group'
|
|
else:
|
|
icon = '_active_broadcast_off'
|
|
group_fg = self.config['title_transmit_fg_color']
|
|
group_bg = self.config['title_transmit_bg_color']
|
|
|
|
self.label.modify_fg(Gtk.StateType.NORMAL,
|
|
Gdk.color_parse(title_fg))
|
|
self.grouplabel.modify_fg(Gtk.StateType.NORMAL,
|
|
Gdk.color_parse(group_fg))
|
|
self.modify_bg(Gtk.StateType.NORMAL,
|
|
Gdk.color_parse(title_bg))
|
|
if not self.get_desired_visibility():
|
|
if default_bg == True:
|
|
color = term.get_style_context().get_background_color(Gtk.StateType.NORMAL) # VERIFY FOR GTK3
|
|
else:
|
|
color = Gdk.color_parse(title_bg)
|
|
self.update_visibility()
|
|
self.ebox.modify_bg(Gtk.StateType.NORMAL,
|
|
Gdk.color_parse(group_bg))
|
|
self.set_from_icon_name(icon, Gtk.IconSize.MENU)
|
|
|
|
def update_visibility(self):
|
|
"""Make the titlebar be visible or not"""
|
|
if not self.get_desired_visibility():
|
|
dbg('hiding titlebar')
|
|
self.hide()
|
|
self.label.hide()
|
|
else:
|
|
dbg('showing titlebar')
|
|
self.show()
|
|
self.label.show()
|
|
|
|
def get_desired_visibility(self):
|
|
"""Returns True if the titlebar is supposed to be visible. False if
|
|
not"""
|
|
if self.editing() == True or self.terminal.group:
|
|
dbg('implicit desired visibility')
|
|
return(True)
|
|
else:
|
|
dbg('configured visibility: %s' % self.config['show_titlebar'])
|
|
return(self.config['show_titlebar'])
|
|
|
|
def set_from_icon_name(self, name, size = Gtk.IconSize.MENU):
|
|
"""Set an icon for the group label"""
|
|
if not name:
|
|
self.groupicon.hide()
|
|
return
|
|
|
|
self.groupicon.set_from_icon_name(APP_NAME + name, size)
|
|
self.groupicon.show()
|
|
|
|
def update_terminal_size(self, width, height):
|
|
"""Update the displayed terminal size"""
|
|
self.sizetext = "%sx%s" % (width, height)
|
|
self.update()
|
|
|
|
def set_terminal_title(self, widget, title):
|
|
"""Update the terminal title"""
|
|
self.termtext = title
|
|
self.update()
|
|
# Return False so we don't interrupt any chains of signal handling
|
|
return False
|
|
|
|
def set_group_label(self, name):
|
|
"""Set the name of the group"""
|
|
if name:
|
|
self.grouplabel.set_text(name)
|
|
self.grouplabel.show()
|
|
else:
|
|
self.grouplabel.set_text('')
|
|
self.grouplabel.hide()
|
|
self.update_visibility()
|
|
|
|
def on_clicked(self, widget, event):
|
|
"""Handle a click on the label"""
|
|
self.show()
|
|
self.label.show()
|
|
self.emit('clicked')
|
|
|
|
def on_edit_done(self, widget):
|
|
"""Re-emit an edit-done signal from an EditableLabel"""
|
|
self.emit('edit-done')
|
|
|
|
def editing(self):
|
|
"""Determine if we're currently editing a group name or title"""
|
|
return(self.groupentry.get_property('visible') or self.label.editing())
|
|
|
|
def create_group(self):
|
|
"""Create a new group"""
|
|
if self.terminal.group:
|
|
self.groupentry.set_text(self.terminal.group)
|
|
else:
|
|
defaultmembers=[_('Alpha'),_('Beta'),_('Gamma'),_('Delta'),_('Epsilon'),_('Zeta'),_('Eta'),
|
|
_('Theta'),_('Iota'),_('Kappa'),_('Lambda'),_('Mu'),_('Nu'),_('Xi'),
|
|
_('Omicron'),_('Pi'),_('Rho'),_('Sigma'),_('Tau'),_('Upsilon'),_('Phi'),
|
|
_('Chi'),_('Psi'),_('Omega')]
|
|
currentgroups=set(self.terminator.groups)
|
|
for i in range(1,4):
|
|
defaultgroups=set(map(''.join, list(itertools.product(defaultmembers,repeat=i))))
|
|
freegroups = list(defaultgroups-currentgroups)
|
|
if freegroups:
|
|
self.groupentry.set_text(random.choice(freegroups))
|
|
break
|
|
else:
|
|
self.groupentry.set_text('')
|
|
self.groupentry.show()
|
|
self.grouplabel.hide()
|
|
self.groupentry.grab_focus()
|
|
self.update_visibility()
|
|
|
|
def groupentry_cancel(self, widget, event):
|
|
"""Hide the group name entry"""
|
|
self.groupentry.set_text('')
|
|
self.groupentry.hide()
|
|
self.grouplabel.show()
|
|
self.get_parent().grab_focus()
|
|
|
|
def groupentry_activate(self, widget):
|
|
"""Actually cause a group to be created"""
|
|
groupname = self.groupentry.get_text() or None
|
|
dbg('Titlebar::groupentry_activate: creating group: %s' % groupname)
|
|
self.groupentry_cancel(None, None)
|
|
last_focused_term=self.terminator.last_focused_term
|
|
if self.terminal.targets_for_new_group:
|
|
[term.titlebar.emit('create-group', groupname) for term in self.terminal.targets_for_new_group]
|
|
self.terminal.targets_for_new_group = None
|
|
else:
|
|
self.emit('create-group', groupname)
|
|
last_focused_term.grab_focus()
|
|
self.terminator.focus_changed(last_focused_term)
|
|
|
|
def groupentry_keypress(self, widget, event):
|
|
"""Handle keypresses on the entry widget"""
|
|
key = Gdk.keyval_name(event.keyval)
|
|
if key == 'Escape':
|
|
self.groupentry_cancel(None, None)
|
|
|
|
def icon_bell(self):
|
|
"""A bell signal requires we display our bell icon"""
|
|
self.bellicon.show()
|
|
GObject.timeout_add(1000, self.icon_bell_hide)
|
|
|
|
def icon_bell_hide(self):
|
|
"""Handle a timeout which means we now hide the bell icon"""
|
|
self.bellicon.hide()
|
|
return(False)
|
|
|
|
def get_custom_string(self):
|
|
"""If we have a custom string set, return it, otherwise None"""
|
|
if self.label.is_custom():
|
|
return(self.label.get_text())
|
|
else:
|
|
return(None)
|
|
|
|
def set_custom_string(self, string):
|
|
"""Set a custom string"""
|
|
self.label.set_text(string)
|
|
self.label.set_custom()
|
|
|
|
GObject.type_register(Titlebar)
|