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
26 from Alacarte
import config
27 gettext
.bindtextdomain(config
.GETTEXT_PACKAGE
, config
.localedir
)
28 gettext
.textdomain(config
.GETTEXT_PACKAGE
)
31 from Alacarte
.MenuEditor
import MenuEditor
32 from Alacarte
import util
34 class MainWindow(object):
36 #hack to make editing menu properties work
39 dnd_items
= [('ALACARTE_ITEM_ROW', Gtk
.TargetFlags
.SAME_APP
, 0), ('text/plain', 0, 1)]
40 dnd_menus
= [('ALACARTE_MENU_ROW', Gtk
.TargetFlags
.SAME_APP
, 0)]
41 dnd_both
= [dnd_items
[0],] + dnd_menus
45 def __init__(self
, datadir
, version
):
46 self
.file_path
= datadir
47 self
.version
= version
48 self
.editor
= MenuEditor()
49 Gtk
.Window
.set_default_icon_name('alacarte')
50 self
.tree
= Gtk
.Builder()
51 self
.tree
.set_translation_domain(config
.GETTEXT_PACKAGE
)
52 self
.tree
.add_from_file(os
.path
.join(self
.file_path
, 'alacarte.ui'))
53 self
.tree
.connect_signals(self
)
56 self
.tree
.get_object('edit_delete').set_sensitive(False)
57 self
.tree
.get_object('edit_revert_to_original').set_sensitive(False)
58 self
.tree
.get_object('edit_properties').set_sensitive(False)
59 self
.tree
.get_object('move_up_button').set_sensitive(False)
60 self
.tree
.get_object('move_down_button').set_sensitive(False)
61 self
.tree
.get_object('new_separator_button').set_sensitive(False)
62 accelgroup
= Gtk
.AccelGroup()
63 keyval
, modifier
= Gtk
.accelerator_parse('<Ctrl>Z')
64 accelgroup
.connect(keyval
, modifier
, Gtk
.AccelFlags
.VISIBLE
, self
.on_mainwindow_undo
)
65 keyval
, modifier
= Gtk
.accelerator_parse('<Ctrl><Shift>Z')
66 accelgroup
.connect(keyval
, modifier
, Gtk
.AccelFlags
.VISIBLE
, self
.on_mainwindow_redo
)
67 keyval
, modifier
= Gtk
.accelerator_parse('F1')
68 accelgroup
.connect(keyval
, modifier
, Gtk
.AccelFlags
.VISIBLE
, self
.on_help_button_clicked
)
69 self
.tree
.get_object('mainwindow').add_accel_group(accelgroup
)
73 self
.editor
.applications
.tree
.connect("changed", self
.menuChanged
)
74 self
.tree
.get_object('mainwindow').show_all()
77 def menuChanged(self
, *a
):
80 def loadUpdates(self
):
81 self
.editor
.reloadMenus()
82 self
.editor
.applications
.tree
.connect("changed", self
.menuChanged
)
84 if not self
.allow_update
:
86 menu_tree
= self
.tree
.get_object('menu_tree')
87 item_tree
= self
.tree
.get_object('item_tree')
88 items
, iter = item_tree
.get_selection().get_selected()
94 if isinstance(items
[iter][3], GMenu
.TreeEntry
):
95 item_id
= items
[iter][3].get_desktop_file_id()
96 update_type
= GMenu
.TreeItemType
.ENTRY
97 elif isinstance(items
[iter][3], GMenu
.TreeDirectory
):
98 item_id
= os
.path
.split(items
[iter][3].get_desktop_file_path())[1]
99 update_type
= GMenu
.TreeItemType
.DIRECTORY
100 elif isinstance(items
[iter][3], GMenu
.Tree
.Separator
):
101 item_id
= items
.get_path(iter)
102 update_type
= GMenu
.TreeItemType
.SEPARATOR
103 menus
, iter = menu_tree
.get_selection().get_selected()
107 if menus
[iter][2].get_desktop_file_path():
108 menu_id
= os
.path
.split(menus
[iter][2].get_desktop_file_path())[1]
110 menu_id
= menus
[iter][2].get_menu_id()
113 #find current menu in new tree
115 menu_tree
.get_model().foreach(self
.findMenu
, menu_id
)
116 menus
, iter = menu_tree
.get_selection().get_selected()
118 self
.on_menu_tree_cursor_changed(menu_tree
)
119 #find current item in new list
122 for item
in item_tree
.get_model():
124 if update_type
!= GMenu
.TreeItemType
.SEPARATOR
:
125 if isinstance (item
[3], GMenu
.TreeEntry
) and item
[3].get_desktop_file_id() == item_id
:
127 if isinstance (item
[3], GMenu
.TreeDirectory
) and item
[3].get_desktop_file_path() and update_type
== GMenu
.TreeItemType
.DIRECTORY
:
128 if os
.path
.split(item
[3].get_desktop_file_path())[1] == item_id
:
130 if isinstance(item
[3], GMenu
.TreeSeparator
):
131 if not isinstance(item_id
, tuple):
132 #we may not skip the increment via "continue"
135 #separators have no id, have to find them manually
136 #probably won't work with two separators together
137 if (item_id
[0] - 1,) == (i
,):
139 elif (item_id
[0] + 1,) == (i
,):
141 elif (item_id
[0],) == (i
,):
144 item_tree
.get_selection().select_path((i
,))
145 self
.on_item_tree_cursor_changed(item_tree
)
150 def findMenu(self
, menus
, path
, iter, menu_id
):
151 if not menus
[path
][2].get_desktop_file_path():
152 if menu_id
== menus
[path
][2].get_menu_id():
153 menu_tree
= self
.tree
.get_object('menu_tree')
154 menu_tree
.expand_to_path(path
)
155 menu_tree
.get_selection().select_path(path
)
158 if os
.path
.split(menus
[path
][2].get_desktop_file_path())[1] == menu_id
:
159 menu_tree
= self
.tree
.get_object('menu_tree')
160 menu_tree
.expand_to_path(path
)
161 menu_tree
.get_selection().select_path(path
)
164 def setupMenuTree(self
):
165 self
.menu_store
= Gtk
.TreeStore(GdkPixbuf
.Pixbuf
, str, object)
166 menus
= self
.tree
.get_object('menu_tree')
167 column
= Gtk
.TreeViewColumn(_('Name'))
168 column
.set_spacing(4)
169 cell
= Gtk
.CellRendererPixbuf()
170 column
.pack_start(cell
, False)
171 column
.add_attribute(cell
, 'pixbuf', 0)
172 cell
= Gtk
.CellRendererText()
173 column
.pack_start(cell
, True)
174 column
.add_attribute(cell
, 'markup', 1)
175 menus
.append_column(column
)
176 menus
.enable_model_drag_source(Gdk
.ModifierType
.BUTTON1_MASK
, self
.dnd_menus
, Gdk
.DragAction
.COPY
)
177 menus
.enable_model_drag_dest(self
.dnd_both
, Gdk
.DragAction
.PRIVATE
)
178 menus
.get_selection().set_mode(Gtk
.SelectionMode
.BROWSE
)
180 def setupItemTree(self
):
181 items
= self
.tree
.get_object('item_tree')
182 column
= Gtk
.TreeViewColumn(_('Show'))
183 cell
= Gtk
.CellRendererToggle()
184 cell
.connect('toggled', self
.on_item_tree_show_toggled
)
185 column
.pack_start(cell
, True)
186 column
.add_attribute(cell
, 'active', 0)
187 #hide toggle for separators
188 column
.set_cell_data_func(cell
, self
._cell
_data
_toggle
_func
)
189 items
.append_column(column
)
190 column
= Gtk
.TreeViewColumn(_('Item'))
191 column
.set_spacing(4)
192 cell
= Gtk
.CellRendererPixbuf()
193 column
.pack_start(cell
, False)
194 column
.add_attribute(cell
, 'pixbuf', 1)
195 cell
= Gtk
.CellRendererText()
196 column
.pack_start(cell
, True)
197 column
.add_attribute(cell
, 'markup', 2)
198 items
.append_column(column
)
199 self
.item_store
= Gtk
.ListStore(bool, GdkPixbuf
.Pixbuf
, str, object)
200 items
.set_model(self
.item_store
)
201 items
.enable_model_drag_source(Gdk
.ModifierType
.BUTTON1_MASK
, self
.dnd_items
, Gdk
.DragAction
.COPY
)
202 items
.enable_model_drag_dest(self
.dnd_items
, Gdk
.DragAction
.PRIVATE
)
204 def _cell_data_toggle_func(self
, tree_column
, renderer
, model
, treeiter
, data
=None):
205 if isinstance(model
[treeiter
][3], GMenu
.TreeSeparator
):
206 renderer
.set_property('visible', False)
208 renderer
.set_property('visible', True)
211 self
.menu_store
.clear()
212 for menu
in self
.editor
.getMenus():
214 self
.loadMenu(iters
, menu
)
215 menu_tree
= self
.tree
.get_object('menu_tree')
216 menu_tree
.set_model(self
.menu_store
)
217 for menu
in self
.menu_store
:
218 menu_tree
.expand_to_path(menu
.path
)
219 menu_tree
.get_selection().select_path((0,))
220 self
.on_menu_tree_cursor_changed(menu_tree
)
222 def loadMenu(self
, iters
, parent
, depth
=0):
224 icon
= util
.getIcon(parent
)
225 iters
[depth
] = self
.menu_store
.append(None, (icon
, cgi
.escape(parent
.get_name()), parent
))
227 for menu
, show
in self
.editor
.getMenus(parent
):
229 name
= cgi
.escape(menu
.get_name())
231 name
= '<small><i>' + cgi
.escape(menu
.get_name()) + '</i></small>'
232 icon
= util
.getIcon(menu
)
233 iters
[depth
] = self
.menu_store
.append(iters
[depth
-1], (icon
, name
, menu
))
234 self
.loadMenu(iters
, menu
, depth
)
237 def loadItems(self
, menu
, menu_path
):
238 self
.item_store
.clear()
239 for item
, show
in self
.editor
.getItems(menu
):
241 if isinstance(item
, GMenu
.TreeSeparator
):
244 elif isinstance(item
, GMenu
.TreeEntry
):
245 app_info
= item
.get_app_info()
247 name
= cgi
.escape(app_info
.get_display_name())
249 name
= '<small><i>' + cgi
.escape(app_info
.get_display_name()) + '</i></small>'
250 icon
= util
.getIcon(item
)
253 name
= cgi
.escape(item
.get_name())
255 name
= '<small><i>' + cgi
.escape(item
.get_name()) + '</i></small>'
256 icon
= util
.getIcon(item
)
257 self
.item_store
.append((show
, icon
, name
, item
))
259 #this is a little timeout callback to insert new items after
260 #gnome-desktop-item-edit has finished running
261 def waitForNewItemProcess(self
, process
, parent_id
, file_path
):
262 if process
.poll() != None:
263 if os
.path
.isfile(file_path
):
264 self
.editor
.insertExternalItem(os
.path
.split(file_path
)[1], parent_id
)
268 def waitForNewMenuProcess(self
, process
, parent_id
, file_path
):
269 if process
.poll() != None:
270 #hack for broken gnome-desktop-item-edit
271 broken_path
= os
.path
.join(os
.path
.split(file_path
)[0], '.directory')
272 if os
.path
.isfile(broken_path
):
273 os
.rename(broken_path
, file_path
)
274 if os
.path
.isfile(file_path
):
275 self
.editor
.insertExternalMenu(os
.path
.split(file_path
)[1], parent_id
)
279 #this callback keeps you from editing the same item twice
280 def waitForEditProcess(self
, process
, file_path
):
281 if process
.poll() != None:
282 self
.edit_pool
.remove(file_path
)
286 def on_new_menu_button_clicked(self
, button
):
287 menu_tree
= self
.tree
.get_object('menu_tree')
288 menus
, iter = menu_tree
.get_selection().get_selected()
290 parent
= menus
[(0,)][2]
291 menu_tree
.expand_to_path((0,))
292 menu_tree
.get_selection().select_path((0,))
294 parent
= menus
[iter][2]
295 file_path
= os
.path
.join(util
.getUserDirectoryPath(), util
.getUniqueFileId('alacarte-made', '.directory'))
296 process
= subprocess
.Popen(['gnome-desktop-item-edit', file_path
], env
=os
.environ
)
297 GObject
.timeout_add(100, self
.waitForNewMenuProcess
, process
, parent
.get_menu_id(), file_path
)
299 def on_new_item_button_clicked(self
, button
):
300 menu_tree
= self
.tree
.get_object('menu_tree')
301 menus
, iter = menu_tree
.get_selection().get_selected()
303 parent
= menus
[(0,)][2]
304 menu_tree
.expand_to_path((0,))
305 menu_tree
.get_selection().select_path((0,))
307 parent
= menus
[iter][2]
308 file_path
= os
.path
.join(util
.getUserItemPath(), util
.getUniqueFileId('alacarte-made', '.desktop'))
309 process
= subprocess
.Popen(['gnome-desktop-item-edit', file_path
], env
=os
.environ
)
310 GObject
.timeout_add(100, self
.waitForNewItemProcess
, process
, parent
.get_menu_id(), file_path
)
312 def on_new_separator_button_clicked(self
, button
):
313 item_tree
= self
.tree
.get_object('item_tree')
314 items
, iter = item_tree
.get_selection().get_selected()
318 after
= items
[iter][3]
319 menu_tree
= self
.tree
.get_object('menu_tree')
320 menus
, iter = menu_tree
.get_selection().get_selected()
321 parent
= menus
[iter][2]
322 self
.editor
.createSeparator(parent
, after
=after
)
324 def on_edit_delete_activate(self
, menu
):
325 item_tree
= self
.tree
.get_object('item_tree')
326 items
, iter = item_tree
.get_selection().get_selected()
329 item
= items
[iter][3]
330 if isinstance(item
, GMenu
.TreeEntry
):
331 self
.editor
.deleteItem(item
)
332 elif isinstance(item
, GMenu
.TreeDirectory
):
333 self
.editor
.deleteMenu(item
)
334 elif isinstance(item
, GMenu
.TreeSeparator
):
335 self
.editor
.deleteSeparator(item
)
337 def on_edit_revert_to_original_activate(self
, menu
):
338 item_tree
= self
.tree
.get_object('item_tree')
339 items
, iter = item_tree
.get_selection().get_selected()
342 item
= items
[iter][3]
343 if isinstance(item
, GMenu
.TreeEntry
):
344 self
.editor
.revertItem(item
)
345 elif isinstance(item
, GMenu
.TreeDirectory
):
346 self
.editor
.revertMenu(item
)
348 def on_edit_properties_activate(self
, menu
):
349 item_tree
= self
.tree
.get_object('item_tree')
350 items
, iter = item_tree
.get_selection().get_selected()
353 item
= items
[iter][3]
354 if not isinstance(item
, GMenu
.TreeEntry
) and not isinstance(item
, GMenu
.TreeDirectory
):
357 if isinstance(item
, GMenu
.TreeEntry
):
358 file_path
= os
.path
.join(util
.getUserItemPath(), item
.get_desktop_file_id())
360 elif isinstance(item
, GMenu
.TreeDirectory
):
361 file_path
= os
.path
.join(util
.getUserDirectoryPath(), os
.path
.split(item
.get_desktop_file_path())[1])
364 if not os
.path
.isfile(file_path
):
365 data
= open(item
.get_desktop_file_path()).read()
366 open(file_path
, 'w').write(data
)
367 self
.editor
._MenuEditor
__addUndo
([(file_type
, os
.path
.split(file_path
)[1]),])
369 self
.editor
._MenuEditor
__addUndo
([item
,])
370 if file_path
not in self
.edit_pool
:
371 self
.edit_pool
.append(file_path
)
372 process
= subprocess
.Popen(['gnome-desktop-item-edit', file_path
], env
=os
.environ
)
373 GObject
.timeout_add(100, self
.waitForEditProcess
, process
, file_path
)
375 def on_menu_tree_cursor_changed(self
, treeview
):
376 menus
, iter = treeview
.get_selection().get_selected()
377 menu_path
= menus
.get_path(iter)
378 item_tree
= self
.tree
.get_object('item_tree')
379 item_tree
.get_selection().unselect_all()
380 self
.loadItems(self
.menu_store
[menu_path
][2], menu_path
)
381 self
.tree
.get_object('edit_delete').set_sensitive(False)
382 self
.tree
.get_object('edit_revert_to_original').set_sensitive(False)
383 self
.tree
.get_object('edit_properties').set_sensitive(False)
384 self
.tree
.get_object('move_up_button').set_sensitive(False)
385 self
.tree
.get_object('move_down_button').set_sensitive(False)
386 self
.tree
.get_object('new_separator_button').set_sensitive(False)
387 self
.tree
.get_object('properties_button').set_sensitive(False)
388 self
.tree
.get_object('delete_button').set_sensitive(False)
390 def on_menu_tree_drag_data_get(self
, treeview
, context
, selection
, target_id
, etime
):
391 menus
, iter = treeview
.get_selection().get_selected()
392 self
.drag_data
= menus
[iter][2]
394 def on_menu_tree_drag_data_received(self
, treeview
, context
, x
, y
, selection
, info
, etime
):
395 menus
= treeview
.get_model()
396 drop_info
= treeview
.get_dest_row_at_pos(x
, y
)
397 types
= (Gtk
.TreeViewDropPosition
.BEFORE
, Gtk
.TreeViewDropPosition
.INTO_OR_BEFORE
)
399 path
, position
= drop_info
400 if position
not in types
:
401 context
.finish(False, False, etime
)
403 if selection
.target
in ('ALACARTE_ITEM_ROW', 'ALACARTE_MENU_ROW'):
404 if self
.drag_data
== None:
406 item
= self
.drag_data
407 new_parent
= menus
[path
][2]
408 treeview
.get_selection().select_path(path
)
409 if isinstance(item
, GMenu
.TreeEntry
):
410 self
.editor
.copyItem(item
, new_parent
)
411 elif isinstance(item
, GMenu
.TreeDirectory
):
412 if self
.editor
.moveMenu(item
, new_parent
) == False:
414 elif isinstance(item
, GMenu
.TreeSeparator
):
415 self
.editor
.moveSeparator(item
, new_parent
)
417 context
.finish(False, False, etime
)
418 context
.finish(True, True, etime
)
419 self
.drag_data
= None
421 def on_item_tree_show_toggled(self
, cell
, path
):
422 item
= self
.item_store
[path
][3]
423 if isinstance(item
, GMenu
.TreeSeparator
):
425 if self
.item_store
[path
][0]:
426 self
.editor
.setVisible(item
, False)
428 self
.editor
.setVisible(item
, True)
429 self
.item_store
[path
][0] = not self
.item_store
[path
][0]
431 def on_item_tree_cursor_changed(self
, treeview
):
432 items
, iter = treeview
.get_selection().get_selected()
435 item
= items
[iter][3]
436 self
.tree
.get_object('edit_delete').set_sensitive(True)
437 self
.tree
.get_object('new_separator_button').set_sensitive(True)
438 self
.tree
.get_object('delete_button').set_sensitive(True)
439 if self
.editor
.canRevert(item
):
440 self
.tree
.get_object('edit_revert_to_original').set_sensitive(True)
442 self
.tree
.get_object('edit_revert_to_original').set_sensitive(False)
443 if not isinstance(item
, GMenu
.TreeSeparator
):
444 self
.tree
.get_object('edit_properties').set_sensitive(True)
445 self
.tree
.get_object('properties_button').set_sensitive(True)
447 self
.tree
.get_object('edit_properties').set_sensitive(False)
448 self
.tree
.get_object('properties_button').set_sensitive(False)
451 if items
.get_path(iter).get_indices()[0] == 0:
452 self
.tree
.get_object('move_up_button').set_sensitive(False)
454 self
.tree
.get_object('move_up_button').set_sensitive(True)
457 if items
.get_path(iter).get_indices()[0] == (len(items
)-1):
458 self
.tree
.get_object('move_down_button').set_sensitive(False)
460 self
.tree
.get_object('move_down_button').set_sensitive(True)
462 def on_item_tree_row_activated(self
, treeview
, path
, column
):
463 self
.on_edit_properties_activate(None)
465 def on_item_tree_popup_menu(self
, item_tree
, event
=None):
466 model
, iter = item_tree
.get_selection().get_selected()
468 #don't show if it's not the right mouse button
469 if event
.button
!= 3:
471 button
= event
.button
472 event_time
= event
.time
473 info
= item_tree
.get_path_at_pos(int(event
.x
), int(event
.y
))
475 path
, col
, cellx
, celly
= info
476 item_tree
.grab_focus()
477 item_tree
.set_cursor(path
, col
, 0)
479 path
= model
.get_path(iter)
482 item_tree
.grab_focus()
483 item_tree
.set_cursor(path
, item_tree
.get_columns()[0], 0)
484 popup
= self
.tree
.get_object('edit_menu')
485 popup
.popup(None, None, None, None, button
, event_time
)
486 #without this shift-f10 won't work
489 def on_item_tree_drag_data_get(self
, treeview
, context
, selection
, target_id
, etime
):
490 items
, iter = treeview
.get_selection().get_selected()
491 self
.drag_data
= items
[iter][3]
493 def on_item_tree_drag_data_received(self
, treeview
, context
, x
, y
, selection
, info
, etime
):
494 items
= treeview
.get_model()
495 types_into
= (Gtk
.TreeViewDropPosition
.INTO_OR_BEFORE
, Gtk
.TreeViewDropPosition
.INTO_OR_AFTER
)
496 types_before
= (Gtk
.TreeViewDropPosition
.BEFORE
, Gtk
.TreeViewDropPosition
.INTO_OR_BEFORE
)
497 types_after
= (Gtk
.TreeViewDropPosition
.AFTER
, Gtk
.TreeViewDropPosition
.INTO_OR_AFTER
)
498 if selection
.target
== 'ALACARTE_ITEM_ROW':
499 drop_info
= treeview
.get_dest_row_at_pos(x
, y
)
502 if self
.drag_data
== None:
504 item
= self
.drag_data
505 # by default we assume, that the items stays in the same menu
506 destination
= item
.get_parent()
508 path
, position
= drop_info
509 target
= items
[path
][3]
510 # move the item to the directory, if the item was dropped into it
511 if isinstance(target
, GMenu
.TreeDirectory
) and (position
in types_into
):
512 # append the selected item to the choosen menu
514 elif position
in types_before
:
516 elif position
in types_after
:
519 # this does not happen
522 path
= (len(items
) - 1,)
523 after
= items
[path
][3]
524 if isinstance(item
, GMenu
.TreeEntry
):
525 self
.editor
.moveItem(item
, destination
, before
, after
)
526 elif isinstance(item
, GMenu
.TreeDirectory
):
527 if self
.editor
.moveMenu(item
, destination
, before
, after
) == False:
529 elif isinstance(item
, GMenu
.TreeSeparator
):
530 self
.editor
.moveSeparator(item
, destination
, before
, after
)
531 context
.finish(True, True, etime
)
532 elif selection
.target
== 'text/plain':
533 if selection
.data
== None:
535 menus
, iter = self
.tree
.get_object('menu_tree').get_selection().get_selected()
536 parent
= menus
[iter][2]
537 drop_info
= treeview
.get_dest_row_at_pos(x
, y
)
541 path
, position
= drop_info
542 if position
in types_before
:
543 before
= items
[path
][3]
545 after
= items
[path
][3]
547 path
= (len(items
) - 1,)
548 after
= items
[path
][3]
549 file_path
= urllib
.unquote(selection
.data
).strip()
550 if not file_path
.startswith('file:'):
552 myfile
= Gio
.File(uri
=file_path
)
553 file_info
= myfile
.query_info(Gio
.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE
)
554 content_type
= file_info
.get_content_type()
555 if content_type
== 'application/x-desktop':
556 input_stream
= myfile
.read()
557 keyfile
= GLib
.KeyFile()
558 keyfile
.load_from_data(input_stream
.read())
559 self
.editor
.createItem(parent
, before
, after
, KeyFile
=keyfile
)
560 elif content_type
in ('application/x-shellscript', 'application/x-executable'):
561 self
.editor
.createItem(parent
, before
, after
,
562 Name
=os
.path
.split(file_path
)[1].strip(),
563 Exec
=file_path
.replace('file://', '').strip(),
565 self
.drag_data
= None
567 def on_item_tree_key_press_event(self
, item_tree
, event
):
568 if event
.keyval
== Gdk
.KEY_Delete
:
569 self
.on_edit_delete_activate(item_tree
)
571 def on_move_up_button_clicked(self
, button
):
572 item_tree
= self
.tree
.get_object('item_tree')
573 items
, iter = item_tree
.get_selection().get_selected()
576 path
= items
.get_path(iter)
577 #at top, can't move up
578 if path
.get_indices()[0] == 0:
580 item
= items
[path
][3]
581 before
= items
[(path
.get_indices()[0] - 1,)][3]
582 if isinstance(item
, GMenu
.TreeEntry
):
583 self
.editor
.moveItem(item
, item
.get_parent(), before
=before
)
584 elif isinstance(item
, GMenu
.TreeDirectory
):
585 self
.editor
.moveMenu(item
, item
.get_parent(), before
=before
)
586 elif isinstance(item
, GMenu
.TreeSeparator
):
587 self
.editor
.moveSeparator(item
, item
.get_parent(), before
=before
)
589 def on_move_down_button_clicked(self
, button
):
590 item_tree
= self
.tree
.get_object('item_tree')
591 items
, iter = item_tree
.get_selection().get_selected()
594 path
= items
.get_path(iter)
595 #at bottom, can't move down
596 if path
.get_indices()[0] == (len(items
) - 1):
598 item
= items
[path
][3]
599 after
= items
[path
][3]
600 if isinstance(item
, GMenu
.TreeEntry
):
601 self
.editor
.moveItem(item
, item
.get_parent(), after
=after
)
602 elif isinstance(item
, GMenu
.TreeDirectory
):
603 self
.editor
.moveMenu(item
, item
.get_parent(), after
=after
)
604 elif isinstance(item
, GMenu
.TreeSeparator
):
605 self
.editor
.moveSeparator(item
, item
.get_parent(), after
=after
)
607 def on_mainwindow_undo(self
, accelgroup
, window
, keyval
, modifier
):
610 def on_mainwindow_redo(self
, accelgroup
, window
, keyval
, modifier
):
613 def on_help_button_clicked(self
, *args
):
614 Gtk
.show_uri(Gdk
.Screen
.get_default(), "ghelp:user-guide#menu-editor", Gtk
.get_current_event_time())
616 def on_revert_button_clicked(self
, button
):
617 dialog
= self
.tree
.get_object('revertdialog')
618 dialog
.set_transient_for(self
.tree
.get_object('mainwindow'))
620 if dialog
.run() == Gtk
.ResponseType
.YES
:
624 def on_close_button_clicked(self
, button
):
627 def on_properties_button_clicked(self
, button
):
628 self
.on_edit_properties_activate(None)
629 def on_delete_button_clicked(self
, button
):
630 self
.on_edit_delete_activate(None)
632 def on_style_set(self
, *args
):