2 #TODO: upcoming pipemenu stuff
5 from xdg import BaseDirectory
6 import re #This is to autoset file mode for *.desktop icons
14 class DeskmenuEditor(gtk.Window):
17 gtk.Window.__init__(self)
19 self.props.title = 'Compiz Deskmenu Editor'
20 self.props.icon_name = 'gtk-edit'
21 self.props.border_width = 12
22 self.set_size_request(400, 400)
23 self.model = gtk.TreeStore(object)
26 vbox = gtk.VBox(spacing=12)
28 scrolled = gtk.ScrolledWindow()
29 scrolled.props.hscrollbar_policy = gtk.POLICY_NEVER
30 scrolled.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC
31 treeview = gtk.TreeView(self.model)
32 treeview.set_reorderable(True)
33 cell = gtk.CellRendererText()
34 elements = gtk.TreeViewColumn('Item', cell)
35 elements.set_cell_data_func(cell, self.get_type)
36 treeview.append_column(elements)
38 name = gtk.TreeViewColumn('Name')
40 cell = gtk.CellRendererPixbuf()
41 name.pack_start(cell, False)
42 name.set_cell_data_func(cell, self.get_icon)
44 cell = gtk.CellRendererText()
46 name.set_cell_data_func(cell, self.get_name)
48 treeview.append_column(name)
49 scrolled.add(treeview)
50 vbox.pack_start(scrolled, True, True)
52 ('deskmenu-element', gtk.TARGET_SAME_WIDGET, 0),
53 ('text/uri-list', 0, 1),
55 treeview.enable_model_drag_source(gtk.gdk.BUTTON1_MASK, targets, gtk.gdk.ACTION_DEFAULT|gtk.gdk.ACTION_MOVE)
56 treeview.enable_model_drag_dest(targets, gtk.gdk.ACTION_MOVE)
58 treeview.connect('drag-data-get', self.on_drag_data_get)
59 treeview.connect('drag-data-received', self.on_drag_data_received)
61 treeview.connect('row-activated', self.on_row_activated)
63 treeview.connect('button-press-event', self.on_treeview_button_press_event)
66 self.selection = treeview.get_selection()
67 self.selection.connect('changed', self.on_selection_changed)
69 buttonbox = gtk.HButtonBox()
70 vbox.pack_end(buttonbox, False, False)
72 new = gtk.Button(stock=gtk.STOCK_NEW)
73 new.connect('clicked', self.on_new_clicked)
74 buttonbox.pack_start(new)
75 self.edit = gtk.Button(stock=gtk.STOCK_EDIT)
76 self.edit.connect('clicked', self.on_edit_clicked)
77 buttonbox.pack_start(self.edit)
78 self.delete = gtk.Button(stock=gtk.STOCK_DELETE)
79 self.delete.connect('clicked', self.on_delete_clicked)
80 buttonbox.pack_start(self.delete)
81 close = gtk.Button(stock=gtk.STOCK_CLOSE)
82 close.connect('clicked', self.on_close_clicked)
83 buttonbox.pack_end(close)
87 self.popup = gtk.Menu()
88 self.edit_menu = gtk.ImageMenuItem(stock_id=gtk.STOCK_EDIT)
89 self.edit_menu.connect('activate', self.on_edit_clicked)
90 self.popup.append(self.edit_menu)
91 self.delete_menu = gtk.ImageMenuItem(stock_id=gtk.STOCK_DELETE)
92 self.delete_menu.connect('activate', self.on_delete_clicked)
93 self.popup.append(self.delete_menu)
96 self.connect('destroy', self.on_close_clicked)
100 def add_menu(self, m, parent=None):
101 for item in m.children:
102 iter = self.model.append(parent, [item])
103 if item.node.tag == 'menu':
104 self.add_menu(item, iter)
106 def get_name(self, column, cell, model, iter):
107 name = model.get_value(iter, 0).get_name()
110 cell.set_property('text', name)
112 def get_type(self, column, cell, model, iter):
113 typ = model.get_value(iter, 0).get_type()
116 cell.set_property('text', typ)
118 def get_icon(self, column, cell, model, iter):
119 icon = model.get_value(iter, 0).get_icon()
120 icon_mode = model.get_value(iter, 0).get_icon_mode()
122 if icon_mode is not None:
123 w = gtk.icon_size_lookup(gtk.ICON_SIZE_MENU)
124 cell.set_property('pixbuf', gtk.gdk.pixbuf_new_from_file_at_size(icon, w[0], w[0]))
125 cell.set_property('icon-name', None) #possibly reduntant safety measure
127 cell.set_property('icon-name', icon)
128 cell.set_property('pixbuf', None) #possibly reduntant safety measure
130 cell.set_property('icon-name', None)
131 cell.set_property('pixbuf', None)
133 def on_new_clicked(self, widget):
135 NewItemDialog(*self.selection.get_selected())
137 def on_edit_clicked(self, widget):
139 EditItemDialog(*self.selection.get_selected())
141 def on_delete_clicked(self, widget):
143 model, row = self.selection.get_selected()
147 current = model[row][0].node
149 if current.tag == 'menu' and len(current):
150 warning = gtk.MessageDialog(self, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_NONE, 'Delete menu element with %s children?' %len(current))
151 warning.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_DELETE, gtk.RESPONSE_ACCEPT)
152 if warning.run() != gtk.RESPONSE_ACCEPT:
157 parent = model[row].parent
158 if parent is not None:
159 parent = parent[0].node
162 parent.remove(current)
167 def on_close_clicked(self, widget):
172 def on_drag_data_get(self, treeview, context, selection, target_id,
174 treeselection = treeview.get_selection()
175 model, iter = treeselection.get_selected()
176 data = model.get_string_from_iter(iter)
177 selection.set(selection.target, 8, data)
179 def on_drag_data_received(self, treeview, context, x, y, selection,
181 model = treeview.get_model()
182 data = selection.data
184 drop_info = treeview.get_dest_row_at_pos(x, y)
185 if selection.type == 'deskmenu-element':
186 source = model[data][0]
188 path, position = drop_info
189 siter = model.get_iter(data)
190 diter = model.get_iter(path)
192 if model.get_path(model.get_iter_from_string(data)) == path:
195 dest = model[path][0]
196 if context.action == gtk.gdk.ACTION_MOVE:
197 source.node.getparent().remove(source.node)
199 if dest.node.tag == 'menu' and position in (gtk.TREE_VIEW_DROP_INTO_OR_BEFORE,
200 gtk.TREE_VIEW_DROP_INTO_OR_AFTER):
201 dest.node.append(source.node)
202 fiter = model.append(diter, row=(source,))
204 i = dest.node.getparent().index(dest.node)
205 if position in (gtk.TREE_VIEW_DROP_INTO_OR_BEFORE,
206 gtk.TREE_VIEW_DROP_BEFORE):
207 dest.node.getparent().insert(i, source.node)
208 fiter = model.insert_before(None, diter, row=(source,))
210 dest.node.getparent().insert(i+1, source.node)
211 fiter = model.insert_after(None, diter, row=(source,))
213 if model.iter_has_child(siter):
214 citer = model.iter_children(siter)
215 while citer is not None:
216 model.append(fiter, row=(model[citer][0],))
217 citer = model.iter_next(citer)
218 if context.action == gtk.gdk.ACTION_MOVE:
219 context.finish(True, True, etime)
221 elif selection.type == 'text/uri-list':
223 path, position = drop_info
224 uri = selection.data.replace('file:///', '/').strip()
225 entry = ConfigParser.ConfigParser()
227 launcher = Launcher()
228 launcher.name = etree.SubElement(launcher.node, 'name')
229 launcher.icon = etree.SubElement(launcher.node, 'icon')
230 launcher.command = etree.SubElement(launcher.node, 'command')
232 launcher.name.text = entry.get('Desktop Entry', 'Name')
233 if re.search("/", entry.get('Desktop Entry', 'Icon')):
234 launcher.icon.attrib['mode1'] = 'file'
235 launcher.icon.text = entry.get('Desktop Entry', 'Icon')
236 #launcher.icon.text = entry.get('Desktop Entry', 'Icon').split('.')[0]
237 launcher.command.text = entry.get('Desktop Entry', 'Exec').split('%')[0]
238 except ConfigParser.Error:
240 dest = model[path][0]
241 diter = model.get_iter(path)
242 if dest.node.tag == 'menu' and position in (gtk.TREE_VIEW_DROP_INTO_OR_BEFORE,
243 gtk.TREE_VIEW_DROP_INTO_OR_AFTER):
244 dest.node.append(launcher.node)
245 fiter = model.append(diter, row=(launcher,))
247 i = dest.node.getparent().index(dest.node)
248 if position in (gtk.TREE_VIEW_DROP_INTO_OR_BEFORE,
249 gtk.TREE_VIEW_DROP_BEFORE):
250 dest.node.getparent().insert(i, launcher.node)
251 fiter = model.insert_before(None, diter, row=(launcher,))
253 dest.node.getparent().insert(i+1, launcher.node)
254 fiter = model.insert_after(None, diter, row=(launcher,))
255 if context.action == gtk.gdk.ACTION_MOVE:
256 context.finish(True, True, etime)
262 def on_selection_changed(self, selection):
264 model, row = selection.get_selected()
266 sensitive = row and model.get_value(row, 0).editable
268 self.edit.props.sensitive = sensitive
269 self.edit_menu.props.sensitive = sensitive
270 self.delete.props.sensitive = row
271 self.delete_menu.props.sensitive = row
273 def on_row_activated(self, treeview, path, view_column):
275 model = treeview.get_model()
276 EditItemDialog(model, model.get_iter(path))
278 def on_treeview_button_press_event(self, treeview, event):
279 if event.button == 3:
280 pthinfo = treeview.get_path_at_pos(int(event.x), int(event.y))
281 if pthinfo is not None:
282 path, col, cellx, celly = pthinfo
283 treeview.grab_focus()
284 treeview.set_cursor(path, col, 0)
285 self.popup.popup(None, None, None, event.button, event.time)
289 class NewItemDialog(gtk.Dialog):
291 elementlist = ['Launcher', 'Menu', 'Separator', 'Windows List',
292 'Viewports List', 'Reload']
294 def __init__(self, model, row):
295 gtk.Dialog.__init__(self, 'New Item', None, 0, None)
297 self.set_size_request(250, 250)
299 self.props.border_width = 6
300 self.vbox.props.spacing = 6
301 self.set_has_separator(False)
302 self.treeview = self.make_treeview()
304 scroll = gtk.ScrolledWindow()
305 scroll.add(self.treeview)
306 scroll.props.hscrollbar_policy = gtk.POLICY_NEVER
307 scroll.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC
308 self.vbox.pack_start(scroll, True, True)
310 self.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
311 gtk.STOCK_NEW, gtk.RESPONSE_ACCEPT)
313 self.action_area.props.border_width = 0
319 if self.run() == gtk.RESPONSE_ACCEPT:
320 m, r = self.treeview.get_selection().get_selected()
322 elementname = m[r][0]
326 parent = sibling = None
328 current = model[row][0]
329 if current.node.tag == 'menu':
332 parent = model[row].parent
333 if parent is not None:
337 parentelement = model[parent][0]
341 element = elementsbyname[elementname]()
343 position = parentelement.node.index(current.node) + 1
344 parentelement.node.insert(position, element.node)
345 model.insert_after(parent, sibling, row=(element,))
347 model.append(parent, row=(element,))
348 parentelement.node.append(element.node)
353 if element and element.editable:
354 EditItemDialog(element=element)
356 def make_treeview(self):
357 model = gtk.ListStore(str)
358 for el in self.elementlist:
361 treeview = gtk.TreeView(model)
362 column = gtk.TreeViewColumn(None, gtk.CellRendererText(), text=0)
363 treeview.set_headers_visible(False)
364 treeview.append_column(column)
366 treeview.connect('row-activated', self.on_row_activated)
369 def on_row_activated(self, treeview, path, view_column):
370 self.response(gtk.RESPONSE_ACCEPT)
373 class EditItemDialog(gtk.Dialog):
375 def __init__(self, model=None, row=None, element=None):
376 gtk.Dialog.__init__(self, 'Edit Item', None, 0, None)
378 self.set_size_request(300, -1)
380 self.props.border_width = 6
381 self.vbox.props.spacing = 6
382 self.set_has_separator(False)
387 element = model.get_value(row, 0)
389 if not element.editable:
392 for widget in element.get_options():
393 self.vbox.pack_start(widget, False, False)
395 self.add_buttons(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
406 def __init__(self, node=None, parent=None, type=None):
408 self.editable = False
411 self.node = etree.Element('item')
413 self.node.attrib['type'] = type
427 def get_icon_mode(self):
430 class Launcher(Item):
432 def __init__(self, node=None):
434 Item.__init__(self, node)
437 self.node = etree.Element('item', type='launcher')
443 subnode = self.node.find('name')
444 if subnode is not None:
446 if subnode.attrib.get('mode') == 'exec':
447 name = 'exec: %s' %name
456 iconnode = self.node.find('icon')
457 if iconnode is not None:
462 def get_icon_mode(self):
463 iconnode = self.node.find('icon')
464 if iconnode is not None:
465 if iconnode.attrib.get('mode1') == 'file':
466 return iconnode.attrib.get('mode1')
470 def get_options(self):
473 sgroup = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
476 label.set_alignment(0, 0.5)
477 sgroup.add_widget(label)
478 label.set_markup('<b>Name:</b>')
481 namenode = self.node.find('name')
482 if namenode is not None:
486 widget.props.text = name
487 widget.connect('changed', self.on_subnode_changed, 'name')
490 hbox.pack_start(label)
491 hbox.pack_start(widget, True, True)
495 label.set_alignment(0, 0.5)
496 sgroup.add_widget(label)
497 label.set_markup('<b>Name mode:</b>')
498 widget = gtk.combo_box_new_text()
499 widget.append_text('Normal')
500 widget.append_text('Execute')
501 widget.props.active = namenode is not None and namenode.attrib.get('mode') == 'exec'
502 widget.connect('changed', self.on_name_mode_changed)
505 hbox.pack_start(label)
506 hbox.pack_start(widget, True, True)
510 label.set_alignment(0, 0.5)
511 sgroup.add_widget(label)
512 label.set_markup('<b>Icon:</b>')
515 iconnode = self.node.find('icon')
516 if iconnode is not None:
520 widget.props.text = icon
521 widget.connect('changed', self.on_subnode_changed, 'icon')
524 hbox.pack_start(label)
525 hbox.pack_start(widget, True, True)
529 label.set_alignment(0, 0.5)
530 sgroup.add_widget(label)
531 label.set_markup('<b>Icon mode:</b>')
532 widget = gtk.combo_box_new_text()
533 widget.append_text('Normal')
534 widget.append_text('File Path')
535 widget.props.active = iconnode is not None and iconnode.attrib.get('mode1') == 'file'
536 widget.connect('changed', self.on_icon_mode_changed)
539 hbox.pack_start(label)
540 hbox.pack_start(widget, True, True)
544 label.set_alignment(0, 0.5)
545 sgroup.add_widget(label)
546 label.set_markup('<b>Command:</b>')
548 commandnode = self.node.find('command')
549 if commandnode is not None:
550 command = commandnode.text
553 widget.props.text = command
554 widget.connect('changed', self.on_subnode_changed, 'command')
557 hbox.pack_start(label)
558 hbox.pack_start(widget, True, True)
563 def on_subnode_changed(self, widget, tag):
564 text = widget.props.text
565 subnode = self.node.find(tag)
568 subnode = etree.SubElement(self.node, tag)
571 if subnode is not None:
572 self.node.remove(subnode)
574 def on_name_mode_changed(self, widget):
575 namenode = self.node.find('name')
576 if widget.props.active:
578 namenode = etree.SubElement(self.node, 'name')
579 namenode.attrib['mode'] = 'exec'
580 elif 'mode' in namenode.attrib:
581 del namenode.attrib['mode']
583 def on_icon_mode_changed(self, widget):
584 iconnode = self.node.find('icon')
585 if widget.props.active:
587 iconnode = etree.SubElement(self.node, 'icon')
588 iconnode.attrib['mode1'] = 'file'
589 elif 'mode1' in iconnode.attrib:
590 del iconnode.attrib['mode1']
592 class Windowlist(Item):
594 def __init__(self, node=None):
595 Item.__init__(self, node, type='windowlist')
599 iconnode = self.node.find('icon')
600 if iconnode is not None:
605 def get_icon_mode(self):
606 iconnode = self.node.find('icon')
607 if iconnode is not None:
608 if iconnode.attrib.get('mode1') == 'file':
609 return iconnode.attrib.get('mode1')
613 def get_options(self):
615 sgroup = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
618 label.set_alignment(0, 0.5)
619 sgroup.add_widget(label)
620 label.set_markup('<b>Icon:</b>')
623 iconnode = self.node.find('icon')
624 if iconnode is not None:
628 widget.props.text = icon
629 widget.connect('changed', self.on_subnode_changed, 'icon')
632 hbox.pack_start(label)
633 hbox.pack_start(widget, True, True)
637 label.set_alignment(0, 0.5)
638 sgroup.add_widget(label)
639 label.set_markup('<b>Icon mode:</b>')
640 widget = gtk.combo_box_new_text()
641 widget.append_text('Normal')
642 widget.append_text('File Path')
643 widget.props.active = iconnode is not None and iconnode.attrib.get('mode1') == 'file'
644 widget.connect('changed', self.on_icon_mode_changed)
647 hbox.pack_start(label)
648 hbox.pack_start(widget, True, True)
653 def on_subnode_changed(self, widget, tag):
654 text = widget.props.text
655 subnode = self.node.find(tag)
658 subnode = etree.SubElement(self.node, tag)
661 if subnode is not None:
662 self.node.remove(subnode)
664 def on_icon_mode_changed(self, widget):
665 iconnode = self.node.find('icon')
666 if widget.props.active:
668 iconnode = etree.SubElement(self.node, 'icon')
669 iconnode.attrib['mode1'] = 'file'
670 elif 'mode1' in iconnode.attrib:
671 del iconnode.attrib['mode1']
674 return 'Windows list'
676 class Viewportlist(Item):
678 def __init__(self, node=None): #change to be an attribute of viewportlist
679 Item.__init__(self, node, type='viewportlist')
681 self.wrap = self.node.find('wrap')
684 return 'Viewports list'
687 iconnode = self.node.find('icon')
688 if iconnode is not None:
693 def get_icon_mode(self):
694 iconnode = self.node.find('icon')
695 if iconnode is not None:
696 if iconnode.attrib.get('mode1') == 'file':
697 return iconnode.attrib.get('mode1')
702 def get_options(self):
704 sgroup = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
705 widget = gtk.CheckButton("Wrap Viewports")
706 widget.props.active = self.get_wrap()
707 widget.connect('toggled', self.on_wrap_changed)
708 retlist.append(widget)
711 label.set_alignment(0, 0.5)
712 sgroup.add_widget(label)
713 label.set_markup('<b>Icon:</b>')
716 iconnode = self.node.find('icon')
717 if iconnode is not None:
721 widget.props.text = icon
722 widget.connect('changed', self.on_subnode_changed, 'icon')
725 hbox.pack_start(label)
726 hbox.pack_start(widget, True, True)
730 label.set_alignment(0, 0.5)
731 sgroup.add_widget(label)
732 label.set_markup('<b>Icon mode:</b>')
733 widget = gtk.combo_box_new_text()
734 widget.append_text('Normal')
735 widget.append_text('File Path')
736 widget.props.active = iconnode is not None and iconnode.attrib.get('mode1') == 'file'
737 widget.connect('changed', self.on_icon_mode_changed)
740 hbox.pack_start(label)
741 hbox.pack_start(widget, True, True)
747 if self.wrap is not None:
748 return self.wrap.text == 'true'
751 def on_subnode_changed(self, widget, tag):
752 text = widget.props.text
753 subnode = self.node.find(tag)
756 subnode = etree.SubElement(self.node, tag)
759 if subnode is not None:
760 self.node.remove(subnode)
762 def on_wrap_changed(self, widget):
763 if self.wrap is None:
764 self.wrap = etree.SubElement(self.node, 'wrap')
765 if widget.props.active:
769 self.wrap.text = text
771 def on_icon_mode_changed(self, widget):
772 iconnode = self.node.find('icon')
773 if widget.props.active:
775 iconnode = etree.SubElement(self.node, 'icon')
776 iconnode.attrib['mode1'] = 'file'
777 elif 'mode1' in iconnode.attrib:
778 del iconnode.attrib['mode1']
782 def __init__(self, node=None):
783 Item.__init__(self, node, type='reload')
790 iconnode = self.node.find('icon')
791 if iconnode is not None:
796 def get_icon_mode(self):
797 iconnode = self.node.find('icon')
798 if iconnode is not None:
799 if iconnode.attrib.get('mode1') == 'file':
800 return iconnode.attrib.get('mode1')
805 def get_options(self):
807 sgroup = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
810 label.set_alignment(0, 0.5)
811 sgroup.add_widget(label)
812 label.set_markup('<b>Icon:</b>')
815 iconnode = self.node.find('icon')
816 if iconnode is not None:
820 widget.props.text = icon
821 widget.connect('changed', self.on_subnode_changed, 'icon')
824 hbox.pack_start(label)
825 hbox.pack_start(widget, True, True)
829 label.set_alignment(0, 0.5)
830 sgroup.add_widget(label)
831 label.set_markup('<b>Icon mode:</b>')
832 widget = gtk.combo_box_new_text()
833 widget.append_text('Normal')
834 widget.append_text('File Path')
835 widget.props.active = iconnode is not None and iconnode.attrib.get('mode1') == 'file'
836 widget.connect('changed', self.on_icon_mode_changed)
839 hbox.pack_start(label)
840 hbox.pack_start(widget, True, True)
843 hbox.pack_start(label)
844 hbox.pack_start(widget, True, True)
849 def on_subnode_changed(self, widget, tag):
850 text = widget.props.text
851 subnode = self.node.find(tag)
854 subnode = etree.SubElement(self.node, tag)
857 if subnode is not None:
858 self.node.remove(subnode)
860 def on_icon_mode_changed(self, widget):
861 iconnode = self.node.find('icon')
862 if widget.props.active:
864 iconnode = etree.SubElement(self.node, 'icon')
865 iconnode.attrib['mode1'] = 'file'
866 elif 'mode1' in iconnode.attrib:
867 del iconnode.attrib['mode1']
869 class Separator(object):
871 def __init__(self, node=None, parent=None):
873 self.editable = False
874 if self.node is None:
875 self.node = etree.Element('separator')
886 def get_icon_mode(self):
891 def __init__(self, node=None):
897 self.node = etree.Element('menu', name='')
899 for child in self.node.getchildren():
901 self.children.append(self.make_child(child))
906 def make_child(self, child):
907 return elements[child.tag](child)
910 name = self.node.attrib.get('name', '')
911 if self.node.attrib.get('mode') == 'exec':
912 name = 'exec: %s' %name
915 #TODO: make this say exec: $name when it detects mode
917 return self.node.attrib.get('icon', '')
919 def get_icon_mode(self):
920 if self.node.attrib.get('mode1') == 'file':
921 return self.node.attrib.get('mode1')
928 def get_options(self):
931 sgroup = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
934 label.set_alignment(0, 0.5)
935 label.set_markup('<b>Name:</b>')
937 widget.props.text = self.node.attrib.get('name', '')
938 widget.connect('changed', self.on_name_changed)
941 hbox.pack_start(label)
942 hbox.pack_start(widget, True, True)
946 label.set_alignment(0, 0.5)
947 sgroup.add_widget(label)
948 label.set_markup('<b>Name mode:</b>')
949 widget = gtk.combo_box_new_text()
950 widget.append_text('Normal')
951 widget.append_text('Execute')
952 widget.props.active = self.node.attrib.get('name') is not None and self.node.attrib.get('mode') == 'exec'
953 widget.connect('changed', self.on_name_mode_changed)
956 hbox.pack_start(label)
957 hbox.pack_start(widget, True, True)
960 #TODO:Make this actually edit icon
962 label.set_alignment(0, 0.5)
963 sgroup.add_widget(label)
964 label.set_markup('<b>Icon:</b>')
966 if self.node.attrib.get('icon') is not None:
967 widget.props.text = self.node.attrib.get('icon')
969 widget.props.text = ''
970 #widget.props.text = self.node.attrib.get('icon')
971 widget.connect('changed', self.on_icon_changed)
974 hbox.pack_start(label)
975 hbox.pack_start(widget, True, True)
979 label.set_alignment(0, 0.5)
980 sgroup.add_widget(label)
981 label.set_markup('<b>Icon mode:</b>')
982 widget = gtk.combo_box_new_text()
983 widget.append_text('Normal')
984 widget.append_text('File Path')
985 widget.props.active = self.node.attrib.get('icon') is not None and self.node.attrib.get('mode1') == 'file'
986 widget.connect('changed', self.on_icon_mode_changed)
989 hbox.pack_start(label)
990 hbox.pack_start(widget, True, True)
995 def on_name_changed(self, widget):
996 self.node.attrib['name'] = widget.props.text
997 def on_name_mode_changed(self, widget): #EDIT THIS
998 if widget.props.active:
999 self.node.attrib['mode'] = 'exec'
1000 elif 'mode' in self.node.attrib:
1001 del self.node.attrib['mode']
1002 def on_icon_changed(self, widget):
1003 if widget.props.text != '':
1004 self.node.attrib['icon'] = widget.props.text
1006 del self.node.attrib['icon']
1007 def on_icon_mode_changed(self, widget): #EDIT THIS
1008 if widget.props.active:
1009 self.node.attrib['mode1'] = 'file'
1010 elif 'mode1' in self.node.attrib:
1011 del self.node.attrib['mode1']
1014 'launcher': Launcher,
1015 'windowlist': Windowlist,
1016 'viewportlist': Viewportlist,
1021 def make_item(node):
1023 itemtype = node.attrib.get('type')
1024 return itemtypes.get(itemtype, Item)(node)
1027 def indent(elem, level=0):
1028 i = "\n" + level*" "
1030 if not elem.text or not elem.text.strip():
1034 if not e.tail or not e.tail.strip():
1036 if not e.tail or not e.tail.strip():
1039 if level and (not elem.tail or not elem.tail.strip()):
1045 menufile.write(open(os.path.join(configdir, 'menu.xml'), 'w'))
1049 bus.get_object('org.compiz_fusion.deskmenu',
1050 '/org/compiz_fusion/deskmenu/menu').reload()
1051 except dbus.DBusException:
1054 elements = {'menu': Menu, 'item': make_item, 'separator': Separator}
1057 'Launcher': Launcher,
1058 'Windows List': Windowlist,
1059 'Viewports List': Viewportlist,
1061 'Separator': Separator,
1066 if __name__ == '__main__':
1070 bus = dbus.SessionBus()
1071 except dbus.DBusException:
1076 filename = BaseDirectory.load_first_config('compiz/deskmenu/menu.xml')
1077 menufile = etree.parse(filename)
1078 root = menufile.getroot()
1080 configdir = BaseDirectory.save_config_path('compiz/deskmenu')