1
from __future__ import absolute_import
2
from __future__ import division
8
from pango import FontDescription
9
from xml.sax.saxutils import escape as xml_escape
11
from guake.common import ShowableError
12
from guake.common import _
13
from guake.globals import GCONF_PATH
14
from guake.globals import GKEY
15
from guake.globals import KEY
16
from guake.globals import LKEY
19
GCONF_MONOSPACE_FONT_PATH = '/desktop/gnome/interface/monospace_font_name'
20
DCONF_MONOSPACE_FONT_PATH = 'org.gnome.desktop.interface'
21
DCONF_MONOSPACE_FONT_KEY = 'monospace-font-name'
24
class GConfHandler(object):
26
"""Handles gconf changes, if any gconf variable is changed, a
27
different method is called to handle this change.
30
def __init__(self, guake):
31
"""Constructor of GConfHandler, just add the guake dir to the
32
gconf client and bind the keys to its handler methods.
36
client = gconf.client_get_default()
37
client.add_dir(GCONF_PATH, gconf.CLIENT_PRELOAD_RECURSIVE)
39
notify_add = client.notify_add
41
# these keys does not need to be watched.
42
# notify_add(KEY('/general/default_shell'), self.shell_changed)
43
# notify_add(KEY('/general/use_login_shell'), self.login_shell_toggled)
44
# notify_add(KEY('/general/use_popup'), self.popup_toggled)
45
# notify_add(KEY('/general/window_losefocus'), self.losefocus_toggled)
46
# notify_add(KEY('/general/use_vte_titles'), self.use_vte_titles_changed)
47
# notify_add(KEY('/general/quick_open_enable'), self.on_quick_open_enable_changed)
48
# notify_add(KEY('/general/quick_open_in_current_terminal'),
49
# self.on_quick_open_in_current_terminal_changed)
51
# Notification is not required for mouse_display/display_n because
52
# set_final_window_rect polls gconf and is called whenever Guake is
55
notify_add(KEY('/general/show_resizer'), self.show_resizer_toggled)
57
notify_add(KEY('/general/use_trayicon'), self.trayicon_toggled)
58
notify_add(KEY('/general/window_ontop'), self.ontop_toggled)
59
notify_add(KEY('/general/tab_ontop'), self.tab_ontop_toggled)
60
notify_add(KEY('/general/window_tabbar'), self.tabbar_toggled)
61
notify_add(KEY('/general/window_height'), self.size_changed)
62
notify_add(KEY('/general/window_width'), self.size_changed)
63
notify_add(KEY('/general/window_height_f'), self.size_changed)
64
notify_add(KEY('/general/window_width_f'), self.size_changed)
65
notify_add(KEY('/general/window_valignment'), self.alignment_changed)
66
notify_add(KEY('/general/window_halignment'), self.alignment_changed)
67
notify_add(KEY('/style/cursor_blink_mode'), self.cursor_blink_mode_changed)
68
notify_add(KEY('/style/cursor_shape'), self.cursor_shape_changed)
70
notify_add(KEY('/general/use_scrollbar'), self.scrollbar_toggled)
71
notify_add(KEY('/general/history_size'), self.history_size_changed)
72
notify_add(KEY('/general/scroll_output'), self.keystroke_output)
73
notify_add(KEY('/general/scroll_keystroke'), self.keystroke_toggled)
75
notify_add(KEY('/general/use_default_font'), self.default_font_toggled)
76
notify_add(KEY('/general/use_palette_font_and_background_color'),
77
self.palette_font_and_background_color_toggled)
78
notify_add(KEY('/style/font/style'), self.fstyle_changed)
79
notify_add(KEY('/style/font/color'), self.fcolor_changed)
80
notify_add(KEY('/style/font/palette'), self.fpalette_changed)
81
# notify_add(KEY('/style/font/palette_name'), self.fpalette_changed)
82
notify_add(KEY('/style/background/color'), self.bgcolor_changed)
83
notify_add(KEY('/style/background/image'), self.bgimage_changed)
84
notify_add(KEY('/style/background/transparency'),
85
self.bgtransparency_changed)
87
notify_add(KEY('/general/compat_backspace'), self.backspace_changed)
88
notify_add(KEY('/general/compat_delete'), self.delete_changed)
90
def show_resizer_toggled(self, client, connection_id, entry, data):
91
"""If the gconf var show_resizer be changed, this method will
92
be called and will show/hide the resizer.
94
if entry.value.get_bool():
95
self.guake.resizer.show()
97
self.guake.resizer.hide()
99
def trayicon_toggled(self, client, connection_id, entry, data):
100
"""If the gconf var use_trayicon be changed, this method will
101
be called and will show/hide the trayicon.
103
if hasattr(self.guake.tray_icon, 'set_status'):
104
self.guake.tray_icon.set_status(entry.value.get_bool())
106
self.guake.tray_icon.set_visible(entry.value.get_bool())
108
def ontop_toggled(self, client, connection_id, entry, data):
109
"""If the gconf var window_ontop be changed, this method will
110
be called and will set the keep_above attribute in guake's
113
self.guake.window.set_keep_above(entry.value.get_bool())
115
def tab_ontop_toggled(self, client, connection_id, entry, data):
116
""" tab_ontop changed
118
self.guake.set_tab_position()
120
def tabbar_toggled(self, client, connection_id, entry, data):
121
"""If the gconf var use_tabbar be changed, this method will be
122
called and will show/hide the tabbar.
124
if entry.value.get_bool():
125
self.guake.toolbar.show()
127
self.guake.toolbar.hide()
129
def alignment_changed(self, client, connection_id, entry, data):
130
"""If the gconf var window_halignment be changed, this method will
131
be called and will call the move function in guake.
133
self.guake.set_final_window_rect()
135
def size_changed(self, client, connection_id, entry, data):
136
"""If the gconf var window_height or window_width are changed,
137
this method will be called and will call the resize function
140
self.guake.set_final_window_rect()
142
def cursor_blink_mode_changed(self, client, connection_id, entry, data):
143
"""Called when cursor blink mode settings has been changed
145
for term in self.guake.notebook.iter_terminals():
146
term.set_property("cursor-blink-mode", entry.value.get_int())
148
def cursor_shape_changed(self, client, connection_id, entry, data):
149
"""Called when the cursor shape settings has been changed
151
for term in self.guake.notebook.iter_terminals():
152
term.set_property("cursor-shape", entry.value.get_int())
154
def scrollbar_toggled(self, client, connection_id, entry, data):
155
"""If the gconf var use_scrollbar be changed, this method will
156
be called and will show/hide scrollbars of all terminals open.
158
for term in self.guake.notebook.iter_terminals():
159
# There is an hbox in each tab of the main notebook and it
160
# contains a Terminal and a Scrollbar. Since only have the
161
# Terminal here, we're going to use this to get the
162
# scrollbar and hide/show it.
163
hbox = term.get_parent()
164
terminal, scrollbar = hbox.get_children()
165
if entry.value.get_bool():
170
def history_size_changed(self, client, connection_id, entry, data):
171
"""If the gconf var history_size be changed, this method will
172
be called and will set the scrollback_lines property of all
175
for i in self.guake.notebook.iter_terminals():
176
i.set_scrollback_lines(entry.value.get_int())
178
def keystroke_output(self, client, connection_id, entry, data):
179
"""If the gconf var scroll_output be changed, this method will
180
be called and will set the scroll_on_output in all terminals
183
for i in self.guake.notebook.iter_terminals():
184
i.set_scroll_on_output(entry.value.get_bool())
186
def keystroke_toggled(self, client, connection_id, entry, data):
187
"""If the gconf var scroll_keystroke be changed, this method
188
will be called and will set the scroll_on_keystroke in all
191
for i in self.guake.notebook.iter_terminals():
192
i.set_scroll_on_keystroke(entry.value.get_bool())
194
def default_font_toggled(self, client, connection_id, entry, data):
195
"""If the gconf var use_default_font be changed, this method
196
will be called and will change the font style to the gnome
197
default or to the chosen font in style/font/style in all
201
if entry.value.get_bool():
202
# cannot directly use the Gio API since it requires to rework completely
203
# the library inclusion, remove dependencies on gobject and so on.
204
# Instead, issuing a direct command line request
205
proc = subprocess.Popen(['gsettings', 'get', DCONF_MONOSPACE_FONT_PATH,
206
DCONF_MONOSPACE_FONT_KEY], stdout=subprocess.PIPE)
207
font_name = proc.stdout.readline().replace("'", "")
208
if font_name is None:
210
font_name = client.get_string(GCONF_MONOSPACE_FONT_PATH)
212
key = KEY('/style/font/style')
213
font_name = client.get_string(key)
216
print "Error: unable to find font name !!!"
218
font = FontDescription(font_name)
221
for i in self.guake.notebook.iter_terminals():
224
def palette_font_and_background_color_toggled(self, client, connection_id, entry, data):
225
"""If the gconf var use_palette_font_and_background_color be changed, this method
226
will be called and will change the font color and the background color to the color
227
defined in the palette.
231
def fstyle_changed(self, client, connection_id, entry, data):
232
"""If the gconf var style/font/style be changed, this method
233
will be called and will change the font style in all terminals
236
font = FontDescription(entry.value.get_string())
237
for i in self.guake.notebook.iter_terminals():
240
def fcolor_changed(self, client, connection_id, entry, data):
241
"""If the gconf var style/font/color be changed, this method
242
will be called and will change the font color in all terminals
245
fgcolor = gtk.gdk.color_parse(entry.value.get_string())
246
use_palette_font_and_background_color = client.get_bool(
247
KEY('/general/use_palette_font_and_background_color'))
248
if use_palette_font_and_background_color:
250
for i in self.guake.notebook.iter_terminals():
251
i.set_color_dim(i.custom_fgcolor or fgcolor)
252
i.set_color_foreground(i.custom_fgcolor or fgcolor)
253
i.set_color_bold(i.custom_fgcolor or fgcolor)
255
def fpalette_changed(self, client, connection_id, entry, data):
256
"""If the gconf var style/font/palette be changed, this method
257
will be called and will change the color scheme in all terminals
260
fgcolor = gtk.gdk.color_parse(
261
client.get_string(KEY('/style/font/color')))
262
bgcolor = gtk.gdk.color_parse(
263
client.get_string(KEY('/style/background/color')))
264
palette = [gtk.gdk.color_parse(color) for color in
265
entry.value.get_string().split(':')]
267
use_palette_font_and_background_color = client.get_bool(
268
KEY('/general/use_palette_font_and_background_color'))
269
if use_palette_font_and_background_color and len(palette) > 16:
270
fgcolor = palette[16]
271
bgcolor = palette[17]
272
for i in self.guake.notebook.iter_terminals():
273
i.set_color_dim(fgcolor)
274
i.set_color_foreground(fgcolor)
275
i.set_color_bold(fgcolor)
276
i.set_color_background(bgcolor)
277
i.set_background_tint_color(bgcolor)
278
for i in self.guake.notebook.iter_terminals():
279
i.set_colors(fgcolor, bgcolor, palette[:16])
281
def bgcolor_changed(self, client, connection_id, entry, data):
282
"""If the gconf var style/background/color be changed, this
283
method will be called and will change the background color in
286
use_palette_font_and_background_color = client.get_bool(
287
KEY('/general/use_palette_font_and_background_color'))
288
if use_palette_font_and_background_color:
289
print "do not set background from user"
291
bgcolor = gtk.gdk.color_parse(entry.value.get_string())
292
for i in self.guake.notebook.iter_terminals():
293
i.set_color_background(i.custom_bgcolor or bgcolor)
294
i.set_background_tint_color(i.custom_bgcolor or bgcolor)
296
def bgimage_changed(self, client, connection_id, entry, data):
297
"""If the gconf var style/background/image be changed, this
298
method will be called and will change the background image and
299
will set the transparent flag to false if an image is set in
302
self.guake.set_background_image(entry.value.get_string())
304
def bgtransparency_changed(self, client, connection_id, entry, data):
305
"""If the gconf var style/background/transparency be changed, this
306
method will be called and will set the saturation and transparency
307
properties in all terminals open.
309
self.guake.set_background_transparency(entry.value.get_int())
311
def backspace_changed(self, client, connection_id, entry, data):
312
"""If the gconf var compat_backspace be changed, this method
313
will be called and will change the binding configuration in
316
for i in self.guake.notebook.iter_terminals():
317
i.set_backspace_binding(entry.value.get_string())
319
def delete_changed(self, client, connection_id, entry, data):
320
"""If the gconf var compat_delete be changed, this method
321
will be called and will change the binding configuration in
324
for i in self.guake.notebook.iter_terminals():
325
i.set_delete_binding(entry.value.get_string())
328
class GConfKeyHandler(object):
330
"""Handles changes in keyboard shortcuts.
333
def __init__(self, guake):
334
"""Constructor of Keyboard, only receives the guake instance
335
to be used in internal methods.
338
self.accel_group = None # see reload_accelerators
339
self.client = gconf.client_get_default()
341
notify_add = self.client.notify_add
342
notify_add(GKEY('show_hide'), self.reload_globals)
344
keys = ['toggle_fullscreen', 'new_tab', 'close_tab', 'rename_current_tab',
345
'previous_tab', 'next_tab', 'clipboard_copy', 'clipboard_paste',
346
'quit', 'zoom_in', 'zoom_out', 'increase_height', 'decrease_height',
347
'increase_transparency', 'decrease_transparency',
348
"search_on_web", 'move_tab_left', 'move_tab_right',
349
'switch_tab1', 'switch_tab2', 'switch_tab3', 'switch_tab4', 'switch_tab5',
350
'switch_tab6', 'switch_tab7', 'switch_tab8', 'switch_tab9', 'switch_tab10'
353
notify_add(LKEY(key), self.reload_accelerators)
354
self.client.notify(LKEY(key))
356
def reload_globals(self, client, connection_id, entry, data):
357
"""Unbind all global hotkeys and rebind the show_hide
358
method. If more global hotkeys should be added, just connect
359
the gconf key to the watch system and add.
361
self.guake.hotkeys.unbind_all()
362
key = entry.get_value().get_string()
363
if not self.guake.hotkeys.bind(key, self.guake.show_hide):
364
raise ShowableError(_('key binding error'),
365
_('Unable to bind global <b>%s</b> key') % xml_escape(key),
368
def reload_accelerators(self, *args):
369
"""Reassign an accel_group to guake main window and guake
370
context menu and calls the load_accelerators method.
373
self.guake.window.remove_accel_group(self.accel_group)
374
self.accel_group = gtk.AccelGroup()
375
self.guake.window.add_accel_group(self.accel_group)
376
self.guake.context_menu.set_accel_group(self.accel_group)
377
self.load_accelerators()
379
def load_accelerators(self):
380
"""Reads all gconf paths under /apps/guake/keybindings/local
381
and adds to the main accel_group.
383
gets = lambda x: self.client.get_string(LKEY(x))
384
key, mask = gtk.accelerator_parse(gets('quit'))
386
self.accel_group.connect_group(key, mask, gtk.ACCEL_VISIBLE,
387
self.guake.accel_quit)
389
key, mask = gtk.accelerator_parse(gets('new_tab'))
391
self.accel_group.connect_group(key, mask, gtk.ACCEL_VISIBLE,
392
self.guake.accel_add)
394
key, mask = gtk.accelerator_parse(gets('close_tab'))
396
self.accel_group.connect_group(
397
key, mask, gtk.ACCEL_VISIBLE,
398
self.guake.close_tab)
400
key, mask = gtk.accelerator_parse(gets('previous_tab'))
402
self.accel_group.connect_group(key, mask, gtk.ACCEL_VISIBLE,
403
self.guake.accel_prev)
405
key, mask = gtk.accelerator_parse(gets('next_tab'))
407
self.accel_group.connect_group(key, mask, gtk.ACCEL_VISIBLE,
408
self.guake.accel_next)
410
key, mask = gtk.accelerator_parse(gets('move_tab_left'))
412
self.accel_group.connect_group(key, mask, gtk.ACCEL_VISIBLE,
413
self.guake.accel_move_tab_left)
415
key, mask = gtk.accelerator_parse(gets('move_tab_right'))
417
self.accel_group.connect_group(key, mask, gtk.ACCEL_VISIBLE,
418
self.guake.accel_move_tab_right)
420
key, mask = gtk.accelerator_parse(gets('rename_current_tab'))
422
self.accel_group.connect_group(key, mask, gtk.ACCEL_VISIBLE,
423
self.guake.accel_rename_current_tab)
425
key, mask = gtk.accelerator_parse(gets('clipboard_copy'))
427
self.accel_group.connect_group(key, mask, gtk.ACCEL_VISIBLE,
428
self.guake.accel_copy_clipboard)
430
key, mask = gtk.accelerator_parse(gets('clipboard_paste'))
432
self.accel_group.connect_group(key, mask, gtk.ACCEL_VISIBLE,
433
self.guake.accel_paste_clipboard)
435
key, mask = gtk.accelerator_parse(gets('toggle_fullscreen'))
437
self.accel_group.connect_group(key, mask, gtk.ACCEL_VISIBLE,
438
self.guake.accel_toggle_fullscreen)
440
key, mask = gtk.accelerator_parse(gets('toggle_hide_on_lose_focus'))
442
self.accel_group.connect_group(key, mask, gtk.ACCEL_VISIBLE,
443
self.guake.accel_toggle_hide_on_lose_focus)
445
key, mask = gtk.accelerator_parse(gets('zoom_in'))
447
self.accel_group.connect_group(key, mask, gtk.ACCEL_VISIBLE,
448
self.guake.accel_zoom_in)
450
key, mask = gtk.accelerator_parse(gets('zoom_in_alt'))
452
self.accel_group.connect_group(key, mask, gtk.ACCEL_VISIBLE,
453
self.guake.accel_zoom_in)
455
key, mask = gtk.accelerator_parse(gets('zoom_out'))
457
self.accel_group.connect_group(key, mask, gtk.ACCEL_VISIBLE,
458
self.guake.accel_zoom_out)
460
key, mask = gtk.accelerator_parse(gets('increase_height'))
462
self.accel_group.connect_group(key, mask, gtk.ACCEL_VISIBLE,
463
self.guake.accel_increase_height)
465
key, mask = gtk.accelerator_parse(gets('decrease_height'))
467
self.accel_group.connect_group(key, mask, gtk.ACCEL_VISIBLE,
468
self.guake.accel_decrease_height)
470
key, mask = gtk.accelerator_parse(gets('increase_transparency'))
472
self.accel_group.connect_group(key, mask, gtk.ACCEL_VISIBLE,
473
self.guake.accel_increase_transparency)
475
key, mask = gtk.accelerator_parse(gets('decrease_transparency'))
477
self.accel_group.connect_group(key, mask, gtk.ACCEL_VISIBLE,
478
self.guake.accel_decrease_transparency)
480
for tab in xrange(1, 11):
481
key, mask = gtk.accelerator_parse(gets('switch_tab%d' % tab))
483
self.accel_group.connect_group(key, mask, gtk.ACCEL_VISIBLE,
484
self.guake.gen_accel_switch_tabN(tab - 1))
487
key, mask = gtk.accelerator_parse(gets('search_on_web'))
489
self.accel_group.connect_group(key, mask, gtk.ACCEL_VISIBLE,
490
self.guake.search_on_web)
491
except Exception as e:
492
print "Exception occured: %s" % (str(e,))