summaryrefslogtreecommitdiff
path: root/Mozo/MainWindow.py
diff options
context:
space:
mode:
Diffstat (limited to 'Mozo/MainWindow.py')
-rw-r--r--Mozo/MainWindow.py1228
1 files changed, 614 insertions, 614 deletions
diff --git a/Mozo/MainWindow.py b/Mozo/MainWindow.py
index 63231df..75533fa 100644
--- a/Mozo/MainWindow.py
+++ b/Mozo/MainWindow.py
@@ -29,623 +29,623 @@ import subprocess
import shutil
import urllib
try:
- from Mozo import config
- gettext.bindtextdomain(config.GETTEXT_PACKAGE,config.localedir)
- gettext.textdomain(config.GETTEXT_PACKAGE)
- GETTEXT_PACKAGE = config.GETTEXT_PACKAGE
+ from Mozo import config
+ gettext.bindtextdomain(config.GETTEXT_PACKAGE,config.localedir)
+ gettext.textdomain(config.GETTEXT_PACKAGE)
+ GETTEXT_PACKAGE = config.GETTEXT_PACKAGE
except:
- GETTEXT_PACKAGE = "mozo"
+ GETTEXT_PACKAGE = "mozo"
_ = gettext.gettext
from Mozo.MenuEditor import MenuEditor
from Mozo import util
class MainWindow:
- timer = None
- #hack to make editing menu properties work
- allow_update = True
- #drag-and-drop stuff
- dnd_items = [('MOZO_ITEM_ROW', Gtk.TargetFlags.SAME_APP, 0), ('text/plain', 0, 1)]
- dnd_menus = [('MOZO_MENU_ROW', Gtk.TargetFlags.SAME_APP, 0)]
- dnd_both = [dnd_items[0],] + dnd_menus
- drag_data = None
- edit_pool = []
-
- def __init__(self, datadir, version, argv):
- self.file_path = datadir
- self.version = version
- self.editor = MenuEditor()
- Gtk.Window.set_default_icon_name('mozo')
- self.tree = Gtk.Builder()
- self.tree.set_translation_domain(GETTEXT_PACKAGE)
- self.tree.add_from_file(os.path.join(self.file_path, 'mozo.ui'))
- self.tree.connect_signals(self)
- self.setupMenuTree()
- self.setupItemTree()
- self.tree.get_object('edit_delete').set_sensitive(False)
- self.tree.get_object('edit_revert_to_original').set_sensitive(False)
- self.tree.get_object('edit_properties').set_sensitive(False)
- self.tree.get_object('move_up_button').set_sensitive(False)
- self.tree.get_object('move_down_button').set_sensitive(False)
- self.tree.get_object('new_separator_button').set_sensitive(False)
- self.tree.get_object('properties_button').set_sensitive(False)
- self.tree.get_object('delete_button').set_sensitive(False)
- accelgroup = Gtk.AccelGroup()
- keyval, modifier = Gtk.accelerator_parse('<Ctrl>Z')
- accelgroup.connect(keyval, modifier, Gtk.AccelFlags.VISIBLE, self.on_mainwindow_undo)
- keyval, modifier = Gtk.accelerator_parse('<Ctrl><Shift>Z')
- accelgroup.connect(keyval, modifier, Gtk.AccelFlags.VISIBLE, self.on_mainwindow_redo)
- keyval, modifier = Gtk.accelerator_parse('F1')
- accelgroup.connect(keyval, modifier, Gtk.AccelFlags.VISIBLE, self.on_help_button_clicked)
- self.tree.get_object('mainwindow').add_accel_group(accelgroup)
-
- def run(self):
- self.loadMenus()
- self.editor.applications.tree.add_monitor(self.menuChanged, None)
- self.editor.settings.tree.add_monitor(self.menuChanged, None)
- self.tree.get_object('mainwindow').show_all()
- Gtk.main()
-
- def menuChanged(self, *a):
- if self.timer:
- GLib.Source.remove(self.timer)
- self.timer = None
- self.timer = GLib.timeout_add(3, self.loadUpdates)
-
- def loadUpdates(self):
- if not self.allow_update:
- self.timer = None
- return False
- menu_tree = self.tree.get_object('menu_tree')
- item_tree = self.tree.get_object('item_tree')
- items, iter = item_tree.get_selection().get_selected()
- update_items = False
- item_id, separator_path = None, None
- if iter:
- update_items = True
- if items[iter][3].get_type() == matemenu.TYPE_DIRECTORY:
- item_id = os.path.split(items[iter][3].get_desktop_file_path())[1]
- update_items = True
- elif items[iter][3].get_type() == matemenu.TYPE_ENTRY:
- item_id = items[iter][3].get_desktop_file_id()
- update_items = True
- elif items[iter][3].get_type() == matemenu.TYPE_SEPARATOR:
- item_id = items.get_path(iter).to_string()
- update_items = True
- menus, iter = menu_tree.get_selection().get_selected()
- update_menus = False
- menu_id = None
- if iter:
- if menus[iter][2].get_desktop_file_path():
- menu_id = os.path.split(menus[iter][2].get_desktop_file_path())[1]
- else:
- menu_id = menus[iter][2].get_menu_id()
- update_menus = True
- self.loadMenus()
- #find current menu in new tree
- if update_menus:
- menu_tree.get_model().foreach(self.findMenu, menu_id)
- menus, iter = menu_tree.get_selection().get_selected()
- if iter:
- self.on_menu_tree_cursor_changed(menu_tree)
- #find current item in new list
- if update_items:
- i = 0
- for item in item_tree.get_model():
- found = False
- if item[3].get_type() == matemenu.TYPE_ENTRY and item[3].get_desktop_file_id() == item_id:
- found = True
- if item[3].get_type() == matemenu.TYPE_DIRECTORY and item[3].get_desktop_file_path():
- if os.path.split(item[3].get_desktop_file_path())[1] == item_id:
- found = True
- if item[3].get_type() == matemenu.TYPE_SEPARATOR:
- if not isinstance(item_id, tuple):
- #we may not skip the increment via "continue"
- i += 1
- continue
- #separators have no id, have to find them manually
- #probably won't work with two separators together
- if (item_id[0] - 1,) == (i,):
- found = True
- elif (item_id[0] + 1,) == (i,):
- found = True
- elif (item_id[0],) == (i,):
- found = True
- if found:
- item_tree.get_selection().select_path((i,))
- self.on_item_tree_cursor_changed(item_tree)
- break
- i += 1
- self.timer = None
- return False
-
- def findMenu(self, menus, path, iter, menu_id):
- if not menus[path][2].get_desktop_file_path():
- if menu_id == menus[path][2].get_menu_id():
- menu_tree = self.tree.get_object('menu_tree')
- menu_tree.expand_to_path(path)
- menu_tree.get_selection().select_path(path)
- return True
- return False
- if os.path.split(menus[path][2].get_desktop_file_path())[1] == menu_id:
- menu_tree = self.tree.get_object('menu_tree')
- menu_tree.expand_to_path(path)
- menu_tree.get_selection().select_path(path)
- return True
-
- def setupMenuTree(self):
- self.menu_store = Gtk.TreeStore(GdkPixbuf.Pixbuf, str, object)
- menus = self.tree.get_object('menu_tree')
- column = Gtk.TreeViewColumn(_('Name'))
- column.set_spacing(4)
- cell = Gtk.CellRendererPixbuf()
- column.pack_start(cell, False)
- column.set_attributes(cell, pixbuf=0)
- cell = Gtk.CellRendererText()
- cell.set_fixed_size(-1, 25)
- column.pack_start(cell, True)
- column.set_attributes(cell, markup=1)
- column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
- menus.append_column(column)
- menus.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK, self.dnd_menus, Gdk.DragAction.COPY)
- menus.enable_model_drag_dest(self.dnd_both, Gdk.DragAction.PRIVATE)
-
- def setupItemTree(self):
- items = self.tree.get_object('item_tree')
- column = Gtk.TreeViewColumn(_('Show'))
- cell = Gtk.CellRendererToggle()
- cell.connect('toggled', self.on_item_tree_show_toggled)
- column.pack_start(cell, True)
- column.set_attributes(cell, active=0)
- #hide toggle for separators
- column.set_cell_data_func(cell, self._cell_data_toggle_func)
- items.append_column(column)
- column = Gtk.TreeViewColumn(_('Item'))
- column.set_spacing(4)
- cell = Gtk.CellRendererPixbuf()
- column.pack_start(cell, False)
- column.set_attributes(cell, pixbuf=1)
- cell = Gtk.CellRendererText()
- cell.set_fixed_size(-1, 25)
- column.pack_start(cell, True)
- column.set_attributes(cell, markup=2)
- items.append_column(column)
- self.item_store = Gtk.ListStore(bool, GdkPixbuf.Pixbuf, str, object)
- items.set_model(self.item_store)
- items.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK, self.dnd_items, Gdk.DragAction.COPY)
- items.enable_model_drag_dest(self.dnd_items, Gdk.DragAction.PRIVATE)
-
- def _cell_data_toggle_func(self, tree_column, renderer, model, treeiter, data=None):
- if model[treeiter][3].get_type() == matemenu.TYPE_SEPARATOR:
- renderer.set_property('visible', False)
- else:
- renderer.set_property('visible', True)
-
- def loadMenus(self):
- self.menu_store.clear()
- for menu in self.editor.getMenus():
- iters = [None]*20
- self.loadMenu(iters, menu)
- menu_tree = self.tree.get_object('menu_tree')
- menu_tree.set_model(self.menu_store)
- for menu in self.menu_store:
- #this might not work for some reason
- try:
- menu_tree.expand_to_path(menu.path)
- except:
- pass
- menu_tree.get_selection().select_path((0,))
- self.on_menu_tree_cursor_changed(menu_tree)
-
- def loadMenu(self, iters, parent, depth=0):
- if depth == 0:
- icon = util.getIcon(parent)
- iters[depth] = self.menu_store.append(None, (icon, cgi.escape(parent.get_name()), parent))
- depth += 1
- for menu, show in self.editor.getMenus(parent):
- if show:
- name = cgi.escape(menu.get_name())
- else:
- name = '<small><i>' + cgi.escape(menu.get_name()) + '</i></small>'
- icon = util.getIcon(menu)
- iters[depth] = self.menu_store.append(iters[depth-1], (icon, name, menu))
- self.loadMenu(iters, menu, depth)
- depth -= 1
-
- def loadItems(self, menu, menu_path):
- self.item_store.clear()
- for item, show in self.editor.getItems(menu):
- menu_icon = None
- if item.get_type() == matemenu.TYPE_SEPARATOR:
- name = '---'
- icon = None
- elif item.get_type() == matemenu.TYPE_ENTRY:
- if show:
- name = cgi.escape(item.get_display_name())
- else:
- name = '<small><i>' + cgi.escape(item.get_display_name()) + '</i></small>'
- icon = util.getIcon(item)
- else:
- if show:
- name = cgi.escape(item.get_name())
- else:
- name = '<small><i>' + cgi.escape(item.get_name()) + '</i></small>'
- icon = util.getIcon(item)
- self.item_store.append((show, icon, name, item))
-
- #this is a little timeout callback to insert new items after
- #mate-desktop-item-edit has finished running
- def waitForNewItemProcess(self, process, parent_id, file_path):
- if process.poll() is not None:
- if os.path.isfile(file_path):
- self.editor.insertExternalItem(os.path.split(file_path)[1], parent_id)
- return False
- return True
-
- def waitForNewMenuProcess(self, process, parent_id, file_path):
- if process.poll() is not None:
- #hack for broken mate-desktop-item-edit
- broken_path = os.path.join(os.path.split(file_path)[0], '.directory')
- if os.path.isfile(broken_path):
- os.rename(broken_path, file_path)
- if os.path.isfile(file_path):
- self.editor.insertExternalMenu(os.path.split(file_path)[1], parent_id)
- return False
- return True
-
- #this callback keeps you from editing the same item twice
- def waitForEditProcess(self, process, file_path):
- if process.poll() is not None:
- self.edit_pool.remove(file_path)
- return False
- return True
-
- def on_delete_event(self, widget, event):
- self.quit()
-
- def on_new_menu_button_clicked(self, button):
- menu_tree = self.tree.get_object('menu_tree')
- menus, iter = menu_tree.get_selection().get_selected()
- if not iter:
- parent = menus[(0,)][2]
- menu_tree.expand_to_path((0,))
- menu_tree.get_selection().select_path((0,))
- else:
- parent = menus[iter][2]
- file_path = os.path.join(util.getUserDirectoryPath(), util.getUniqueFileId('mozo-made', '.directory'))
- process = subprocess.Popen(['mate-desktop-item-edit', file_path], env=os.environ)
- GLib.timeout_add(100, self.waitForNewMenuProcess, process, parent.menu_id, file_path)
-
- def on_new_item_button_clicked(self, button):
- menu_tree = self.tree.get_object('menu_tree')
- menus, iter = menu_tree.get_selection().get_selected()
- if not iter:
- parent = menus[(0,)][2]
- menu_tree.expand_to_path((0,))
- menu_tree.get_selection().select_path((0,))
- else:
- parent = menus[iter][2]
- file_path = os.path.join(util.getUserItemPath(), util.getUniqueFileId('mozo-made', '.desktop'))
- process = subprocess.Popen(['mate-desktop-item-edit', file_path], env=os.environ)
- GLib.timeout_add(100, self.waitForNewItemProcess, process, parent.menu_id, file_path)
-
- def on_new_separator_button_clicked(self, button):
- item_tree = self.tree.get_object('item_tree')
- items, iter = item_tree.get_selection().get_selected()
- if not iter:
- return
- else:
- after = items[iter][3]
- menu_tree = self.tree.get_object('menu_tree')
- menus, iter = menu_tree.get_selection().get_selected()
- parent = menus[iter][2]
- self.editor.createSeparator(parent, after=after)
-
- def on_edit_delete_activate(self, menu):
- item_tree = self.tree.get_object('item_tree')
- items, iter = item_tree.get_selection().get_selected()
- if not iter:
- return
- item = items[iter][3]
- if item.get_type() == matemenu.TYPE_ENTRY:
- self.editor.deleteItem(item)
- elif item.get_type() == matemenu.TYPE_DIRECTORY:
- self.editor.deleteMenu(item)
- elif item.get_type() == matemenu.TYPE_SEPARATOR:
- self.editor.deleteSeparator(item)
-
- def on_edit_revert_to_original_activate(self, menu):
- item_tree = self.tree.get_object('item_tree')
- items, iter = item_tree.get_selection().get_selected()
- if not iter:
- return
- item = items[iter][3]
- if item.get_type() == matemenu.TYPE_ENTRY:
- self.editor.revertItem(item)
- elif item.get_type() == matemenu.TYPE_DIRECTORY:
- self.editor.revertMenu(item)
-
- def on_edit_properties_activate(self, menu):
- item_tree = self.tree.get_object('item_tree')
- items, iter = item_tree.get_selection().get_selected()
- if not iter:
- return
- item = items[iter][3]
- if item.get_type() not in (matemenu.TYPE_ENTRY, matemenu.TYPE_DIRECTORY):
- return
-
- if item.get_type() == matemenu.TYPE_ENTRY:
- file_path = os.path.join(util.getUserItemPath(), item.get_desktop_file_id())
- file_type = 'Item'
- elif item.get_type() == matemenu.TYPE_DIRECTORY:
- file_path = os.path.join(util.getUserDirectoryPath(), os.path.split(item.get_desktop_file_path())[1])
- file_type = 'Menu'
-
- if not os.path.isfile(file_path):
- shutil.copy(item.get_desktop_file_path(), file_path)
- self.editor._MenuEditor__addUndo([(file_type, os.path.split(file_path)[1]),])
- else:
- self.editor._MenuEditor__addUndo([item,])
- if file_path not in self.edit_pool:
- self.edit_pool.append(file_path)
- process = subprocess.Popen(['mate-desktop-item-edit', file_path], env=os.environ)
- GLib.timeout_add(100, self.waitForEditProcess, process, file_path)
-
- def on_menu_tree_cursor_changed(self, treeview):
- menus, iter = treeview.get_selection().get_selected()
- if iter is None:
- return
- menu_path = menus.get_path(iter)
- item_tree = self.tree.get_object('item_tree')
- item_tree.get_selection().unselect_all()
- self.loadItems(self.menu_store[menu_path][2], menu_path)
- self.tree.get_object('edit_delete').set_sensitive(False)
- self.tree.get_object('edit_revert_to_original').set_sensitive(False)
- self.tree.get_object('edit_properties').set_sensitive(False)
- self.tree.get_object('move_up_button').set_sensitive(False)
- self.tree.get_object('move_down_button').set_sensitive(False)
- self.tree.get_object('new_separator_button').set_sensitive(False)
-
- def on_menu_tree_drag_data_get(self, treeview, context, selection, target_id, etime):
- menus, iter = treeview.get_selection().get_selected()
- self.drag_data = menus[iter][2]
-
- def on_menu_tree_drag_data_received(self, treeview, context, x, y, selection, info, etime):
- menus = treeview.get_model()
- drop_info = treeview.get_dest_row_at_pos(x, y)
- if drop_info:
- path, position = drop_info
- types = (Gtk.TreeViewDropPosition.INTO_OR_BEFORE, Gtk.TreeViewDropPosition.INTO_OR_AFTER)
- if position not in types:
- context.finish(False, False, etime)
- return False
- if str(selection.get_target()) in ('MOZO_ITEM_ROW', 'MOZO_MENU_ROW'):
- if self.drag_data is None:
- return False
- item = self.drag_data
- new_parent = menus[path][2]
- if item.get_type() == matemenu.TYPE_ENTRY:
- self.editor.copyItem(item, new_parent)
- elif item.get_type() == matemenu.TYPE_DIRECTORY:
- if not self.editor.moveMenu(item, new_parent):
- self.loadUpdates()
- elif item.get_type() == matemenu.TYPE_SEPARATOR:
- self.editor.moveSeparator(item, new_parent)
- else:
- context.finish(False, False, etime)
- context.finish(True, True, etime)
- self.drag_data = None
-
- def on_item_tree_show_toggled(self, cell, path):
- item = self.item_store[path][3]
- if item.get_type() == matemenu.TYPE_SEPARATOR:
- return
- if self.item_store[path][0]:
- self.editor.setVisible(item, False)
- else:
- self.editor.setVisible(item, True)
- self.item_store[path][0] = not self.item_store[path][0]
-
- def on_item_tree_cursor_changed(self, treeview):
- items, iter = treeview.get_selection().get_selected()
- if iter is None:
- return
-
- item = items[iter][3]
- self.tree.get_object('edit_delete').set_sensitive(True)
- self.tree.get_object('new_separator_button').set_sensitive(True)
- self.tree.get_object('delete_button').set_sensitive(True)
-
- can_revert = self.editor.canRevert(item)
- self.tree.get_object('edit_revert_to_original').set_sensitive(can_revert)
-
- can_edit = not item.get_type() == matemenu.TYPE_SEPARATOR
- self.tree.get_object('edit_properties').set_sensitive(can_edit)
- self.tree.get_object('properties_button').set_sensitive(can_edit)
-
- index = items.get_path(iter).get_indices()[0]
- can_go_up = index > 0
- can_go_down = index < len(items) - 1
- self.tree.get_object('move_up_button').set_sensitive(can_go_up)
- self.tree.get_object('move_down_button').set_sensitive(can_go_down)
-
- def on_item_tree_row_activated(self, treeview, path, column):
- self.on_edit_properties_activate(None)
-
- def on_item_tree_popup_menu(self, item_tree, event=None):
- model, iter = item_tree.get_selection().get_selected()
- if event:
- #don't show if it's not the right mouse button
- if event.button != 3:
- return
- button = event.button
- event_time = event.time
- info = item_tree.get_path_at_pos(int(event.x), int(event.y))
- if info is not None:
- path, col, cellx, celly = info
- item_tree.grab_focus()
- item_tree.set_cursor(path, col, 0)
- else:
- path = model.get_path(iter)
- button = 0
- event_time = 0
- item_tree.grab_focus()
- item_tree.set_cursor(path, item_tree.get_columns()[0], 0)
- popup = self.tree.get_object('edit_menu')
- popup.popup(None, None, None, None, button, event_time)
- #without this shift-f10 won't work
- return True
-
- def on_item_tree_drag_data_get(self, treeview, context, selection, target_id, etime):
- items, iter = treeview.get_selection().get_selected()
- self.drag_data = items[iter][3]
-
- def on_item_tree_drag_data_received(self, treeview, context, x, y, selection, info, etime):
- items = treeview.get_model()
- types_before = (Gtk.TreeViewDropPosition.BEFORE, Gtk.TreeViewDropPosition.INTO_OR_BEFORE)
- types_into = (Gtk.TreeViewDropPosition.INTO_OR_BEFORE, Gtk.TreeViewDropPosition.INTO_OR_AFTER)
- types_after = (Gtk.TreeViewDropPosition.AFTER, Gtk.TreeViewDropPosition.INTO_OR_AFTER)
- if str(selection.get_target()) == 'MOZO_ITEM_ROW':
- drop_info = treeview.get_dest_row_at_pos(x, y)
- before = None
- after = None
- if self.drag_data is None:
- return False
- item = self.drag_data
- # by default we assume, that the items stays in the same menu
- destination = item.get_parent()
- if drop_info:
- path, position = drop_info
- target = items[path][3]
- # move the item to the directory, if the item was dropped into it
- if (target.get_type() == matemenu.TYPE_DIRECTORY) and (position in types_into):
- # append the selected item to the choosen menu
- destination = target
- elif position in types_before:
- before = target
- elif position in types_after:
- after = target
- else:
- # this does not happen
- pass
- else:
- path = (len(items) - 1,)
- after = items[path][3]
- if item.get_type() == matemenu.TYPE_ENTRY:
- self.editor.moveItem(item, destination, before, after)
- elif item.get_type() == matemenu.TYPE_DIRECTORY:
- if not self.editor.moveMenu(item, destination, before, after):
- self.loadUpdates()
- elif item.get_type() == matemenu.TYPE_SEPARATOR:
- self.editor.moveSeparator(item, destination, before, after)
- context.finish(True, True, etime)
- elif str(selection.get_target()) == 'text/plain':
- if selection.data is None:
- return False
- menus, iter = self.tree.get_object('menu_tree').get_selection().get_selected()
- parent = menus[iter][2]
- drop_info = treeview.get_dest_row_at_pos(x, y)
- before = None
- after = None
- if drop_info:
- path, position = drop_info
- if position in types_before:
- before = items[path][3]
- else:
- after = items[path][3]
- else:
- path = (len(items) - 1,)
- after = items[path][3]
- file_path = urllib.unquote(selection.data).strip()
- if not file_path.startswith('file:'):
- return
- myfile = Gio.File(uri=file_path)
- file_info = myfile.query_info(Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE)
- content_type = file_info.get_content_type()
- if content_type == 'application/x-desktop':
- input_stream = myfile.read()
- keyfile = GLib.KeyFile()
- keyfile.load_from_data(input_stream.read())
- self.editor.createItem(parent, before, after, KeyFile=keyfile)
- elif content_type in ('application/x-shellscript', 'application/x-executable'):
- self.editor.createItem(parent, before, after,
- Name=os.path.split(file_path)[1].strip(),
- Exec=file_path.replace('file://', '').strip(),
- Terminal=False)
- self.drag_data = None
-
- def on_item_tree_key_press_event(self, item_tree, event):
- if event.keyval == Gdk.KEY_Delete:
- self.on_edit_delete_activate(item_tree)
-
- def on_move_up_button_clicked(self, button):
- item_tree = self.tree.get_object('item_tree')
- items, iter = item_tree.get_selection().get_selected()
- if not iter:
- return
- path = items.get_path(iter)
- #at top, can't move up
- if path.get_indices()[0] == 0:
- return
- item = items[path][3]
- before = items[(path[0] - 1,)][3]
- if item.get_type() == matemenu.TYPE_ENTRY:
- self.editor.moveItem(item, item.get_parent(), before=before)
- elif item.get_type() == matemenu.TYPE_DIRECTORY:
- self.editor.moveMenu(item, item.get_parent(), before=before)
- elif item.get_type() == matemenu.TYPE_SEPARATOR:
- self.editor.moveSeparator(item, item.get_parent(), before=before)
-
- def on_move_down_button_clicked(self, button):
- item_tree = self.tree.get_object('item_tree')
- items, iter = item_tree.get_selection().get_selected()
- if not iter:
- return
- path = items.get_path(iter)
- #at bottom, can't move down
- if path.get_indices()[0] == (len(items) - 1):
- return
- item = items[path][3]
- after = items[path][3]
- if item.get_type() == matemenu.TYPE_ENTRY:
- self.editor.moveItem(item, item.get_parent(), after=after)
- elif item.get_type() == matemenu.TYPE_DIRECTORY:
- self.editor.moveMenu(item, item.get_parent(), after=after)
- elif item.get_type() == matemenu.TYPE_SEPARATOR:
- self.editor.moveSeparator(item, item.get_parent(), after=after)
-
- def on_mainwindow_undo(self, accelgroup, window, keyval, modifier):
- self.editor.undo()
-
- def on_mainwindow_redo(self, accelgroup, window, keyval, modifier):
- self.editor.redo()
-
- def on_help_button_clicked(self, *args):
- Gtk.show_uri(Gdk.Screen.get_default(), "help:mate-user-guide/menu-editor", Gtk.get_current_event_time())
-
- def on_revert_button_clicked(self, button):
- dialog = self.tree.get_object('revertdialog')
- dialog.set_transient_for(self.tree.get_object('mainwindow'))
- dialog.show_all()
- if dialog.run() == Gtk.ResponseType.YES:
- self.editor.revert()
- dialog.hide()
-
- def on_close_button_clicked(self, button):
- try:
- self.tree.get_object('mainwindow').hide()
- except:
- pass
- GLib.timeout_add(10, self.quit)
-
- def on_properties_button_clicked(self, button):
- self.on_edit_properties_activate(None)
-
- def on_delete_button_clicked(self, button):
- self.on_edit_delete_activate(None)
-
- def on_style_updated(self, *args):
- self.loadUpdates()
-
- def quit(self):
- self.editor.quit()
- Gtk.main_quit()
+ timer = None
+ #hack to make editing menu properties work
+ allow_update = True
+ #drag-and-drop stuff
+ dnd_items = [('MOZO_ITEM_ROW', Gtk.TargetFlags.SAME_APP, 0), ('text/plain', 0, 1)]
+ dnd_menus = [('MOZO_MENU_ROW', Gtk.TargetFlags.SAME_APP, 0)]
+ dnd_both = [dnd_items[0],] + dnd_menus
+ drag_data = None
+ edit_pool = []
+
+ def __init__(self, datadir, version, argv):
+ self.file_path = datadir
+ self.version = version
+ self.editor = MenuEditor()
+ Gtk.Window.set_default_icon_name('mozo')
+ self.tree = Gtk.Builder()
+ self.tree.set_translation_domain(GETTEXT_PACKAGE)
+ self.tree.add_from_file(os.path.join(self.file_path, 'mozo.ui'))
+ self.tree.connect_signals(self)
+ self.setupMenuTree()
+ self.setupItemTree()
+ self.tree.get_object('edit_delete').set_sensitive(False)
+ self.tree.get_object('edit_revert_to_original').set_sensitive(False)
+ self.tree.get_object('edit_properties').set_sensitive(False)
+ self.tree.get_object('move_up_button').set_sensitive(False)
+ self.tree.get_object('move_down_button').set_sensitive(False)
+ self.tree.get_object('new_separator_button').set_sensitive(False)
+ self.tree.get_object('properties_button').set_sensitive(False)
+ self.tree.get_object('delete_button').set_sensitive(False)
+ accelgroup = Gtk.AccelGroup()
+ keyval, modifier = Gtk.accelerator_parse('<Ctrl>Z')
+ accelgroup.connect(keyval, modifier, Gtk.AccelFlags.VISIBLE, self.on_mainwindow_undo)
+ keyval, modifier = Gtk.accelerator_parse('<Ctrl><Shift>Z')
+ accelgroup.connect(keyval, modifier, Gtk.AccelFlags.VISIBLE, self.on_mainwindow_redo)
+ keyval, modifier = Gtk.accelerator_parse('F1')
+ accelgroup.connect(keyval, modifier, Gtk.AccelFlags.VISIBLE, self.on_help_button_clicked)
+ self.tree.get_object('mainwindow').add_accel_group(accelgroup)
+
+ def run(self):
+ self.loadMenus()
+ self.editor.applications.tree.add_monitor(self.menuChanged, None)
+ self.editor.settings.tree.add_monitor(self.menuChanged, None)
+ self.tree.get_object('mainwindow').show_all()
+ Gtk.main()
+
+ def menuChanged(self, *a):
+ if self.timer:
+ GLib.Source.remove(self.timer)
+ self.timer = None
+ self.timer = GLib.timeout_add(3, self.loadUpdates)
+
+ def loadUpdates(self):
+ if not self.allow_update:
+ self.timer = None
+ return False
+ menu_tree = self.tree.get_object('menu_tree')
+ item_tree = self.tree.get_object('item_tree')
+ items, iter = item_tree.get_selection().get_selected()
+ update_items = False
+ item_id, separator_path = None, None
+ if iter:
+ update_items = True
+ if items[iter][3].get_type() == matemenu.TYPE_DIRECTORY:
+ item_id = os.path.split(items[iter][3].get_desktop_file_path())[1]
+ update_items = True
+ elif items[iter][3].get_type() == matemenu.TYPE_ENTRY:
+ item_id = items[iter][3].get_desktop_file_id()
+ update_items = True
+ elif items[iter][3].get_type() == matemenu.TYPE_SEPARATOR:
+ item_id = items.get_path(iter).to_string()
+ update_items = True
+ menus, iter = menu_tree.get_selection().get_selected()
+ update_menus = False
+ menu_id = None
+ if iter:
+ if menus[iter][2].get_desktop_file_path():
+ menu_id = os.path.split(menus[iter][2].get_desktop_file_path())[1]
+ else:
+ menu_id = menus[iter][2].get_menu_id()
+ update_menus = True
+ self.loadMenus()
+ #find current menu in new tree
+ if update_menus:
+ menu_tree.get_model().foreach(self.findMenu, menu_id)
+ menus, iter = menu_tree.get_selection().get_selected()
+ if iter:
+ self.on_menu_tree_cursor_changed(menu_tree)
+ #find current item in new list
+ if update_items:
+ i = 0
+ for item in item_tree.get_model():
+ found = False
+ if item[3].get_type() == matemenu.TYPE_ENTRY and item[3].get_desktop_file_id() == item_id:
+ found = True
+ if item[3].get_type() == matemenu.TYPE_DIRECTORY and item[3].get_desktop_file_path():
+ if os.path.split(item[3].get_desktop_file_path())[1] == item_id:
+ found = True
+ if item[3].get_type() == matemenu.TYPE_SEPARATOR:
+ if not isinstance(item_id, tuple):
+ #we may not skip the increment via "continue"
+ i += 1
+ continue
+ #separators have no id, have to find them manually
+ #probably won't work with two separators together
+ if (item_id[0] - 1,) == (i,):
+ found = True
+ elif (item_id[0] + 1,) == (i,):
+ found = True
+ elif (item_id[0],) == (i,):
+ found = True
+ if found:
+ item_tree.get_selection().select_path((i,))
+ self.on_item_tree_cursor_changed(item_tree)
+ break
+ i += 1
+ self.timer = None
+ return False
+
+ def findMenu(self, menus, path, iter, menu_id):
+ if not menus[path][2].get_desktop_file_path():
+ if menu_id == menus[path][2].get_menu_id():
+ menu_tree = self.tree.get_object('menu_tree')
+ menu_tree.expand_to_path(path)
+ menu_tree.get_selection().select_path(path)
+ return True
+ return False
+ if os.path.split(menus[path][2].get_desktop_file_path())[1] == menu_id:
+ menu_tree = self.tree.get_object('menu_tree')
+ menu_tree.expand_to_path(path)
+ menu_tree.get_selection().select_path(path)
+ return True
+
+ def setupMenuTree(self):
+ self.menu_store = Gtk.TreeStore(GdkPixbuf.Pixbuf, str, object)
+ menus = self.tree.get_object('menu_tree')
+ column = Gtk.TreeViewColumn(_('Name'))
+ column.set_spacing(4)
+ cell = Gtk.CellRendererPixbuf()
+ column.pack_start(cell, False)
+ column.set_attributes(cell, pixbuf=0)
+ cell = Gtk.CellRendererText()
+ cell.set_fixed_size(-1, 25)
+ column.pack_start(cell, True)
+ column.set_attributes(cell, markup=1)
+ column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
+ menus.append_column(column)
+ menus.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK, self.dnd_menus, Gdk.DragAction.COPY)
+ menus.enable_model_drag_dest(self.dnd_both, Gdk.DragAction.PRIVATE)
+
+ def setupItemTree(self):
+ items = self.tree.get_object('item_tree')
+ column = Gtk.TreeViewColumn(_('Show'))
+ cell = Gtk.CellRendererToggle()
+ cell.connect('toggled', self.on_item_tree_show_toggled)
+ column.pack_start(cell, True)
+ column.set_attributes(cell, active=0)
+ #hide toggle for separators
+ column.set_cell_data_func(cell, self._cell_data_toggle_func)
+ items.append_column(column)
+ column = Gtk.TreeViewColumn(_('Item'))
+ column.set_spacing(4)
+ cell = Gtk.CellRendererPixbuf()
+ column.pack_start(cell, False)
+ column.set_attributes(cell, pixbuf=1)
+ cell = Gtk.CellRendererText()
+ cell.set_fixed_size(-1, 25)
+ column.pack_start(cell, True)
+ column.set_attributes(cell, markup=2)
+ items.append_column(column)
+ self.item_store = Gtk.ListStore(bool, GdkPixbuf.Pixbuf, str, object)
+ items.set_model(self.item_store)
+ items.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK, self.dnd_items, Gdk.DragAction.COPY)
+ items.enable_model_drag_dest(self.dnd_items, Gdk.DragAction.PRIVATE)
+
+ def _cell_data_toggle_func(self, tree_column, renderer, model, treeiter, data=None):
+ if model[treeiter][3].get_type() == matemenu.TYPE_SEPARATOR:
+ renderer.set_property('visible', False)
+ else:
+ renderer.set_property('visible', True)
+
+ def loadMenus(self):
+ self.menu_store.clear()
+ for menu in self.editor.getMenus():
+ iters = [None]*20
+ self.loadMenu(iters, menu)
+ menu_tree = self.tree.get_object('menu_tree')
+ menu_tree.set_model(self.menu_store)
+ for menu in self.menu_store:
+ #this might not work for some reason
+ try:
+ menu_tree.expand_to_path(menu.path)
+ except:
+ pass
+ menu_tree.get_selection().select_path((0,))
+ self.on_menu_tree_cursor_changed(menu_tree)
+
+ def loadMenu(self, iters, parent, depth=0):
+ if depth == 0:
+ icon = util.getIcon(parent)
+ iters[depth] = self.menu_store.append(None, (icon, cgi.escape(parent.get_name()), parent))
+ depth += 1
+ for menu, show in self.editor.getMenus(parent):
+ if show:
+ name = cgi.escape(menu.get_name())
+ else:
+ name = '<small><i>' + cgi.escape(menu.get_name()) + '</i></small>'
+ icon = util.getIcon(menu)
+ iters[depth] = self.menu_store.append(iters[depth-1], (icon, name, menu))
+ self.loadMenu(iters, menu, depth)
+ depth -= 1
+
+ def loadItems(self, menu, menu_path):
+ self.item_store.clear()
+ for item, show in self.editor.getItems(menu):
+ menu_icon = None
+ if item.get_type() == matemenu.TYPE_SEPARATOR:
+ name = '---'
+ icon = None
+ elif item.get_type() == matemenu.TYPE_ENTRY:
+ if show:
+ name = cgi.escape(item.get_display_name())
+ else:
+ name = '<small><i>' + cgi.escape(item.get_display_name()) + '</i></small>'
+ icon = util.getIcon(item)
+ else:
+ if show:
+ name = cgi.escape(item.get_name())
+ else:
+ name = '<small><i>' + cgi.escape(item.get_name()) + '</i></small>'
+ icon = util.getIcon(item)
+ self.item_store.append((show, icon, name, item))
+
+ #this is a little timeout callback to insert new items after
+ #mate-desktop-item-edit has finished running
+ def waitForNewItemProcess(self, process, parent_id, file_path):
+ if process.poll() is not None:
+ if os.path.isfile(file_path):
+ self.editor.insertExternalItem(os.path.split(file_path)[1], parent_id)
+ return False
+ return True
+
+ def waitForNewMenuProcess(self, process, parent_id, file_path):
+ if process.poll() is not None:
+ #hack for broken mate-desktop-item-edit
+ broken_path = os.path.join(os.path.split(file_path)[0], '.directory')
+ if os.path.isfile(broken_path):
+ os.rename(broken_path, file_path)
+ if os.path.isfile(file_path):
+ self.editor.insertExternalMenu(os.path.split(file_path)[1], parent_id)
+ return False
+ return True
+
+ #this callback keeps you from editing the same item twice
+ def waitForEditProcess(self, process, file_path):
+ if process.poll() is not None:
+ self.edit_pool.remove(file_path)
+ return False
+ return True
+
+ def on_delete_event(self, widget, event):
+ self.quit()
+
+ def on_new_menu_button_clicked(self, button):
+ menu_tree = self.tree.get_object('menu_tree')
+ menus, iter = menu_tree.get_selection().get_selected()
+ if not iter:
+ parent = menus[(0,)][2]
+ menu_tree.expand_to_path((0,))
+ menu_tree.get_selection().select_path((0,))
+ else:
+ parent = menus[iter][2]
+ file_path = os.path.join(util.getUserDirectoryPath(), util.getUniqueFileId('mozo-made', '.directory'))
+ process = subprocess.Popen(['mate-desktop-item-edit', file_path], env=os.environ)
+ GLib.timeout_add(100, self.waitForNewMenuProcess, process, parent.menu_id, file_path)
+
+ def on_new_item_button_clicked(self, button):
+ menu_tree = self.tree.get_object('menu_tree')
+ menus, iter = menu_tree.get_selection().get_selected()
+ if not iter:
+ parent = menus[(0,)][2]
+ menu_tree.expand_to_path((0,))
+ menu_tree.get_selection().select_path((0,))
+ else:
+ parent = menus[iter][2]
+ file_path = os.path.join(util.getUserItemPath(), util.getUniqueFileId('mozo-made', '.desktop'))
+ process = subprocess.Popen(['mate-desktop-item-edit', file_path], env=os.environ)
+ GLib.timeout_add(100, self.waitForNewItemProcess, process, parent.menu_id, file_path)
+
+ def on_new_separator_button_clicked(self, button):
+ item_tree = self.tree.get_object('item_tree')
+ items, iter = item_tree.get_selection().get_selected()
+ if not iter:
+ return
+ else:
+ after = items[iter][3]
+ menu_tree = self.tree.get_object('menu_tree')
+ menus, iter = menu_tree.get_selection().get_selected()
+ parent = menus[iter][2]
+ self.editor.createSeparator(parent, after=after)
+
+ def on_edit_delete_activate(self, menu):
+ item_tree = self.tree.get_object('item_tree')
+ items, iter = item_tree.get_selection().get_selected()
+ if not iter:
+ return
+ item = items[iter][3]
+ if item.get_type() == matemenu.TYPE_ENTRY:
+ self.editor.deleteItem(item)
+ elif item.get_type() == matemenu.TYPE_DIRECTORY:
+ self.editor.deleteMenu(item)
+ elif item.get_type() == matemenu.TYPE_SEPARATOR:
+ self.editor.deleteSeparator(item)
+
+ def on_edit_revert_to_original_activate(self, menu):
+ item_tree = self.tree.get_object('item_tree')
+ items, iter = item_tree.get_selection().get_selected()
+ if not iter:
+ return
+ item = items[iter][3]
+ if item.get_type() == matemenu.TYPE_ENTRY:
+ self.editor.revertItem(item)
+ elif item.get_type() == matemenu.TYPE_DIRECTORY:
+ self.editor.revertMenu(item)
+
+ def on_edit_properties_activate(self, menu):
+ item_tree = self.tree.get_object('item_tree')
+ items, iter = item_tree.get_selection().get_selected()
+ if not iter:
+ return
+ item = items[iter][3]
+ if item.get_type() not in (matemenu.TYPE_ENTRY, matemenu.TYPE_DIRECTORY):
+ return
+
+ if item.get_type() == matemenu.TYPE_ENTRY:
+ file_path = os.path.join(util.getUserItemPath(), item.get_desktop_file_id())
+ file_type = 'Item'
+ elif item.get_type() == matemenu.TYPE_DIRECTORY:
+ file_path = os.path.join(util.getUserDirectoryPath(), os.path.split(item.get_desktop_file_path())[1])
+ file_type = 'Menu'
+
+ if not os.path.isfile(file_path):
+ shutil.copy(item.get_desktop_file_path(), file_path)
+ self.editor._MenuEditor__addUndo([(file_type, os.path.split(file_path)[1]),])
+ else:
+ self.editor._MenuEditor__addUndo([item,])
+ if file_path not in self.edit_pool:
+ self.edit_pool.append(file_path)
+ process = subprocess.Popen(['mate-desktop-item-edit', file_path], env=os.environ)
+ GLib.timeout_add(100, self.waitForEditProcess, process, file_path)
+
+ def on_menu_tree_cursor_changed(self, treeview):
+ menus, iter = treeview.get_selection().get_selected()
+ if iter is None:
+ return
+ menu_path = menus.get_path(iter)
+ item_tree = self.tree.get_object('item_tree')
+ item_tree.get_selection().unselect_all()
+ self.loadItems(self.menu_store[menu_path][2], menu_path)
+ self.tree.get_object('edit_delete').set_sensitive(False)
+ self.tree.get_object('edit_revert_to_original').set_sensitive(False)
+ self.tree.get_object('edit_properties').set_sensitive(False)
+ self.tree.get_object('move_up_button').set_sensitive(False)
+ self.tree.get_object('move_down_button').set_sensitive(False)
+ self.tree.get_object('new_separator_button').set_sensitive(False)
+
+ def on_menu_tree_drag_data_get(self, treeview, context, selection, target_id, etime):
+ menus, iter = treeview.get_selection().get_selected()
+ self.drag_data = menus[iter][2]
+
+ def on_menu_tree_drag_data_received(self, treeview, context, x, y, selection, info, etime):
+ menus = treeview.get_model()
+ drop_info = treeview.get_dest_row_at_pos(x, y)
+ if drop_info:
+ path, position = drop_info
+ types = (Gtk.TreeViewDropPosition.INTO_OR_BEFORE, Gtk.TreeViewDropPosition.INTO_OR_AFTER)
+ if position not in types:
+ context.finish(False, False, etime)
+ return False
+ if str(selection.get_target()) in ('MOZO_ITEM_ROW', 'MOZO_MENU_ROW'):
+ if self.drag_data is None:
+ return False
+ item = self.drag_data
+ new_parent = menus[path][2]
+ if item.get_type() == matemenu.TYPE_ENTRY:
+ self.editor.copyItem(item, new_parent)
+ elif item.get_type() == matemenu.TYPE_DIRECTORY:
+ if not self.editor.moveMenu(item, new_parent):
+ self.loadUpdates()
+ elif item.get_type() == matemenu.TYPE_SEPARATOR:
+ self.editor.moveSeparator(item, new_parent)
+ else:
+ context.finish(False, False, etime)
+ context.finish(True, True, etime)
+ self.drag_data = None
+
+ def on_item_tree_show_toggled(self, cell, path):
+ item = self.item_store[path][3]
+ if item.get_type() == matemenu.TYPE_SEPARATOR:
+ return
+ if self.item_store[path][0]:
+ self.editor.setVisible(item, False)
+ else:
+ self.editor.setVisible(item, True)
+ self.item_store[path][0] = not self.item_store[path][0]
+
+ def on_item_tree_cursor_changed(self, treeview):
+ items, iter = treeview.get_selection().get_selected()
+ if iter is None:
+ return
+
+ item = items[iter][3]
+ self.tree.get_object('edit_delete').set_sensitive(True)
+ self.tree.get_object('new_separator_button').set_sensitive(True)
+ self.tree.get_object('delete_button').set_sensitive(True)
+
+ can_revert = self.editor.canRevert(item)
+ self.tree.get_object('edit_revert_to_original').set_sensitive(can_revert)
+
+ can_edit = not item.get_type() == matemenu.TYPE_SEPARATOR
+ self.tree.get_object('edit_properties').set_sensitive(can_edit)
+ self.tree.get_object('properties_button').set_sensitive(can_edit)
+
+ index = items.get_path(iter).get_indices()[0]
+ can_go_up = index > 0
+ can_go_down = index < len(items) - 1
+ self.tree.get_object('move_up_button').set_sensitive(can_go_up)
+ self.tree.get_object('move_down_button').set_sensitive(can_go_down)
+
+ def on_item_tree_row_activated(self, treeview, path, column):
+ self.on_edit_properties_activate(None)
+
+ def on_item_tree_popup_menu(self, item_tree, event=None):
+ model, iter = item_tree.get_selection().get_selected()
+ if event:
+ #don't show if it's not the right mouse button
+ if event.button != 3:
+ return
+ button = event.button
+ event_time = event.time
+ info = item_tree.get_path_at_pos(int(event.x), int(event.y))
+ if info is not None:
+ path, col, cellx, celly = info
+ item_tree.grab_focus()
+ item_tree.set_cursor(path, col, 0)
+ else:
+ path = model.get_path(iter)
+ button = 0
+ event_time = 0
+ item_tree.grab_focus()
+ item_tree.set_cursor(path, item_tree.get_columns()[0], 0)
+ popup = self.tree.get_object('edit_menu')
+ popup.popup(None, None, None, None, button, event_time)
+ #without this shift-f10 won't work
+ return True
+
+ def on_item_tree_drag_data_get(self, treeview, context, selection, target_id, etime):
+ items, iter = treeview.get_selection().get_selected()
+ self.drag_data = items[iter][3]
+
+ def on_item_tree_drag_data_received(self, treeview, context, x, y, selection, info, etime):
+ items = treeview.get_model()
+ types_before = (Gtk.TreeViewDropPosition.BEFORE, Gtk.TreeViewDropPosition.INTO_OR_BEFORE)
+ types_into = (Gtk.TreeViewDropPosition.INTO_OR_BEFORE, Gtk.TreeViewDropPosition.INTO_OR_AFTER)
+ types_after = (Gtk.TreeViewDropPosition.AFTER, Gtk.TreeViewDropPosition.INTO_OR_AFTER)
+ if str(selection.get_target()) == 'MOZO_ITEM_ROW':
+ drop_info = treeview.get_dest_row_at_pos(x, y)
+ before = None
+ after = None
+ if self.drag_data is None:
+ return False
+ item = self.drag_data
+ # by default we assume, that the items stays in the same menu
+ destination = item.get_parent()
+ if drop_info:
+ path, position = drop_info
+ target = items[path][3]
+ # move the item to the directory, if the item was dropped into it
+ if (target.get_type() == matemenu.TYPE_DIRECTORY) and (position in types_into):
+ # append the selected item to the choosen menu
+ destination = target
+ elif position in types_before:
+ before = target
+ elif position in types_after:
+ after = target
+ else:
+ # this does not happen
+ pass
+ else:
+ path = (len(items) - 1,)
+ after = items[path][3]
+ if item.get_type() == matemenu.TYPE_ENTRY:
+ self.editor.moveItem(item, destination, before, after)
+ elif item.get_type() == matemenu.TYPE_DIRECTORY:
+ if not self.editor.moveMenu(item, destination, before, after):
+ self.loadUpdates()
+ elif item.get_type() == matemenu.TYPE_SEPARATOR:
+ self.editor.moveSeparator(item, destination, before, after)
+ context.finish(True, True, etime)
+ elif str(selection.get_target()) == 'text/plain':
+ if selection.data is None:
+ return False
+ menus, iter = self.tree.get_object('menu_tree').get_selection().get_selected()
+ parent = menus[iter][2]
+ drop_info = treeview.get_dest_row_at_pos(x, y)
+ before = None
+ after = None
+ if drop_info:
+ path, position = drop_info
+ if position in types_before:
+ before = items[path][3]
+ else:
+ after = items[path][3]
+ else:
+ path = (len(items) - 1,)
+ after = items[path][3]
+ file_path = urllib.unquote(selection.data).strip()
+ if not file_path.startswith('file:'):
+ return
+ myfile = Gio.File(uri=file_path)
+ file_info = myfile.query_info(Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE)
+ content_type = file_info.get_content_type()
+ if content_type == 'application/x-desktop':
+ input_stream = myfile.read()
+ keyfile = GLib.KeyFile()
+ keyfile.load_from_data(input_stream.read())
+ self.editor.createItem(parent, before, after, KeyFile=keyfile)
+ elif content_type in ('application/x-shellscript', 'application/x-executable'):
+ self.editor.createItem(parent, before, after,
+ Name=os.path.split(file_path)[1].strip(),
+ Exec=file_path.replace('file://', '').strip(),
+ Terminal=False)
+ self.drag_data = None
+
+ def on_item_tree_key_press_event(self, item_tree, event):
+ if event.keyval == Gdk.KEY_Delete:
+ self.on_edit_delete_activate(item_tree)
+
+ def on_move_up_button_clicked(self, button):
+ item_tree = self.tree.get_object('item_tree')
+ items, iter = item_tree.get_selection().get_selected()
+ if not iter:
+ return
+ path = items.get_path(iter)
+ #at top, can't move up
+ if path.get_indices()[0] == 0:
+ return
+ item = items[path][3]
+ before = items[(path[0] - 1,)][3]
+ if item.get_type() == matemenu.TYPE_ENTRY:
+ self.editor.moveItem(item, item.get_parent(), before=before)
+ elif item.get_type() == matemenu.TYPE_DIRECTORY:
+ self.editor.moveMenu(item, item.get_parent(), before=before)
+ elif item.get_type() == matemenu.TYPE_SEPARATOR:
+ self.editor.moveSeparator(item, item.get_parent(), before=before)
+
+ def on_move_down_button_clicked(self, button):
+ item_tree = self.tree.get_object('item_tree')
+ items, iter = item_tree.get_selection().get_selected()
+ if not iter:
+ return
+ path = items.get_path(iter)
+ #at bottom, can't move down
+ if path.get_indices()[0] == (len(items) - 1):
+ return
+ item = items[path][3]
+ after = items[path][3]
+ if item.get_type() == matemenu.TYPE_ENTRY:
+ self.editor.moveItem(item, item.get_parent(), after=after)
+ elif item.get_type() == matemenu.TYPE_DIRECTORY:
+ self.editor.moveMenu(item, item.get_parent(), after=after)
+ elif item.get_type() == matemenu.TYPE_SEPARATOR:
+ self.editor.moveSeparator(item, item.get_parent(), after=after)
+
+ def on_mainwindow_undo(self, accelgroup, window, keyval, modifier):
+ self.editor.undo()
+
+ def on_mainwindow_redo(self, accelgroup, window, keyval, modifier):
+ self.editor.redo()
+
+ def on_help_button_clicked(self, *args):
+ Gtk.show_uri(Gdk.Screen.get_default(), "help:mate-user-guide/menu-editor", Gtk.get_current_event_time())
+
+ def on_revert_button_clicked(self, button):
+ dialog = self.tree.get_object('revertdialog')
+ dialog.set_transient_for(self.tree.get_object('mainwindow'))
+ dialog.show_all()
+ if dialog.run() == Gtk.ResponseType.YES:
+ self.editor.revert()
+ dialog.hide()
+
+ def on_close_button_clicked(self, button):
+ try:
+ self.tree.get_object('mainwindow').hide()
+ except:
+ pass
+ GLib.timeout_add(10, self.quit)
+
+ def on_properties_button_clicked(self, button):
+ self.on_edit_properties_activate(None)
+
+ def on_delete_button_clicked(self, button):
+ self.on_edit_delete_activate(None)
+
+ def on_style_updated(self, *args):
+ self.loadUpdates()
+
+ def quit(self):
+ self.editor.quit()
+ Gtk.main_quit()