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()
379 menu_path
= menus
.get_path(iter)
380 item_tree
= self
.tree
.get_object('item_tree')
381 item_tree
.get_selection().unselect_all()
382 self
.loadItems(self
.menu_store
[menu_path
][2], menu_path
)
383 self
.tree
.get_object('edit_delete').set_sensitive(False)
384 self
.tree
.get_object('edit_revert_to_original').set_sensitive(False)
385 self
.tree
.get_object('edit_properties').set_sensitive(False)
386 self
.tree
.get_object('move_up_button').set_sensitive(False)
387 self
.tree
.get_object('move_down_button').set_sensitive(False)
388 self
.tree
.get_object('new_separator_button').set_sensitive(False)
389 self
.tree
.get_object('properties_button').set_sensitive(False)
390 self
.tree
.get_object('delete_button').set_sensitive(False)
392 def on_menu_tree_drag_data_get(self
, treeview
, context
, selection
, target_id
, etime
):
393 menus
, iter = treeview
.get_selection().get_selected()
394 self
.drag_data
= menus
[iter][2]
396 def on_menu_tree_drag_data_received(self
, treeview
, context
, x
, y
, selection
, info
, etime
):
397 menus
= treeview
.get_model()
398 drop_info
= treeview
.get_dest_row_at_pos(x
, y
)
399 types
= (Gtk
.TreeViewDropPosition
.BEFORE
, Gtk
.TreeViewDropPosition
.INTO_OR_BEFORE
)
401 path
, position
= drop_info
402 if position
not in types
:
403 context
.finish(False, False, etime
)
405 if selection
.target
in ('ALACARTE_ITEM_ROW', 'ALACARTE_MENU_ROW'):
406 if self
.drag_data
== None:
408 item
= self
.drag_data
409 new_parent
= menus
[path
][2]
410 treeview
.get_selection().select_path(path
)
411 if isinstance(item
, GMenu
.TreeEntry
):
412 self
.editor
.copyItem(item
, new_parent
)
413 elif isinstance(item
, GMenu
.TreeDirectory
):
414 if self
.editor
.moveMenu(item
, new_parent
) == False:
416 elif isinstance(item
, GMenu
.TreeSeparator
):
417 self
.editor
.moveSeparator(item
, new_parent
)
419 context
.finish(False, False, etime
)
420 context
.finish(True, True, etime
)
421 self
.drag_data
= None
423 def on_item_tree_show_toggled(self
, cell
, path
):
424 item
= self
.item_store
[path
][3]
425 if isinstance(item
, GMenu
.TreeSeparator
):
427 if self
.item_store
[path
][0]:
428 self
.editor
.setVisible(item
, False)
430 self
.editor
.setVisible(item
, True)
431 self
.item_store
[path
][0] = not self
.item_store
[path
][0]
433 def on_item_tree_cursor_changed(self
, treeview
):
434 items
, iter = treeview
.get_selection().get_selected()
437 item
= items
[iter][3]
438 self
.tree
.get_object('edit_delete').set_sensitive(True)
439 self
.tree
.get_object('new_separator_button').set_sensitive(True)
440 self
.tree
.get_object('delete_button').set_sensitive(True)
441 if self
.editor
.canRevert(item
):
442 self
.tree
.get_object('edit_revert_to_original').set_sensitive(True)
444 self
.tree
.get_object('edit_revert_to_original').set_sensitive(False)
445 if not isinstance(item
, GMenu
.TreeSeparator
):
446 self
.tree
.get_object('edit_properties').set_sensitive(True)
447 self
.tree
.get_object('properties_button').set_sensitive(True)
449 self
.tree
.get_object('edit_properties').set_sensitive(False)
450 self
.tree
.get_object('properties_button').set_sensitive(False)
453 if items
.get_path(iter).get_indices()[0] == 0:
454 self
.tree
.get_object('move_up_button').set_sensitive(False)
456 self
.tree
.get_object('move_up_button').set_sensitive(True)
459 if items
.get_path(iter).get_indices()[0] == (len(items
)-1):
460 self
.tree
.get_object('move_down_button').set_sensitive(False)
462 self
.tree
.get_object('move_down_button').set_sensitive(True)
464 def on_item_tree_row_activated(self
, treeview
, path
, column
):
465 self
.on_edit_properties_activate(None)
467 def on_item_tree_popup_menu(self
, item_tree
, event
=None):
468 model
, iter = item_tree
.get_selection().get_selected()
470 #don't show if it's not the right mouse button
471 if event
.button
!= 3:
473 button
= event
.button
474 event_time
= event
.time
475 info
= item_tree
.get_path_at_pos(int(event
.x
), int(event
.y
))
477 path
, col
, cellx
, celly
= info
478 item_tree
.grab_focus()
479 item_tree
.set_cursor(path
, col
, 0)
481 path
= model
.get_path(iter)
484 item_tree
.grab_focus()
485 item_tree
.set_cursor(path
, item_tree
.get_columns()[0], 0)
486 popup
= self
.tree
.get_object('edit_menu')
487 popup
.popup(None, None, None, None, button
, event_time
)
488 #without this shift-f10 won't work
491 def on_item_tree_drag_data_get(self
, treeview
, context
, selection
, target_id
, etime
):
492 items
, iter = treeview
.get_selection().get_selected()
493 self
.drag_data
= items
[iter][3]
495 def on_item_tree_drag_data_received(self
, treeview
, context
, x
, y
, selection
, info
, etime
):
496 items
= treeview
.get_model()
497 types_into
= (Gtk
.TreeViewDropPosition
.INTO_OR_BEFORE
, Gtk
.TreeViewDropPosition
.INTO_OR_AFTER
)
498 types_before
= (Gtk
.TreeViewDropPosition
.BEFORE
, Gtk
.TreeViewDropPosition
.INTO_OR_BEFORE
)
499 types_after
= (Gtk
.TreeViewDropPosition
.AFTER
, Gtk
.TreeViewDropPosition
.INTO_OR_AFTER
)
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_before
:
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
):