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
27 from Alacarte
import config
28 gettext
.bindtextdomain(config
.GETTEXT_PACKAGE
, config
.localedir
)
29 gettext
.textdomain(config
.GETTEXT_PACKAGE
)
32 from Alacarte
.MenuEditor
import MenuEditor
33 from Alacarte
import util
38 #hack to make editing menu properties work
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
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
)
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
)
75 self
.editor
.applications
.tree
.connect("changed", self
.menuChanged
)
76 self
.tree
.get_object('mainwindow').show_all()
79 def menuChanged(self
, *a
):
82 def loadUpdates(self
):
83 self
.editor
.reloadMenus()
84 self
.editor
.applications
.tree
.connect("changed", self
.menuChanged
)
86 if not self
.allow_update
:
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()
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()
109 if menus
[iter][2].get_desktop_file_path():
110 menu_id
= os
.path
.split(menus
[iter][2].get_desktop_file_path())[1]
112 menu_id
= menus
[iter][2].get_menu_id()
115 #find current menu in new tree
117 menu_tree
.get_model().foreach(self
.findMenu
, menu_id
)
118 menus
, iter = menu_tree
.get_selection().get_selected()
120 self
.on_menu_tree_cursor_changed(menu_tree
)
121 #find current item in new list
124 for item
in item_tree
.get_model():
126 if update_type
!= GMenu
.TreeItemType
.SEPARATOR
:
127 if isinstance (item
[3], GMenu
.TreeEntry
) and item
[3].get_desktop_file_id() == item_id
:
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
:
132 if isinstance(item
[3], GMenu
.TreeSeparator
):
133 if not isinstance(item_id
, tuple):
134 #we may not skip the increment via "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
,):
141 elif (item_id
[0] + 1,) == (i
,):
143 elif (item_id
[0],) == (i
,):
146 item_tree
.get_selection().select_path((i
,))
147 self
.on_item_tree_cursor_changed(item_tree
)
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
)
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
)
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)
210 renderer
.set_property('visible', True)
213 self
.menu_store
.clear()
214 for menu
in self
.editor
.getMenus():
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):
226 icon
= util
.getIcon(parent
)
227 iters
[depth
] = self
.menu_store
.append(None, (icon
, cgi
.escape(parent
.get_name()), parent
))
229 for menu
, show
in self
.editor
.getMenus(parent
):
231 name
= cgi
.escape(menu
.get_name())
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
)
239 def loadItems(self
, menu
, menu_path
):
240 self
.item_store
.clear()
241 for item
, show
in self
.editor
.getItems(menu
):
243 if isinstance(item
, GMenu
.TreeSeparator
):
246 elif isinstance(item
, GMenu
.TreeEntry
):
247 app_info
= item
.get_app_info()
249 name
= cgi
.escape(app_info
.get_display_name())
251 name
= '<small><i>' + cgi
.escape(app_info
.get_display_name()) + '</i></small>'
252 icon
= util
.getIcon(item
)
255 name
= cgi
.escape(item
.get_name())
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
)
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
)
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
)
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()
292 parent
= menus
[(0,)][2]
293 menu_tree
.expand_to_path((0,))
294 menu_tree
.get_selection().select_path((0,))
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()
305 parent
= menus
[(0,)][2]
306 menu_tree
.expand_to_path((0,))
307 menu_tree
.get_selection().select_path((0,))
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()
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()
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()
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()
355 item
= items
[iter][3]
356 if not isinstance(item
, GMenu
.TreeEntry
) and not isinstance(item
, GMenu
.TreeDirectory
):
359 if isinstance(item
, GMenu
.TreeEntry
):
360 file_path
= os
.path
.join(util
.getUserItemPath(), item
.get_desktop_file_id())
362 elif isinstance(item
, GMenu
.TreeDirectory
):
363 file_path
= os
.path
.join(util
.getUserDirectoryPath(), os
.path
.split(item
.get_desktop_file_path())[1])
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]),])
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
)
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
)
407 if selection
.target
in ('ALACARTE_ITEM_ROW', 'ALACARTE_MENU_ROW'):
408 if self
.drag_data
== None:
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:
418 elif isinstance(item
, GMenu
.TreeSeparator
):
419 self
.editor
.moveSeparator(item
, new_parent
)
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
):
429 if self
.item_store
[path
][0]:
430 self
.editor
.setVisible(item
, False)
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()
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)
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)
451 self
.tree
.get_object('edit_properties').set_sensitive(False)
452 self
.tree
.get_object('properties_button').set_sensitive(False)
455 if items
.get_path(iter).get_indices()[0] == 0:
456 self
.tree
.get_object('move_up_button').set_sensitive(False)
458 self
.tree
.get_object('move_up_button').set_sensitive(True)
461 if items
.get_path(iter).get_indices()[0] == (len(items
)-1):
462 self
.tree
.get_object('move_down_button').set_sensitive(False)
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()
472 #don't show if it's not the right mouse button
473 if event
.button
!= 3:
475 button
= event
.button
476 event_time
= event
.time
477 info
= item_tree
.get_path_at_pos(int(event
.x
), int(event
.y
))
479 path
, col
, cellx
, celly
= info
480 item_tree
.grab_focus()
481 item_tree
.set_cursor(path
, col
, 0)
483 path
= model
.get_path(iter)
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
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
)
504 if self
.drag_data
== None:
506 item
= self
.drag_data
507 # by default we assume, that the items stays in the same menu
508 destination
= item
.get_parent()
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
516 elif position
in types_before
:
518 elif position
in types_after
:
521 # this does not happen
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:
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:
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
)
543 path
, position
= drop_info
544 if position
in types
:
545 before
= items
[path
][3]
547 after
= items
[path
][3]
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:'):
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(),
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()
578 path
= items
.get_path(iter)
579 #at top, can't move up
580 if path
.get_indices()[0] == 0:
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()
596 path
= items
.get_path(iter)
597 #at bottom, can't move down
598 if path
.get_indices()[0] == (len(items
) - 1):
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
):
612 def on_mainwindow_redo(self
, accelgroup
, window
, keyval
, modifier
):
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'))
622 if dialog
.run() == Gtk
.ResponseType
.YES
:
626 def on_close_button_clicked(self
, button
):
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
):