Remove print statements
[alacarte.git] / Alacarte / MainWindow.py
blob3f157fab55017be2e898606f5b15151f87a912e3
1 # -*- coding: utf-8 -*-
2 # vim: set noexpandtab:
3 # Alacarte Menu Editor - Simple fd.o Compliant Menu Editor
4 # Copyright (C) 2006 Travis Watkins
6 # This library is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU Library General Public
8 # License as published by the Free Software Foundation; either
9 # version 2 of the License, or (at your option) any later version.
11 # This library is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # Library General Public License for more details.
16 # You should have received a copy of the GNU Library General Public
17 # License along with this library; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 from gi.repository import Gtk, GObject, Gio, GdkPixbuf, Gdk, GMenu, GLib
21 import cgi, os
22 import gettext
23 import subprocess
24 import urllib
25 import tempfile
27 from Alacarte import config
28 gettext.bindtextdomain(config.GETTEXT_PACKAGE, config.localedir)
29 gettext.textdomain(config.GETTEXT_PACKAGE)
31 _ = gettext.gettext
32 from Alacarte.MenuEditor import MenuEditor
33 from Alacarte import util
34 import sys
36 class MainWindow:
37 timer = None
38 #hack to make editing menu properties work
39 allow_update = True
40 #drag-and-drop stuff
41 dnd_items = [('ALACARTE_ITEM_ROW', Gtk.TargetFlags.SAME_APP, 0), ('text/plain', 0, 1)]
42 dnd_menus = [('ALACARTE_MENU_ROW', Gtk.TargetFlags.SAME_APP, 0)]
43 dnd_both = [dnd_items[0],] + dnd_menus
44 drag_data = None
45 edit_pool = []
47 def __init__(self, datadir, version, argv):
48 self.file_path = datadir
49 self.version = version
50 self.editor = MenuEditor()
51 Gtk.Window.set_default_icon_name('alacarte')
52 self.tree = Gtk.Builder()
53 self.tree.set_translation_domain(config.GETTEXT_PACKAGE)
54 self.tree.add_from_file(os.path.join(self.file_path, 'alacarte.ui'))
55 self.tree.connect_signals(self)
56 self.setupMenuTree()
57 self.setupItemTree()
58 self.tree.get_object('edit_delete').set_sensitive(False)
59 self.tree.get_object('edit_revert_to_original').set_sensitive(False)
60 self.tree.get_object('edit_properties').set_sensitive(False)
61 self.tree.get_object('move_up_button').set_sensitive(False)
62 self.tree.get_object('move_down_button').set_sensitive(False)
63 self.tree.get_object('new_separator_button').set_sensitive(False)
64 accelgroup = Gtk.AccelGroup()
65 keyval, modifier = Gtk.accelerator_parse('<Ctrl>Z')
66 accelgroup.connect(keyval, modifier, Gtk.AccelFlags.VISIBLE, self.on_mainwindow_undo)
67 keyval, modifier = Gtk.accelerator_parse('<Ctrl><Shift>Z')
68 accelgroup.connect(keyval, modifier, Gtk.AccelFlags.VISIBLE, self.on_mainwindow_redo)
69 keyval, modifier = Gtk.accelerator_parse('F1')
70 accelgroup.connect(keyval, modifier, Gtk.AccelFlags.VISIBLE, self.on_help_button_clicked)
71 self.tree.get_object('mainwindow').add_accel_group(accelgroup)
73 def run(self):
74 self.loadMenus()
75 self.editor.applications.tree.connect("changed", self.menuChanged)
76 self.tree.get_object('mainwindow').show_all()
77 Gtk.main()
79 def menuChanged(self, *a):
80 self.loadUpdates()
82 def loadUpdates(self):
83 self.editor.reloadMenus()
84 self.editor.applications.tree.connect("changed", self.menuChanged)
86 if not self.allow_update:
87 return False
88 menu_tree = self.tree.get_object('menu_tree')
89 item_tree = self.tree.get_object('item_tree')
90 items, iter = item_tree.get_selection().get_selected()
91 update_items = False
92 update_type = None
93 item_id = None
94 if iter:
95 update_items = True
96 if isinstance(items[iter][3], GMenu.TreeEntry):
97 item_id = items[iter][3].get_desktop_file_id()
98 update_type = GMenu.TreeItemType.ENTRY
99 elif isinstance(items[iter][3], GMenu.TreeDirectory):
100 item_id = os.path.split(items[iter][3].get_desktop_file_path())[1]
101 update_type = GMenu.TreeItemType.DIRECTORY
102 elif isinstance(items[iter][3], GMenu.Tree.Separator):
103 item_id = items.get_path(iter)
104 update_type = GMenu.TreeItemType.SEPARATOR
105 menus, iter = menu_tree.get_selection().get_selected()
106 update_menus = False
107 menu_id = None
108 if iter:
109 if menus[iter][2].get_desktop_file_path():
110 menu_id = os.path.split(menus[iter][2].get_desktop_file_path())[1]
111 else:
112 menu_id = menus[iter][2].get_menu_id()
113 update_menus = True
114 self.loadMenus()
115 #find current menu in new tree
116 if update_menus:
117 menu_tree.get_model().foreach(self.findMenu, menu_id)
118 menus, iter = menu_tree.get_selection().get_selected()
119 if iter:
120 self.on_menu_tree_cursor_changed(menu_tree)
121 #find current item in new list
122 if update_items:
123 i = 0
124 for item in item_tree.get_model():
125 found = False
126 if update_type != GMenu.TreeItemType.SEPARATOR:
127 if isinstance (item[3], GMenu.TreeEntry) and item[3].get_desktop_file_id() == item_id:
128 found = True
129 if isinstance (item[3], GMenu.TreeDirectory) and item[3].get_desktop_file_path() and update_type == GMenu.TreeItemType.DIRECTORY:
130 if os.path.split(item[3].get_desktop_file_path())[1] == item_id:
131 found = True
132 if isinstance(item[3], GMenu.TreeSeparator):
133 if not isinstance(item_id, tuple):
134 #we may not skip the increment via "continue"
135 i += 1
136 continue
137 #separators have no id, have to find them manually
138 #probably won't work with two separators together
139 if (item_id[0] - 1,) == (i,):
140 found = True
141 elif (item_id[0] + 1,) == (i,):
142 found = True
143 elif (item_id[0],) == (i,):
144 found = True
145 if found:
146 item_tree.get_selection().select_path((i,))
147 self.on_item_tree_cursor_changed(item_tree)
148 break
149 i += 1
150 return False
152 def findMenu(self, menus, path, iter, menu_id):
153 if not menus[path][2].get_desktop_file_path():
154 if menu_id == menus[path][2].get_menu_id():
155 menu_tree = self.tree.get_object('menu_tree')
156 menu_tree.expand_to_path(path)
157 menu_tree.get_selection().select_path(path)
158 return True
159 return False
160 if os.path.split(menus[path][2].get_desktop_file_path())[1] == menu_id:
161 menu_tree = self.tree.get_object('menu_tree')
162 menu_tree.expand_to_path(path)
163 menu_tree.get_selection().select_path(path)
164 return True
166 def setupMenuTree(self):
167 self.menu_store = Gtk.TreeStore(GdkPixbuf.Pixbuf, str, object)
168 menus = self.tree.get_object('menu_tree')
169 column = Gtk.TreeViewColumn(_('Name'))
170 column.set_spacing(4)
171 cell = Gtk.CellRendererPixbuf()
172 column.pack_start(cell, False)
173 column.add_attribute(cell, 'pixbuf', 0)
174 cell = Gtk.CellRendererText()
175 column.pack_start(cell, True)
176 column.add_attribute(cell, 'markup', 1)
177 menus.append_column(column)
178 menus.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK, self.dnd_menus, Gdk.DragAction.COPY)
179 menus.enable_model_drag_dest(self.dnd_both, Gdk.DragAction.PRIVATE)
180 menus.get_selection().set_mode(Gtk.SelectionMode.BROWSE)
182 def setupItemTree(self):
183 items = self.tree.get_object('item_tree')
184 column = Gtk.TreeViewColumn(_('Show'))
185 cell = Gtk.CellRendererToggle()
186 cell.connect('toggled', self.on_item_tree_show_toggled)
187 column.pack_start(cell, True)
188 column.add_attribute(cell, 'active', 0)
189 #hide toggle for separators
190 column.set_cell_data_func(cell, self._cell_data_toggle_func)
191 items.append_column(column)
192 column = Gtk.TreeViewColumn(_('Item'))
193 column.set_spacing(4)
194 cell = Gtk.CellRendererPixbuf()
195 column.pack_start(cell, False)
196 column.add_attribute(cell, 'pixbuf', 1)
197 cell = Gtk.CellRendererText()
198 column.pack_start(cell, True)
199 column.add_attribute(cell, 'markup', 2)
200 items.append_column(column)
201 self.item_store = Gtk.ListStore(bool, GdkPixbuf.Pixbuf, str, object)
202 items.set_model(self.item_store)
203 items.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK, self.dnd_items, Gdk.DragAction.COPY)
204 items.enable_model_drag_dest(self.dnd_items, Gdk.DragAction.PRIVATE)
206 def _cell_data_toggle_func(self, tree_column, renderer, model, treeiter, data=None):
207 if isinstance(model[treeiter][3], GMenu.TreeSeparator):
208 renderer.set_property('visible', False)
209 else:
210 renderer.set_property('visible', True)
212 def loadMenus(self):
213 self.menu_store.clear()
214 for menu in self.editor.getMenus():
215 iters = [None]*20
216 self.loadMenu(iters, menu)
217 menu_tree = self.tree.get_object('menu_tree')
218 menu_tree.set_model(self.menu_store)
219 for menu in self.menu_store:
220 menu_tree.expand_to_path(menu.path)
221 menu_tree.get_selection().select_path((0,))
222 self.on_menu_tree_cursor_changed(menu_tree)
224 def loadMenu(self, iters, parent, depth=0):
225 if depth == 0:
226 icon = util.getIcon(parent)
227 iters[depth] = self.menu_store.append(None, (icon, cgi.escape(parent.get_name()), parent))
228 depth += 1
229 for menu, show in self.editor.getMenus(parent):
230 if show:
231 name = cgi.escape(menu.get_name())
232 else:
233 name = '<small><i>' + cgi.escape(menu.get_name()) + '</i></small>'
234 icon = util.getIcon(menu)
235 iters[depth] = self.menu_store.append(iters[depth-1], (icon, name, menu))
236 self.loadMenu(iters, menu, depth)
237 depth -= 1
239 def loadItems(self, menu, menu_path):
240 self.item_store.clear()
241 for item, show in self.editor.getItems(menu):
242 menu_icon = None
243 if isinstance(item, GMenu.TreeSeparator):
244 name = '---'
245 icon = None
246 elif isinstance(item, GMenu.TreeEntry):
247 app_info = item.get_app_info()
248 if show:
249 name = cgi.escape(app_info.get_display_name())
250 else:
251 name = '<small><i>' + cgi.escape(app_info.get_display_name()) + '</i></small>'
252 icon = util.getIcon(item)
253 else:
254 if show:
255 name = cgi.escape(item.get_name())
256 else:
257 name = '<small><i>' + cgi.escape(item.get_name()) + '</i></small>'
258 icon = util.getIcon(item)
259 self.item_store.append((show, icon, name, item))
261 #this is a little timeout callback to insert new items after
262 #gnome-desktop-item-edit has finished running
263 def waitForNewItemProcess(self, process, parent_id, file_path):
264 if process.poll() != None:
265 if os.path.isfile(file_path):
266 self.editor.insertExternalItem(os.path.split(file_path)[1], parent_id)
267 return False
268 return True
270 def waitForNewMenuProcess(self, process, parent_id, file_path):
271 if process.poll() != None:
272 #hack for broken gnome-desktop-item-edit
273 broken_path = os.path.join(os.path.split(file_path)[0], '.directory')
274 if os.path.isfile(broken_path):
275 os.rename(broken_path, file_path)
276 if os.path.isfile(file_path):
277 self.editor.insertExternalMenu(os.path.split(file_path)[1], parent_id)
278 return False
279 return True
281 #this callback keeps you from editing the same item twice
282 def waitForEditProcess(self, process, file_path):
283 if process.poll() != None:
284 self.edit_pool.remove(file_path)
285 return False
286 return True
288 def on_new_menu_button_clicked(self, button):
289 menu_tree = self.tree.get_object('menu_tree')
290 menus, iter = menu_tree.get_selection().get_selected()
291 if not iter:
292 parent = menus[(0,)][2]
293 menu_tree.expand_to_path((0,))
294 menu_tree.get_selection().select_path((0,))
295 else:
296 parent = menus[iter][2]
297 file_path = os.path.join(util.getUserDirectoryPath(), util.getUniqueFileId('alacarte-made', '.directory'))
298 process = subprocess.Popen(['gnome-desktop-item-edit', file_path], env=os.environ)
299 GObject.timeout_add(100, self.waitForNewMenuProcess, process, parent.get_menu_id(), file_path)
301 def on_new_item_button_clicked(self, button):
302 menu_tree = self.tree.get_object('menu_tree')
303 menus, iter = menu_tree.get_selection().get_selected()
304 if not iter:
305 parent = menus[(0,)][2]
306 menu_tree.expand_to_path((0,))
307 menu_tree.get_selection().select_path((0,))
308 else:
309 parent = menus[iter][2]
310 file_path = os.path.join(util.getUserItemPath(), util.getUniqueFileId('alacarte-made', '.desktop'))
311 process = subprocess.Popen(['gnome-desktop-item-edit', file_path], env=os.environ)
312 GObject.timeout_add(100, self.waitForNewItemProcess, process, parent.get_menu_id(), file_path)
314 def on_new_separator_button_clicked(self, button):
315 item_tree = self.tree.get_object('item_tree')
316 items, iter = item_tree.get_selection().get_selected()
317 if not iter:
318 return
319 else:
320 after = items[iter][3]
321 menu_tree = self.tree.get_object('menu_tree')
322 menus, iter = menu_tree.get_selection().get_selected()
323 parent = menus[iter][2]
324 self.editor.createSeparator(parent, after=after)
326 def on_edit_delete_activate(self, menu):
327 item_tree = self.tree.get_object('item_tree')
328 items, iter = item_tree.get_selection().get_selected()
329 if not iter:
330 return
331 item = items[iter][3]
332 if isinstance(item, GMenu.TreeEntry):
333 self.editor.deleteItem(item)
334 elif isinstance(item, GMenu.TreeDirectory):
335 self.editor.deleteMenu(item)
336 elif isinstance(item, GMenu.TreeSeparator):
337 self.editor.deleteSeparator(item)
339 def on_edit_revert_to_original_activate(self, menu):
340 item_tree = self.tree.get_object('item_tree')
341 items, iter = item_tree.get_selection().get_selected()
342 if not iter:
343 return
344 item = items[iter][3]
345 if isinstance(item, GMenu.TreeEntry):
346 self.editor.revertItem(item)
347 elif isinstance(item, GMenu.TreeDirectory):
348 self.editor.revertMenu(item)
350 def on_edit_properties_activate(self, menu):
351 item_tree = self.tree.get_object('item_tree')
352 items, iter = item_tree.get_selection().get_selected()
353 if not iter:
354 return
355 item = items[iter][3]
356 if not isinstance(item, GMenu.TreeEntry) and not isinstance(item, GMenu.TreeDirectory):
357 return
359 if isinstance(item, GMenu.TreeEntry):
360 file_path = os.path.join(util.getUserItemPath(), item.get_desktop_file_id())
361 file_type = 'Item'
362 elif isinstance(item, GMenu.TreeDirectory):
363 file_path = os.path.join(util.getUserDirectoryPath(), os.path.split(item.get_desktop_file_path())[1])
364 file_type = 'Menu'
366 if not os.path.isfile(file_path):
367 data = open(item.get_desktop_file_path()).read()
368 open(file_path, 'w').write(data)
369 self.editor._MenuEditor__addUndo([(file_type, os.path.split(file_path)[1]),])
370 else:
371 self.editor._MenuEditor__addUndo([item,])
372 if file_path not in self.edit_pool:
373 self.edit_pool.append(file_path)
374 process = subprocess.Popen(['gnome-desktop-item-edit', file_path], env=os.environ)
375 GObject.timeout_add(100, self.waitForEditProcess, process, file_path)
377 def on_menu_tree_cursor_changed(self, treeview):
378 menus, iter = treeview.get_selection().get_selected()
379 menu_path = menus.get_path(iter)
380 item_tree = self.tree.get_object('item_tree')
381 item_tree.get_selection().unselect_all()
382 self.loadItems(self.menu_store[menu_path][2], menu_path)
383 self.tree.get_object('edit_delete').set_sensitive(False)
384 self.tree.get_object('edit_revert_to_original').set_sensitive(False)
385 self.tree.get_object('edit_properties').set_sensitive(False)
386 self.tree.get_object('move_up_button').set_sensitive(False)
387 self.tree.get_object('move_down_button').set_sensitive(False)
388 self.tree.get_object('new_separator_button').set_sensitive(False)
389 self.tree.get_object('properties_button').set_sensitive(False)
390 self.tree.get_object('delete_button').set_sensitive(False)
392 def on_menu_tree_drag_data_get(self, treeview, context, selection, target_id, etime):
393 menus, iter = treeview.get_selection().get_selected()
394 self.drag_data = menus[iter][2]
396 def on_menu_tree_drag_data_received(self, treeview, context, x, y, selection, info, etime):
397 menus = treeview.get_model()
398 drop_info = treeview.get_dest_row_at_pos(x, y)
399 if drop_info:
400 path, position = drop_info
401 types_before = (Gtk.TreeViewDropPosition.INTO_OR_BEFORE, Gtk.TreeViewDropPosition.INTO_OR_AFTER)
402 types_into = (Gtk.TreeViewDropPosition.INTO_OR_BEFORE, Gtk.TreeViewDropPosition.INTO_OR_AFTER)
403 types_after = (Gtk.TreeViewDropPosition.AFTER, Gtk.TreeViewDropPosition.INTO_OR_AFTER)
404 if position not in types:
405 context.finish(False, False, etime)
406 return False
407 if selection.target in ('ALACARTE_ITEM_ROW', 'ALACARTE_MENU_ROW'):
408 if self.drag_data == None:
409 return False
410 item = self.drag_data
411 new_parent = menus[path][2]
412 treeview.get_selection().select_path(path)
413 if isinstance(item, GMenu.TreeEntry):
414 self.editor.copyItem(item, new_parent)
415 elif isinstance(item, GMenu.TreeDirectory):
416 if self.editor.moveMenu(item, new_parent) == False:
417 self.loadUpdates()
418 elif isinstance(item, GMenu.TreeSeparator):
419 self.editor.moveSeparator(item, new_parent)
420 else:
421 context.finish(False, False, etime)
422 context.finish(True, True, etime)
423 self.drag_data = None
425 def on_item_tree_show_toggled(self, cell, path):
426 item = self.item_store[path][3]
427 if isinstance(item, GMenu.TreeSeparator):
428 return
429 if self.item_store[path][0]:
430 self.editor.setVisible(item, False)
431 else:
432 self.editor.setVisible(item, True)
433 self.item_store[path][0] = not self.item_store[path][0]
435 def on_item_tree_cursor_changed(self, treeview):
436 items, iter = treeview.get_selection().get_selected()
437 if iter is None:
438 return
439 item = items[iter][3]
440 self.tree.get_object('edit_delete').set_sensitive(True)
441 self.tree.get_object('new_separator_button').set_sensitive(True)
442 self.tree.get_object('delete_button').set_sensitive(True)
443 if self.editor.canRevert(item):
444 self.tree.get_object('edit_revert_to_original').set_sensitive(True)
445 else:
446 self.tree.get_object('edit_revert_to_original').set_sensitive(False)
447 if not isinstance(item, GMenu.TreeSeparator):
448 self.tree.get_object('edit_properties').set_sensitive(True)
449 self.tree.get_object('properties_button').set_sensitive(True)
450 else:
451 self.tree.get_object('edit_properties').set_sensitive(False)
452 self.tree.get_object('properties_button').set_sensitive(False)
454 # If first item...
455 if items.get_path(iter).get_indices()[0] == 0:
456 self.tree.get_object('move_up_button').set_sensitive(False)
457 else:
458 self.tree.get_object('move_up_button').set_sensitive(True)
460 # If last item...
461 if items.get_path(iter).get_indices()[0] == (len(items)-1):
462 self.tree.get_object('move_down_button').set_sensitive(False)
463 else:
464 self.tree.get_object('move_down_button').set_sensitive(True)
466 def on_item_tree_row_activated(self, treeview, path, column):
467 self.on_edit_properties_activate(None)
469 def on_item_tree_popup_menu(self, item_tree, event=None):
470 model, iter = item_tree.get_selection().get_selected()
471 if event:
472 #don't show if it's not the right mouse button
473 if event.button != 3:
474 return
475 button = event.button
476 event_time = event.time
477 info = item_tree.get_path_at_pos(int(event.x), int(event.y))
478 if info != None:
479 path, col, cellx, celly = info
480 item_tree.grab_focus()
481 item_tree.set_cursor(path, col, 0)
482 else:
483 path = model.get_path(iter)
484 button = 0
485 event_time = 0
486 item_tree.grab_focus()
487 item_tree.set_cursor(path, item_tree.get_columns()[0], 0)
488 popup = self.tree.get_object('edit_menu')
489 popup.popup(None, None, None, None, button, event_time)
490 #without this shift-f10 won't work
491 return True
493 def on_item_tree_drag_data_get(self, treeview, context, selection, target_id, etime):
494 items, iter = treeview.get_selection().get_selected()
495 self.drag_data = items[iter][3]
497 def on_item_tree_drag_data_received(self, treeview, context, x, y, selection, info, etime):
498 items = treeview.get_model()
499 types = (Gtk.TreeViewDropPosition.BEFORE, Gtk.TreeViewDropPosition.INTO_OR_BEFORE)
500 if selection.target == 'ALACARTE_ITEM_ROW':
501 drop_info = treeview.get_dest_row_at_pos(x, y)
502 before = None
503 after = None
504 if self.drag_data == None:
505 return False
506 item = self.drag_data
507 # by default we assume, that the items stays in the same menu
508 destination = item.get_parent()
509 if drop_info:
510 path, position = drop_info
511 target = items[path][3]
512 # move the item to the directory, if the item was dropped into it
513 if isinstance(target, GMenu.TreeDirectory) and (position in types_into):
514 # append the selected item to the choosen menu
515 destination = target
516 elif position in types_before:
517 before = target
518 elif position in types_after:
519 after = target
520 else:
521 # this does not happen
522 pass
523 else:
524 path = (len(items) - 1,)
525 after = items[path][3]
526 if isinstance(item, GMenu.TreeEntry):
527 self.editor.moveItem(item, destination, before, after)
528 elif isinstance(item, GMenu.TreeDirectory):
529 if self.editor.moveMenu(item, destination, before, after) == False:
530 self.loadUpdates()
531 elif isinstance(item, GMenu.TreeSeparator):
532 self.editor.moveSeparator(item, destination, before, after)
533 context.finish(True, True, etime)
534 elif selection.target == 'text/plain':
535 if selection.data == None:
536 return False
537 menus, iter = self.tree.get_object('menu_tree').get_selection().get_selected()
538 parent = menus[iter][2]
539 drop_info = treeview.get_dest_row_at_pos(x, y)
540 before = None
541 after = None
542 if drop_info:
543 path, position = drop_info
544 if position in types:
545 before = items[path][3]
546 else:
547 after = items[path][3]
548 else:
549 path = (len(items) - 1,)
550 after = items[path][3]
551 file_path = urllib.unquote(selection.data).strip()
552 if not file_path.startswith('file:'):
553 return
554 myfile = Gio.File(uri=file_path)
555 file_info = myfile.query_info(Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE)
556 content_type = file_info.get_content_type()
557 if content_type == 'application/x-desktop':
558 input_stream = myfile.read()
559 keyfile = GLib.KeyFile()
560 keyfile.load_from_data(input_stream.read())
561 self.editor.createItem(parent, before, after, KeyFile=keyfile)
562 elif content_type in ('application/x-shellscript', 'application/x-executable'):
563 self.editor.createItem(parent, before, after,
564 Name=os.path.split(file_path)[1].strip(),
565 Exec=file_path.replace('file://', '').strip(),
566 Terminal=False)
567 self.drag_data = None
569 def on_item_tree_key_press_event(self, item_tree, event):
570 if event.keyval == Gdk.KEY_Delete:
571 self.on_edit_delete_activate(item_tree)
573 def on_move_up_button_clicked(self, button):
574 item_tree = self.tree.get_object('item_tree')
575 items, iter = item_tree.get_selection().get_selected()
576 if not iter:
577 return
578 path = items.get_path(iter)
579 #at top, can't move up
580 if path.get_indices()[0] == 0:
581 return
582 item = items[path][3]
583 before = items[(path.get_indices()[0] - 1,)][3]
584 if isinstance(item, GMenu.TreeEntry):
585 self.editor.moveItem(item, item.get_parent(), before=before)
586 elif isinstance(item, GMenu.TreeDirectory):
587 self.editor.moveMenu(item, item.get_parent(), before=before)
588 elif isinstance(item, GMenu.TreeSeparator):
589 self.editor.moveSeparator(item, item.get_parent(), before=before)
591 def on_move_down_button_clicked(self, button):
592 item_tree = self.tree.get_object('item_tree')
593 items, iter = item_tree.get_selection().get_selected()
594 if not iter:
595 return
596 path = items.get_path(iter)
597 #at bottom, can't move down
598 if path.get_indices()[0] == (len(items) - 1):
599 return
600 item = items[path][3]
601 after = items[path][3]
602 if isinstance(item, GMenu.TreeEntry):
603 self.editor.moveItem(item, item.get_parent(), after=after)
604 elif isinstance(item, GMenu.TreeDirectory):
605 self.editor.moveMenu(item, item.get_parent(), after=after)
606 elif isinstance(item, GMenu.TreeSeparator):
607 self.editor.moveSeparator(item, item.get_parent(), after=after)
609 def on_mainwindow_undo(self, accelgroup, window, keyval, modifier):
610 self.editor.undo()
612 def on_mainwindow_redo(self, accelgroup, window, keyval, modifier):
613 self.editor.redo()
615 def on_help_button_clicked(self, *args):
616 Gtk.show_uri(Gdk.Screen.get_default(), "ghelp:user-guide#menu-editor", Gtk.get_current_event_time())
618 def on_revert_button_clicked(self, button):
619 dialog = self.tree.get_object('revertdialog')
620 dialog.set_transient_for(self.tree.get_object('mainwindow'))
621 dialog.show_all()
622 if dialog.run() == Gtk.ResponseType.YES:
623 self.editor.revert()
624 dialog.hide()
626 def on_close_button_clicked(self, button):
627 self.quit()
629 def on_properties_button_clicked(self, button):
630 self.on_edit_properties_activate(None)
631 def on_delete_button_clicked(self, button):
632 self.on_edit_delete_activate(None)
634 def on_style_set(self, *args):
635 self.loadUpdates()
637 def quit(self):
638 self.editor.quit()
639 Gtk.main_quit()