mirror of
https://github.com/archlinux/aur.git
synced 2026-03-05 15:42:45 +01:00
3504 lines
111 KiB
Diff
Executable file
3504 lines
111 KiB
Diff
Executable file
diff -aur compiz-deskmenu/Makefile compiz-deskmenu3/Makefile
|
|
--- compiz-deskmenu/Makefile 2008-03-14 16:25:23.000000000 -0700
|
|
+++ compiz-deskmenu3/Makefile 2010-11-15 15:58:20.000000000 -0800
|
|
@@ -1,34 +1,24 @@
|
|
PREFIX := /usr
|
|
|
|
-CPPFLAGS := `pkg-config --cflags dbus-glib-1 gdk-2.0 gtk+-2.0 libwnck-1.0`
|
|
-CPPFLAGS_CLIENT := `pkg-config --cflags dbus-glib-1`
|
|
+CPPFLAGS := `pkg-config --cflags gdk-2.0 gtk+-2.0 libwnck-1.0`
|
|
WARNINGS := -Wall -Wextra -Wno-unused-parameter
|
|
CFLAGS := -O2 $(WARNINGS)
|
|
-LDFLAGS := `pkg-config --libs dbus-glib-1 gdk-2.0 gtk+-2.0 libwnck-1.0`
|
|
+LDFLAGS := `pkg-config --libs gdk-2.0 gtk+-2.0 libwnck-1.0`
|
|
LDFLAGS_CLIENT := `pkg-config --libs dbus-glib-1`
|
|
|
|
-all: compiz-deskmenu-menu compiz-deskmenu
|
|
+all: compiz-deskmenu
|
|
|
|
-compiz-deskmenu: deskmenu.c deskmenu-common.h
|
|
- $(CC) $(CPPFLAGS_CLIENT) $(CFLAGS) $(LDFLAGS_CLIENT) -o $@ $<
|
|
-
|
|
-compiz-deskmenu-menu: deskmenu-menu.c deskmenu-wnck.c deskmenu-wnck.h deskmenu-glue.h deskmenu-common.h deskmenu-menu.h
|
|
+compiz-deskmenu: deskmenu-menu.c deskmenu-wnck.c deskmenu-wnck.h deskmenu-menu.h
|
|
|
|
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ deskmenu-menu.c deskmenu-wnck.c
|
|
|
|
-deskmenu-glue.h: deskmenu-service.xml
|
|
- dbus-binding-tool --mode=glib-server --prefix=deskmenu --output=$@ $^
|
|
-
|
|
install: all
|
|
mkdir -p $(DESTDIR)$(PREFIX)/bin/
|
|
install compiz-deskmenu $(DESTDIR)$(PREFIX)/bin/
|
|
- install compiz-deskmenu-menu $(DESTDIR)$(PREFIX)/bin/
|
|
install compiz-deskmenu-editor $(DESTDIR)$(PREFIX)/bin/
|
|
mkdir -p $(DESTDIR)/etc/xdg/compiz/deskmenu/
|
|
install menu.xml $(DESTDIR)/etc/xdg/compiz/deskmenu/
|
|
- mkdir -p $(DESTDIR)$(PREFIX)/share/dbus-1/services/
|
|
- install org.compiz_fusion.deskmenu.service $(DESTDIR)$(PREFIX)/share/dbus-1/services/
|
|
|
|
clean:
|
|
- rm -f compiz-deskmenu compiz-deskmenu-menu deskmenu-glue.h
|
|
+ rm -f compiz-deskmenu
|
|
|
|
diff -aur compiz-deskmenu/README compiz-deskmenu3/README
|
|
--- compiz-deskmenu/README 2008-03-14 16:25:23.000000000 -0700
|
|
+++ compiz-deskmenu3/README 2010-11-16 17:55:54.000000000 -0800
|
|
@@ -1,10 +1,11 @@
|
|
Compiz Deskmenu
|
|
+== Credits ==
|
|
+Kudos to Christopher Williams for the excellent program. This new version contains several updates.
|
|
|
|
=== Requirements ===
|
|
|
|
* A recent version of GLib 2.x and GTK+ 2.x
|
|
* libwnck (2.20 is probably best, but not strictly required)
|
|
- * dbus (you must have a running session bus) and dbus-glib
|
|
|
|
It does not strictly require compiz (but it does need a recent version of the
|
|
vpswitch plugin for 'Initiate on Desktop' to work)
|
|
@@ -48,15 +49,13 @@
|
|
* separator: a simple GtkSeparatorMenuItem
|
|
* windowlist: libwnck-based window list menu.
|
|
* viewportlist: libwnck-based viewport list menu.
|
|
- * reload: reload button (it actually quits the menu)
|
|
+ * pipe: dynamically creates any other menu item, as long as the script
|
|
+ you make formats your entries properly
|
|
|
|
-Menu editor coming soon.
|
|
+Also, you can edit other menu files by doing this:
|
|
+compiz-deskmenu-editor /path/to/file
|
|
|
|
=== Implementation ===
|
|
|
|
-It compiles into two binaries, compiz-deskmenu and compiz-deskmenu-menu.
|
|
-compiz-deskmenu is a simple dbus client that connects
|
|
-to org.compiz_fusion.deskmenu and calls the show method. The actual menu is
|
|
-compiz-deskmenu-menu, but you shouldn't ever need to manually launch it; the
|
|
-dbus service file will cause it to be automatically spawned when the name is
|
|
-requested.
|
|
+Compiz-deskmenu compiles into one binary, which is what parses and
|
|
+displays the menu. If demanded, an apwal-esque version of this will be on its way.
|
|
diff -aur compiz-deskmenu/compiz-deskmenu-editor compiz-deskmenu3/compiz-deskmenu-editor
|
|
--- compiz-deskmenu/compiz-deskmenu-editor 2008-03-14 16:25:23.000000000 -0700
|
|
+++ compiz-deskmenu3/compiz-deskmenu-editor 2010-11-16 17:53:13.000000000 -0800
|
|
@@ -1,734 +1,1070 @@
|
|
-#!/usr/bin/env python
|
|
-
|
|
+#!/usr/bin/env python2
|
|
+#TODO: An actual icon dialog and editing non-default files
|
|
+import sys
|
|
import gtk, os
|
|
from lxml import etree
|
|
from xdg import BaseDirectory
|
|
+import re #This is to autoset file mode for *.desktop icons
|
|
import ConfigParser
|
|
|
|
-try:
|
|
- import dbus
|
|
-except ImportError:
|
|
- dbus = None
|
|
-
|
|
class DeskmenuEditor(gtk.Window):
|
|
|
|
- def __init__(self):
|
|
- gtk.Window.__init__(self)
|
|
-
|
|
- self.props.title = 'Compiz Deskmenu Editor'
|
|
- self.props.icon_name = 'gtk-edit'
|
|
- self.props.border_width = 12
|
|
- self.set_size_request(400, 400)
|
|
- self.model = gtk.TreeStore(object)
|
|
- self.add_menu(menu)
|
|
-
|
|
- vbox = gtk.VBox(spacing=12)
|
|
-
|
|
- scrolled = gtk.ScrolledWindow()
|
|
- scrolled.props.hscrollbar_policy = gtk.POLICY_NEVER
|
|
- scrolled.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC
|
|
- treeview = gtk.TreeView(self.model)
|
|
- treeview.set_reorderable(True)
|
|
- cell = gtk.CellRendererText()
|
|
- elements = gtk.TreeViewColumn('Item', cell)
|
|
- elements.set_cell_data_func(cell, self.get_type)
|
|
- treeview.append_column(elements)
|
|
-
|
|
- name = gtk.TreeViewColumn('Name')
|
|
-
|
|
- cell = gtk.CellRendererPixbuf()
|
|
- name.pack_start(cell, False)
|
|
- name.set_cell_data_func(cell, self.get_icon)
|
|
-
|
|
- cell = gtk.CellRendererText()
|
|
- name.pack_start(cell)
|
|
- name.set_cell_data_func(cell, self.get_name)
|
|
-
|
|
- treeview.append_column(name)
|
|
- scrolled.add(treeview)
|
|
- vbox.pack_start(scrolled, True, True)
|
|
- targets = [
|
|
- ('deskmenu-element', gtk.TARGET_SAME_WIDGET, 0),
|
|
- ('text/uri-list', 0, 1),
|
|
- ]
|
|
- treeview.enable_model_drag_source(gtk.gdk.BUTTON1_MASK, targets, gtk.gdk.ACTION_DEFAULT|gtk.gdk.ACTION_MOVE)
|
|
- treeview.enable_model_drag_dest(targets, gtk.gdk.ACTION_MOVE)
|
|
-
|
|
- treeview.connect('drag-data-get', self.on_drag_data_get)
|
|
- treeview.connect('drag-data-received', self.on_drag_data_received)
|
|
-
|
|
- treeview.connect('row-activated', self.on_row_activated)
|
|
-
|
|
- treeview.connect('button-press-event', self.on_treeview_button_press_event)
|
|
- treeview.expand_all()
|
|
-
|
|
- self.selection = treeview.get_selection()
|
|
- self.selection.connect('changed', self.on_selection_changed)
|
|
-
|
|
- buttonbox = gtk.HButtonBox()
|
|
- vbox.pack_end(buttonbox, False, False)
|
|
-
|
|
- new = gtk.Button(stock=gtk.STOCK_NEW)
|
|
- new.connect('clicked', self.on_new_clicked)
|
|
- buttonbox.pack_start(new)
|
|
- self.edit = gtk.Button(stock=gtk.STOCK_EDIT)
|
|
- self.edit.connect('clicked', self.on_edit_clicked)
|
|
- buttonbox.pack_start(self.edit)
|
|
- self.delete = gtk.Button(stock=gtk.STOCK_DELETE)
|
|
- self.delete.connect('clicked', self.on_delete_clicked)
|
|
- buttonbox.pack_start(self.delete)
|
|
- close = gtk.Button(stock=gtk.STOCK_CLOSE)
|
|
- close.connect('clicked', self.on_close_clicked)
|
|
- buttonbox.pack_end(close)
|
|
-
|
|
- self.add(vbox)
|
|
-
|
|
- self.popup = gtk.Menu()
|
|
- self.edit_menu = gtk.ImageMenuItem(stock_id=gtk.STOCK_EDIT)
|
|
- self.edit_menu.connect('activate', self.on_edit_clicked)
|
|
- self.popup.append(self.edit_menu)
|
|
- self.delete_menu = gtk.ImageMenuItem(stock_id=gtk.STOCK_DELETE)
|
|
- self.delete_menu.connect('activate', self.on_delete_clicked)
|
|
- self.popup.append(self.delete_menu)
|
|
- self.popup.show_all()
|
|
-
|
|
- self.connect('destroy', self.on_close_clicked)
|
|
-
|
|
- self.show_all()
|
|
-
|
|
- def add_menu(self, m, parent=None):
|
|
- for item in m.children:
|
|
- iter = self.model.append(parent, [item])
|
|
- if item.node.tag == 'menu':
|
|
- self.add_menu(item, iter)
|
|
-
|
|
- def get_name(self, column, cell, model, iter):
|
|
- name = model.get_value(iter, 0).get_name()
|
|
- if name is None:
|
|
- name = ''
|
|
- cell.set_property('text', name)
|
|
-
|
|
- def get_type(self, column, cell, model, iter):
|
|
- typ = model.get_value(iter, 0).get_type()
|
|
- if typ is None:
|
|
- typ = ''
|
|
- cell.set_property('text', typ)
|
|
-
|
|
- def get_icon(self, column, cell, model, iter):
|
|
- icon = model.get_value(iter, 0).get_icon()
|
|
- if icon is not None:
|
|
- cell.set_property('icon-name', icon)
|
|
- else:
|
|
- cell.set_property('icon-name', None)
|
|
-
|
|
- def on_new_clicked(self, widget):
|
|
-
|
|
- NewItemDialog(*self.selection.get_selected())
|
|
-
|
|
- def on_edit_clicked(self, widget):
|
|
-
|
|
- EditItemDialog(*self.selection.get_selected())
|
|
-
|
|
- def on_delete_clicked(self, widget):
|
|
-
|
|
- model, row = self.selection.get_selected()
|
|
-
|
|
- parent = None
|
|
- if row:
|
|
- current = model[row][0].node
|
|
-
|
|
- if current.tag == 'menu' and len(current):
|
|
- warning = gtk.MessageDialog(self, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_NONE, 'Delete menu element with %s children?' %len(current))
|
|
- warning.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_DELETE, gtk.RESPONSE_ACCEPT)
|
|
- if warning.run() != gtk.RESPONSE_ACCEPT:
|
|
- warning.destroy()
|
|
- return
|
|
- warning.destroy()
|
|
-
|
|
- parent = model[row].parent
|
|
- if parent is not None:
|
|
- parent = parent[0].node
|
|
- else:
|
|
- parent = menu.node
|
|
- parent.remove(current)
|
|
- model.remove(row)
|
|
-
|
|
- write_menu()
|
|
-
|
|
- def on_close_clicked(self, widget):
|
|
-
|
|
- write_menu()
|
|
- gtk.main_quit()
|
|
-
|
|
- def on_drag_data_get(self, treeview, context, selection, target_id,
|
|
- etime):
|
|
- treeselection = treeview.get_selection()
|
|
- model, iter = treeselection.get_selected()
|
|
- data = model.get_string_from_iter(iter)
|
|
- selection.set(selection.target, 8, data)
|
|
-
|
|
- def on_drag_data_received(self, treeview, context, x, y, selection,
|
|
- info, etime):
|
|
- model = treeview.get_model()
|
|
- data = selection.data
|
|
-
|
|
- drop_info = treeview.get_dest_row_at_pos(x, y)
|
|
- if selection.type == 'deskmenu-element':
|
|
- source = model[data][0]
|
|
- if drop_info:
|
|
- path, position = drop_info
|
|
- siter = model.get_iter(data)
|
|
- diter = model.get_iter(path)
|
|
-
|
|
- if model.get_path(model.get_iter_from_string(data)) == path:
|
|
- return
|
|
-
|
|
- dest = model[path][0]
|
|
- if context.action == gtk.gdk.ACTION_MOVE:
|
|
- source.node.getparent().remove(source.node)
|
|
-
|
|
- if dest.node.tag == 'menu' and position in (gtk.TREE_VIEW_DROP_INTO_OR_BEFORE,
|
|
- gtk.TREE_VIEW_DROP_INTO_OR_AFTER):
|
|
- dest.node.append(source.node)
|
|
- fiter = model.append(diter, row=(source,))
|
|
- else:
|
|
- i = dest.node.getparent().index(dest.node)
|
|
- if position in (gtk.TREE_VIEW_DROP_INTO_OR_BEFORE,
|
|
- gtk.TREE_VIEW_DROP_BEFORE):
|
|
- dest.node.getparent().insert(i, source.node)
|
|
- fiter = model.insert_before(None, diter, row=(source,))
|
|
- else:
|
|
- dest.node.getparent().insert(i+1, source.node)
|
|
- fiter = model.insert_after(None, diter, row=(source,))
|
|
-
|
|
- if model.iter_has_child(siter):
|
|
- citer = model.iter_children(siter)
|
|
- while citer is not None:
|
|
- model.append(fiter, row=(model[citer][0],))
|
|
- citer = model.iter_next(citer)
|
|
- if context.action == gtk.gdk.ACTION_MOVE:
|
|
- context.finish(True, True, etime)
|
|
-
|
|
- elif selection.type == 'text/uri-list':
|
|
- if drop_info:
|
|
- path, position = drop_info
|
|
- uri = selection.data.replace('file:///', '/').strip()
|
|
- entry = ConfigParser.ConfigParser()
|
|
- entry.read(uri)
|
|
- launcher = Launcher()
|
|
- launcher.name = etree.SubElement(launcher.node, 'name')
|
|
- launcher.icon = etree.SubElement(launcher.node, 'icon')
|
|
- launcher.command = etree.SubElement(launcher.node, 'command')
|
|
- try:
|
|
- launcher.name.text = entry.get('Desktop Entry', 'Name')
|
|
- launcher.icon.text = entry.get('Desktop Entry', 'Icon').split('.')[0]
|
|
- launcher.command.text = entry.get('Desktop Entry', 'Exec').split('%')[0]
|
|
- except ConfigParser.Error:
|
|
- return
|
|
- dest = model[path][0]
|
|
- diter = model.get_iter(path)
|
|
- if dest.node.tag == 'menu' and position in (gtk.TREE_VIEW_DROP_INTO_OR_BEFORE,
|
|
- gtk.TREE_VIEW_DROP_INTO_OR_AFTER):
|
|
- dest.node.append(launcher.node)
|
|
- fiter = model.append(diter, row=(launcher,))
|
|
- else:
|
|
- i = dest.node.getparent().index(dest.node)
|
|
- if position in (gtk.TREE_VIEW_DROP_INTO_OR_BEFORE,
|
|
- gtk.TREE_VIEW_DROP_BEFORE):
|
|
- dest.node.getparent().insert(i, launcher.node)
|
|
- fiter = model.insert_before(None, diter, row=(launcher,))
|
|
- else:
|
|
- dest.node.getparent().insert(i+1, launcher.node)
|
|
- fiter = model.insert_after(None, diter, row=(launcher,))
|
|
- if context.action == gtk.gdk.ACTION_MOVE:
|
|
- context.finish(True, True, etime)
|
|
+ def __init__(self):
|
|
+ gtk.Window.__init__(self)
|
|
+
|
|
+ self.props.title = 'Compiz Deskmenu Editor'
|
|
+ self.props.icon_name = 'gtk-edit'
|
|
+ self.props.border_width = 12
|
|
+ self.set_size_request(400, 400)
|
|
+ self.model = gtk.TreeStore(object)
|
|
+ self.add_menu(menu)
|
|
+
|
|
+ vbox = gtk.VBox(spacing=12)
|
|
+
|
|
+ scrolled = gtk.ScrolledWindow()
|
|
+ scrolled.props.hscrollbar_policy = gtk.POLICY_NEVER
|
|
+ scrolled.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC
|
|
+ treeview = gtk.TreeView(self.model)
|
|
+ treeview.set_reorderable(True)
|
|
+ cell = gtk.CellRendererText()
|
|
+ elements = gtk.TreeViewColumn('Item', cell)
|
|
+ elements.set_cell_data_func(cell, self.get_type)
|
|
+ treeview.append_column(elements)
|
|
+
|
|
+ name = gtk.TreeViewColumn('Name')
|
|
+
|
|
+ cell = gtk.CellRendererPixbuf()
|
|
+ name.pack_start(cell, False)
|
|
+ name.set_cell_data_func(cell, self.get_icon)
|
|
+
|
|
+ cell = gtk.CellRendererText()
|
|
+ name.pack_start(cell)
|
|
+ name.set_cell_data_func(cell, self.get_name)
|
|
+
|
|
+ treeview.append_column(name)
|
|
+ scrolled.add(treeview)
|
|
+ vbox.pack_start(scrolled, True, True)
|
|
+ targets = [
|
|
+ ('deskmenu-element', gtk.TARGET_SAME_WIDGET, 0),
|
|
+ ('text/uri-list', 0, 1),
|
|
+ ]
|
|
+ treeview.enable_model_drag_source(gtk.gdk.BUTTON1_MASK, targets, gtk.gdk.ACTION_DEFAULT|gtk.gdk.ACTION_MOVE)
|
|
+ treeview.enable_model_drag_dest(targets, gtk.gdk.ACTION_MOVE)
|
|
+
|
|
+ treeview.connect('drag-data-get', self.on_drag_data_get)
|
|
+ treeview.connect('drag-data-received', self.on_drag_data_received)
|
|
+
|
|
+ treeview.connect('row-activated', self.on_row_activated)
|
|
+
|
|
+ treeview.connect('button-press-event', self.on_treeview_button_press_event)
|
|
+ treeview.expand_all()
|
|
+
|
|
+ self.selection = treeview.get_selection()
|
|
+ self.selection.connect('changed', self.on_selection_changed)
|
|
+
|
|
+ buttonbox = gtk.HButtonBox()
|
|
+ vbox.pack_end(buttonbox, False, False)
|
|
+
|
|
+ new = gtk.Button(stock=gtk.STOCK_NEW)
|
|
+ new.connect('clicked', self.on_new_clicked)
|
|
+ buttonbox.pack_start(new)
|
|
+ self.edit = gtk.Button(stock=gtk.STOCK_EDIT)
|
|
+ self.edit.connect('clicked', self.on_edit_clicked)
|
|
+ buttonbox.pack_start(self.edit)
|
|
+ self.delete = gtk.Button(stock=gtk.STOCK_DELETE)
|
|
+ self.delete.connect('clicked', self.on_delete_clicked)
|
|
+ buttonbox.pack_start(self.delete)
|
|
+ close = gtk.Button(stock=gtk.STOCK_CLOSE)
|
|
+ close.connect('clicked', self.on_close_clicked)
|
|
+ buttonbox.pack_end(close)
|
|
+
|
|
+ self.add(vbox)
|
|
+
|
|
+ self.popup = gtk.Menu()
|
|
+ self.edit_menu = gtk.ImageMenuItem(stock_id=gtk.STOCK_EDIT)
|
|
+ self.edit_menu.connect('activate', self.on_edit_clicked)
|
|
+ self.popup.append(self.edit_menu)
|
|
+ self.delete_menu = gtk.ImageMenuItem(stock_id=gtk.STOCK_DELETE)
|
|
+ self.delete_menu.connect('activate', self.on_delete_clicked)
|
|
+ self.popup.append(self.delete_menu)
|
|
+ self.popup.show_all()
|
|
+
|
|
+ self.connect('destroy', self.on_close_clicked)
|
|
+
|
|
+ self.show_all()
|
|
+
|
|
+ def add_menu(self, m, parent=None):
|
|
+ for item in m.children:
|
|
+ iter = self.model.append(parent, [item])
|
|
+ if item.node.tag == 'menu':
|
|
+ self.add_menu(item, iter)
|
|
+
|
|
+ def get_name(self, column, cell, model, iter):
|
|
+ name = model.get_value(iter, 0).get_name()
|
|
+ if name is None:
|
|
+ name = ''
|
|
+ cell.set_property('text', name)
|
|
+
|
|
+ def get_type(self, column, cell, model, iter):
|
|
+ typ = model.get_value(iter, 0).get_type()
|
|
+ if typ is None:
|
|
+ typ = ''
|
|
+ cell.set_property('text', typ)
|
|
+
|
|
+ def get_icon(self, column, cell, model, iter):
|
|
+ icon = model.get_value(iter, 0).get_icon()
|
|
+ icon_mode = model.get_value(iter, 0).get_icon_mode()
|
|
+ if icon is not None:
|
|
+ if icon_mode is not None:
|
|
+ w = gtk.icon_size_lookup(gtk.ICON_SIZE_MENU)
|
|
+ cell.set_property('pixbuf', gtk.gdk.pixbuf_new_from_file_at_size(os.path.expanduser(icon), w[0], w[0]))
|
|
+ cell.set_property('icon-name', None) #possibly reduntant safety measure
|
|
+ else:
|
|
+ cell.set_property('icon-name', icon)
|
|
+ cell.set_property('pixbuf', None) #possibly reduntant safety measure
|
|
+ else:
|
|
+ cell.set_property('icon-name', None)
|
|
+ cell.set_property('pixbuf', None)
|
|
+
|
|
+ def on_new_clicked(self, widget):
|
|
+
|
|
+ NewItemDialog(*self.selection.get_selected())
|
|
+
|
|
+ def on_edit_clicked(self, widget):
|
|
+
|
|
+ EditItemDialog(*self.selection.get_selected())
|
|
+
|
|
+ def on_delete_clicked(self, widget):
|
|
+
|
|
+ model, row = self.selection.get_selected()
|
|
+
|
|
+ parent = None
|
|
+ if row:
|
|
+ current = model[row][0].node
|
|
+
|
|
+ if current.tag == 'menu' and len(current):
|
|
+ warning = gtk.MessageDialog(self, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_NONE, 'Delete menu element with %s children?' %len(current))
|
|
+ warning.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_DELETE, gtk.RESPONSE_ACCEPT)
|
|
+ if warning.run() != gtk.RESPONSE_ACCEPT:
|
|
+ warning.destroy()
|
|
+ return
|
|
+ warning.destroy()
|
|
+
|
|
+ parent = model[row].parent
|
|
+ if parent is not None:
|
|
+ parent = parent[0].node
|
|
+ else:
|
|
+ parent = menu.node
|
|
+ parent.remove(current)
|
|
+ model.remove(row)
|
|
+
|
|
+ write_menu()
|
|
+
|
|
+ def on_close_clicked(self, widget):
|
|
+
|
|
+ write_menu()
|
|
+ gtk.main_quit()
|
|
+
|
|
+ def on_drag_data_get(self, treeview, context, selection, target_id,
|
|
+ etime):
|
|
+ treeselection = treeview.get_selection()
|
|
+ model, iter = treeselection.get_selected()
|
|
+ data = model.get_string_from_iter(iter)
|
|
+ selection.set(selection.target, 8, data)
|
|
+
|
|
+ def on_drag_data_received(self, treeview, context, x, y, selection,
|
|
+ info, etime):
|
|
+ model = treeview.get_model()
|
|
+ data = selection.data
|
|
+
|
|
+ drop_info = treeview.get_dest_row_at_pos(x, y)
|
|
+ if selection.type == 'deskmenu-element':
|
|
+ source = model[data][0]
|
|
+ if drop_info:
|
|
+ path, position = drop_info
|
|
+ siter = model.get_iter(data)
|
|
+ diter = model.get_iter(path)
|
|
+
|
|
+ if model.get_path(model.get_iter_from_string(data)) == path:
|
|
+ return
|
|
+
|
|
+ dest = model[path][0]
|
|
+ if context.action == gtk.gdk.ACTION_MOVE:
|
|
+ source.node.getparent().remove(source.node)
|
|
+
|
|
+ if dest.node.tag == 'menu' and position in (gtk.TREE_VIEW_DROP_INTO_OR_BEFORE,
|
|
+ gtk.TREE_VIEW_DROP_INTO_OR_AFTER):
|
|
+ dest.node.append(source.node)
|
|
+ fiter = model.append(diter, row=(source,))
|
|
+ else:
|
|
+ i = dest.node.getparent().index(dest.node)
|
|
+ if position in (gtk.TREE_VIEW_DROP_INTO_OR_BEFORE,
|
|
+ gtk.TREE_VIEW_DROP_BEFORE):
|
|
+ dest.node.getparent().insert(i, source.node)
|
|
+ fiter = model.insert_before(None, diter, row=(source,))
|
|
+ else:
|
|
+ dest.node.getparent().insert(i+1, source.node)
|
|
+ fiter = model.insert_after(None, diter, row=(source,))
|
|
+
|
|
+ if model.iter_has_child(siter):
|
|
+ citer = model.iter_children(siter)
|
|
+ while citer is not None:
|
|
+ model.append(fiter, row=(model[citer][0],))
|
|
+ citer = model.iter_next(citer)
|
|
+ if context.action == gtk.gdk.ACTION_MOVE:
|
|
+ context.finish(True, True, etime)
|
|
+
|
|
+ elif selection.type == 'text/uri-list':
|
|
+ if drop_info:
|
|
+ path, position = drop_info
|
|
+ uri = selection.data.replace('file:///', '/').strip()
|
|
+ entry = ConfigParser.ConfigParser()
|
|
+ entry.read(uri)
|
|
+ launcher = Launcher()
|
|
+ launcher.name = etree.SubElement(launcher.node, 'name')
|
|
+ launcher.icon = etree.SubElement(launcher.node, 'icon')
|
|
+ launcher.command = etree.SubElement(launcher.node, 'command')
|
|
+ try:
|
|
+ launcher.name.text = entry.get('Desktop Entry', 'Name')
|
|
+ if re.search("/", entry.get('Desktop Entry', 'Icon')):
|
|
+ launcher.icon.attrib['mode1'] = 'file'
|
|
+ launcher.icon.text = entry.get('Desktop Entry', 'Icon')
|
|
+ launcher.command.text = entry.get('Desktop Entry', 'Exec').split('%')[0]
|
|
+ except ConfigParser.Error:
|
|
+ return
|
|
+ dest = model[path][0]
|
|
+ diter = model.get_iter(path)
|
|
+ if dest.node.tag == 'menu' and position in (gtk.TREE_VIEW_DROP_INTO_OR_BEFORE,
|
|
+ gtk.TREE_VIEW_DROP_INTO_OR_AFTER):
|
|
+ dest.node.append(launcher.node)
|
|
+ fiter = model.append(diter, row=(launcher,))
|
|
+ else:
|
|
+ i = dest.node.getparent().index(dest.node)
|
|
+ if position in (gtk.TREE_VIEW_DROP_INTO_OR_BEFORE,
|
|
+ gtk.TREE_VIEW_DROP_BEFORE):
|
|
+ dest.node.getparent().insert(i, launcher.node)
|
|
+ fiter = model.insert_before(None, diter, row=(launcher,))
|
|
+ else:
|
|
+ dest.node.getparent().insert(i+1, launcher.node)
|
|
+ fiter = model.insert_after(None, diter, row=(launcher,))
|
|
+ if context.action == gtk.gdk.ACTION_MOVE:
|
|
+ context.finish(True, True, etime)
|
|
|
|
- write_menu()
|
|
+ write_menu()
|
|
|
|
- return
|
|
+ return
|
|
|
|
- def on_selection_changed(self, selection):
|
|
+ def on_selection_changed(self, selection):
|
|
|
|
- model, row = selection.get_selected()
|
|
+ model, row = selection.get_selected()
|
|
|
|
- sensitive = row and model.get_value(row, 0).editable
|
|
+ sensitive = row and model.get_value(row, 0).editable
|
|
|
|
- self.edit.props.sensitive = sensitive
|
|
- self.edit_menu.props.sensitive = sensitive
|
|
- self.delete.props.sensitive = row
|
|
- self.delete_menu.props.sensitive = row
|
|
-
|
|
- def on_row_activated(self, treeview, path, view_column):
|
|
-
|
|
- model = treeview.get_model()
|
|
- EditItemDialog(model, model.get_iter(path))
|
|
-
|
|
- def on_treeview_button_press_event(self, treeview, event):
|
|
- if event.button == 3:
|
|
- pthinfo = treeview.get_path_at_pos(int(event.x), int(event.y))
|
|
- if pthinfo is not None:
|
|
- path, col, cellx, celly = pthinfo
|
|
- treeview.grab_focus()
|
|
- treeview.set_cursor(path, col, 0)
|
|
- self.popup.popup(None, None, None, event.button, event.time)
|
|
- return 1
|
|
+ self.edit.props.sensitive = sensitive
|
|
+ self.edit_menu.props.sensitive = sensitive
|
|
+ self.delete.props.sensitive = row
|
|
+ self.delete_menu.props.sensitive = row
|
|
+
|
|
+ def on_row_activated(self, treeview, path, view_column):
|
|
+
|
|
+ model = treeview.get_model()
|
|
+ EditItemDialog(model, model.get_iter(path))
|
|
+
|
|
+ def on_treeview_button_press_event(self, treeview, event):
|
|
+ if event.button == 3:
|
|
+ pthinfo = treeview.get_path_at_pos(int(event.x), int(event.y))
|
|
+ if pthinfo is not None:
|
|
+ path, col, cellx, celly = pthinfo
|
|
+ treeview.grab_focus()
|
|
+ treeview.set_cursor(path, col, 0)
|
|
+ self.popup.popup(None, None, None, event.button, event.time)
|
|
+ return 1
|
|
|
|
|
|
class NewItemDialog(gtk.Dialog):
|
|
|
|
- elementlist = ['Launcher', 'Menu', 'Separator', 'Windows List',
|
|
- 'Viewports List', 'Reload']
|
|
+ elementlist = ['Launcher', 'Menu', 'Separator', 'Windows List',
|
|
+ 'Viewports List', 'Pipeitem']
|
|
|
|
- def __init__(self, model, row):
|
|
- gtk.Dialog.__init__(self, 'New Item', None, 0, None)
|
|
+ def __init__(self, model, row):
|
|
+ gtk.Dialog.__init__(self, 'New Item', None, 0, None)
|
|
|
|
- self.set_size_request(250, 250)
|
|
+ self.set_size_request(250, 250)
|
|
|
|
- self.props.border_width = 6
|
|
- self.vbox.props.spacing = 6
|
|
- self.set_has_separator(False)
|
|
- self.treeview = self.make_treeview()
|
|
-
|
|
- scroll = gtk.ScrolledWindow()
|
|
- scroll.add(self.treeview)
|
|
- scroll.props.hscrollbar_policy = gtk.POLICY_NEVER
|
|
- scroll.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC
|
|
- self.vbox.pack_start(scroll, True, True)
|
|
-
|
|
- self.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
|
|
- gtk.STOCK_NEW, gtk.RESPONSE_ACCEPT)
|
|
-
|
|
- self.action_area.props.border_width = 0
|
|
-
|
|
- self.show_all()
|
|
-
|
|
- element = None
|
|
-
|
|
- if self.run() == gtk.RESPONSE_ACCEPT:
|
|
- m, r = self.treeview.get_selection().get_selected()
|
|
- if r:
|
|
- elementname = m[r][0]
|
|
- else:
|
|
- self.destroy()
|
|
- return
|
|
- parent = sibling = None
|
|
- if row:
|
|
- current = model[row][0]
|
|
- if current.node.tag == 'menu':
|
|
- parent = row
|
|
- else:
|
|
- parent = model[row].parent
|
|
- if parent is not None:
|
|
- parent = parent.iter
|
|
- sibling = row
|
|
- if parent:
|
|
- parentelement = model[parent][0]
|
|
- else:
|
|
- parentelement = menu
|
|
-
|
|
- element = elementsbyname[elementname]()
|
|
- if sibling:
|
|
- position = parentelement.node.index(current.node) + 1
|
|
- parentelement.node.insert(position, element.node)
|
|
- model.insert_after(parent, sibling, row=(element,))
|
|
- else:
|
|
- model.append(parent, row=(element,))
|
|
- parentelement.node.append(element.node)
|
|
-
|
|
- self.destroy()
|
|
- write_menu()
|
|
-
|
|
- if element and element.editable:
|
|
- EditItemDialog(element=element)
|
|
-
|
|
- def make_treeview(self):
|
|
- model = gtk.ListStore(str)
|
|
- for el in self.elementlist:
|
|
- model.append([el])
|
|
-
|
|
- treeview = gtk.TreeView(model)
|
|
- column = gtk.TreeViewColumn(None, gtk.CellRendererText(), text=0)
|
|
- treeview.set_headers_visible(False)
|
|
- treeview.append_column(column)
|
|
+ self.props.border_width = 6
|
|
+ self.vbox.props.spacing = 6
|
|
+ self.set_has_separator(False)
|
|
+ self.treeview = self.make_treeview()
|
|
+
|
|
+ scroll = gtk.ScrolledWindow()
|
|
+ scroll.add(self.treeview)
|
|
+ scroll.props.hscrollbar_policy = gtk.POLICY_NEVER
|
|
+ scroll.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC
|
|
+ self.vbox.pack_start(scroll, True, True)
|
|
+
|
|
+ self.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
|
|
+ gtk.STOCK_NEW, gtk.RESPONSE_ACCEPT)
|
|
+
|
|
+ self.action_area.props.border_width = 0
|
|
+
|
|
+ self.show_all()
|
|
+
|
|
+ element = None
|
|
+
|
|
+ if self.run() == gtk.RESPONSE_ACCEPT:
|
|
+ m, r = self.treeview.get_selection().get_selected()
|
|
+ if r:
|
|
+ elementname = m[r][0]
|
|
+ else:
|
|
+ self.destroy()
|
|
+ return
|
|
+ parent = sibling = None
|
|
+ if row:
|
|
+ current = model[row][0]
|
|
+ if current.node.tag == 'menu':
|
|
+ parent = row
|
|
+ else:
|
|
+ parent = model[row].parent
|
|
+ if parent is not None:
|
|
+ parent = parent.iter
|
|
+ sibling = row
|
|
+ if parent:
|
|
+ parentelement = model[parent][0]
|
|
+ else:
|
|
+ parentelement = menu
|
|
+
|
|
+ element = elementsbyname[elementname]()
|
|
+ if sibling:
|
|
+ position = parentelement.node.index(current.node) + 1
|
|
+ parentelement.node.insert(position, element.node)
|
|
+ model.insert_after(parent, sibling, row=(element,))
|
|
+ else:
|
|
+ model.append(parent, row=(element,))
|
|
+ parentelement.node.append(element.node)
|
|
+
|
|
+ self.destroy()
|
|
+ write_menu()
|
|
+
|
|
+ if element and element.editable:
|
|
+ EditItemDialog(element=element)
|
|
+
|
|
+ def make_treeview(self):
|
|
+ model = gtk.ListStore(str)
|
|
+ for el in self.elementlist:
|
|
+ model.append([el])
|
|
+
|
|
+ treeview = gtk.TreeView(model)
|
|
+ column = gtk.TreeViewColumn(None, gtk.CellRendererText(), text=0)
|
|
+ treeview.set_headers_visible(False)
|
|
+ treeview.append_column(column)
|
|
|
|
- treeview.connect('row-activated', self.on_row_activated)
|
|
- return treeview
|
|
+ treeview.connect('row-activated', self.on_row_activated)
|
|
+ return treeview
|
|
|
|
- def on_row_activated(self, treeview, path, view_column):
|
|
- self.response(gtk.RESPONSE_ACCEPT)
|
|
+ def on_row_activated(self, treeview, path, view_column):
|
|
+ self.response(gtk.RESPONSE_ACCEPT)
|
|
|
|
|
|
class EditItemDialog(gtk.Dialog):
|
|
|
|
- def __init__(self, model=None, row=None, element=None):
|
|
- gtk.Dialog.__init__(self, 'Edit Item', None, 0, None)
|
|
-
|
|
- self.set_size_request(300, -1)
|
|
+ def __init__(self, model=None, row=None, element=None):
|
|
+ gtk.Dialog.__init__(self, 'Edit Item', None, 0, None)
|
|
|
|
- self.props.border_width = 6
|
|
- self.vbox.props.spacing = 6
|
|
- self.set_has_separator(False)
|
|
+ self.set_size_request(300, -1)
|
|
|
|
- if element is None:
|
|
- if not row:
|
|
- return
|
|
- element = model.get_value(row, 0)
|
|
+ self.props.border_width = 6
|
|
+ self.vbox.props.spacing = 6
|
|
+ self.set_has_separator(False)
|
|
|
|
- if not element.editable:
|
|
- return
|
|
+ if element is None:
|
|
+ if not row:
|
|
+ return
|
|
+ element = model.get_value(row, 0)
|
|
|
|
- for widget in element.get_options():
|
|
- self.vbox.pack_start(widget, False, False)
|
|
+ if not element.editable:
|
|
+ return
|
|
|
|
- self.add_buttons(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
|
|
+ for widget in element.get_options():
|
|
+ self.vbox.pack_start(widget, False, False)
|
|
|
|
- self.show_all()
|
|
- self.run()
|
|
- self.destroy()
|
|
- write_menu()
|
|
+ self.add_buttons(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
|
|
|
|
+ self.show_all()
|
|
+ self.run()
|
|
+ self.destroy()
|
|
+ write_menu()
|
|
|
|
|
|
class Item(object):
|
|
-
|
|
- def __init__(self, node=None, parent=None, type=None):
|
|
+
|
|
+ def __init__(self, node=None, parent=None, type=None):
|
|
|
|
- self.editable = False
|
|
+ self.editable = False
|
|
|
|
- if node is None:
|
|
- self.node = etree.Element('item')
|
|
- if type is not None:
|
|
- self.node.attrib['type'] = type
|
|
-
|
|
- else:
|
|
- self.node = node
|
|
+ if node is None:
|
|
+ self.node = etree.Element('item')
|
|
+ if type is not None:
|
|
+ self.node.attrib['type'] = type
|
|
+
|
|
+ else:
|
|
+ self.node = node
|
|
+
|
|
+ def get_name(self):
|
|
+ return None
|
|
|
|
- def get_name(self):
|
|
- return None
|
|
+ def get_type(self):
|
|
+ return 'Item'
|
|
|
|
- def get_type(self):
|
|
- return 'Item'
|
|
+ def get_icon(self):
|
|
+ return None
|
|
|
|
- def get_icon(self):
|
|
- return None
|
|
+ def get_icon_mode(self):
|
|
+ return None
|
|
|
|
class Launcher(Item):
|
|
-
|
|
- def __init__(self, node=None):
|
|
+
|
|
+ def __init__(self, node=None):
|
|
|
|
- Item.__init__(self, node)
|
|
-
|
|
- if node is None:
|
|
- self.node = etree.Element('item', type='launcher')
|
|
-
|
|
- self.editable = True
|
|
-
|
|
- def get_name(self):
|
|
-
|
|
- subnode = self.node.find('name')
|
|
- if subnode is not None:
|
|
- name = subnode.text
|
|
- if subnode.attrib.get('mode') == 'exec':
|
|
- name = 'exec: %s' %name
|
|
- return name
|
|
- else:
|
|
- return None
|
|
-
|
|
- def get_type(self):
|
|
- return 'Launcher'
|
|
-
|
|
- def get_icon(self):
|
|
- iconnode = self.node.find('icon')
|
|
- if iconnode is not None:
|
|
- return iconnode.text
|
|
- else:
|
|
- return None
|
|
-
|
|
- def get_options(self):
|
|
-
|
|
- retlist = []
|
|
- sgroup = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
|
|
-
|
|
- label = gtk.Label()
|
|
- label.set_alignment(0, 0.5)
|
|
- sgroup.add_widget(label)
|
|
- label.set_markup('<b>Name:</b>')
|
|
- widget = gtk.Entry()
|
|
-
|
|
- namenode = self.node.find('name')
|
|
- if namenode is not None:
|
|
- name = namenode.text
|
|
- else:
|
|
- name = ''
|
|
- widget.props.text = name
|
|
- widget.connect('changed', self.on_subnode_changed, 'name')
|
|
-
|
|
- hbox = gtk.HBox()
|
|
- hbox.pack_start(label)
|
|
- hbox.pack_start(widget, True, True)
|
|
- retlist.append(hbox)
|
|
-
|
|
- label = gtk.Label()
|
|
- label.set_alignment(0, 0.5)
|
|
- sgroup.add_widget(label)
|
|
- label.set_markup('<b>Name mode:</b>')
|
|
- widget = gtk.combo_box_new_text()
|
|
- widget.append_text('Normal')
|
|
- widget.append_text('Execute')
|
|
- widget.props.active = namenode is not None and namenode.attrib.get('mode') == 'exec'
|
|
- widget.connect('changed', self.on_name_mode_changed)
|
|
-
|
|
- hbox = gtk.HBox()
|
|
- hbox.pack_start(label)
|
|
- hbox.pack_start(widget, True, True)
|
|
- retlist.append(hbox)
|
|
-
|
|
- label = gtk.Label()
|
|
- label.set_alignment(0, 0.5)
|
|
- sgroup.add_widget(label)
|
|
- label.set_markup('<b>Icon:</b>')
|
|
- widget = gtk.Entry()
|
|
- iconnode = self.node.find('icon')
|
|
- if iconnode is not None:
|
|
- icon = iconnode.text
|
|
- else:
|
|
- icon = ''
|
|
- widget.props.text = icon
|
|
- widget.connect('changed', self.on_subnode_changed, 'icon')
|
|
-
|
|
- hbox = gtk.HBox()
|
|
- hbox.pack_start(label)
|
|
- hbox.pack_start(widget, True, True)
|
|
- retlist.append(hbox)
|
|
-
|
|
- label = gtk.Label()
|
|
- label.set_alignment(0, 0.5)
|
|
- sgroup.add_widget(label)
|
|
- label.set_markup('<b>Command:</b>')
|
|
- widget = gtk.Entry()
|
|
- commandnode = self.node.find('command')
|
|
- if commandnode is not None:
|
|
- command = commandnode.text
|
|
- else:
|
|
- command = ''
|
|
- widget.props.text = command
|
|
- widget.connect('changed', self.on_subnode_changed, 'command')
|
|
-
|
|
- hbox = gtk.HBox()
|
|
- hbox.pack_start(label)
|
|
- hbox.pack_start(widget, True, True)
|
|
- retlist.append(hbox)
|
|
-
|
|
- return retlist
|
|
-
|
|
- def on_subnode_changed(self, widget, tag):
|
|
- text = widget.props.text
|
|
- subnode = self.node.find(tag)
|
|
- if text:
|
|
- if subnode is None:
|
|
- subnode = etree.SubElement(self.node, tag)
|
|
- subnode.text = text
|
|
- else:
|
|
- if subnode is not None:
|
|
- self.node.remove(subnode)
|
|
-
|
|
- def on_name_mode_changed(self, widget):
|
|
- namenode = self.node.find('name')
|
|
- if widget.props.active:
|
|
- if namenode is None:
|
|
- namenode = etree.SubElement(self.node, 'name')
|
|
- namenode.attrib['mode'] = 'exec'
|
|
- elif 'mode' in self.name.attrib:
|
|
- namenode.attrib['mode'] = 'normal'
|
|
+ Item.__init__(self, node)
|
|
|
|
+ if node is None:
|
|
+ self.node = etree.Element('item', type='launcher')
|
|
+
|
|
+ self.editable = True
|
|
+
|
|
+ def get_name(self):
|
|
+
|
|
+ subnode = self.node.find('name')
|
|
+ if subnode is not None:
|
|
+ name = subnode.text
|
|
+ if subnode.attrib.get('mode') == 'exec':
|
|
+ name = 'exec: %s' %name
|
|
+ return name
|
|
+ else:
|
|
+ return None
|
|
+
|
|
+ def get_type(self):
|
|
+ return 'Launcher'
|
|
+
|
|
+ def get_icon(self):
|
|
+ iconnode = self.node.find('icon')
|
|
+ if iconnode is not None:
|
|
+ return iconnode.text
|
|
+ else:
|
|
+ return None
|
|
+
|
|
+ def get_icon_mode(self):
|
|
+ iconnode = self.node.find('icon')
|
|
+ if iconnode is not None:
|
|
+ if iconnode.attrib.get('mode1') == 'file':
|
|
+ return iconnode.attrib.get('mode1')
|
|
+ else:
|
|
+ return None
|
|
+
|
|
+ def get_options(self):
|
|
+
|
|
+ retlist = []
|
|
+ sgroup = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
|
|
+
|
|
+ label = gtk.Label()
|
|
+ label.set_alignment(0, 0.5)
|
|
+ sgroup.add_widget(label)
|
|
+ label.set_markup('<b>Name:</b>')
|
|
+ widget = gtk.Entry()
|
|
+
|
|
+ namenode = self.node.find('name')
|
|
+ if namenode is not None:
|
|
+ name = namenode.text
|
|
+ else:
|
|
+ name = ''
|
|
+ widget.props.text = name
|
|
+ widget.connect('changed', self.on_subnode_changed, 'name')
|
|
+
|
|
+ hbox = gtk.HBox()
|
|
+ hbox.pack_start(label)
|
|
+ hbox.pack_start(widget, True, True)
|
|
+ retlist.append(hbox)
|
|
+
|
|
+ label = gtk.Label()
|
|
+ label.set_alignment(0, 0.5)
|
|
+ sgroup.add_widget(label)
|
|
+ label.set_markup('<b>Name mode:</b>')
|
|
+ widget = gtk.combo_box_new_text()
|
|
+ widget.append_text('Normal')
|
|
+ widget.append_text('Execute')
|
|
+ widget.props.active = namenode is not None and namenode.attrib.get('mode') == 'exec'
|
|
+ widget.connect('changed', self.on_name_mode_changed)
|
|
+
|
|
+ hbox = gtk.HBox()
|
|
+ hbox.pack_start(label)
|
|
+ hbox.pack_start(widget, True, True)
|
|
+ retlist.append(hbox)
|
|
+
|
|
+ label = gtk.Label()
|
|
+ label.set_alignment(0, 0.5)
|
|
+ sgroup.add_widget(label)
|
|
+ label.set_markup('<b>Icon:</b>')
|
|
+ widget = gtk.Entry()
|
|
+
|
|
+ iconnode = self.node.find('icon')
|
|
+ if iconnode is not None:
|
|
+ icon = iconnode.text
|
|
+ else:
|
|
+ icon = ''
|
|
+ widget.props.text = icon
|
|
+ widget.connect('changed', self.on_subnode_changed, 'icon')
|
|
+
|
|
+ hbox = gtk.HBox()
|
|
+ hbox.pack_start(label)
|
|
+ hbox.pack_start(widget, True, True)
|
|
+ retlist.append(hbox)
|
|
+
|
|
+ label = gtk.Label()
|
|
+ label.set_alignment(0, 0.5)
|
|
+ sgroup.add_widget(label)
|
|
+ label.set_markup('<b>Icon mode:</b>')
|
|
+ widget = gtk.combo_box_new_text()
|
|
+ widget.append_text('Normal')
|
|
+ widget.append_text('File Path')
|
|
+ widget.props.active = iconnode is not None and iconnode.attrib.get('mode1') == 'file'
|
|
+ widget.connect('changed', self.on_icon_mode_changed)
|
|
+
|
|
+ hbox = gtk.HBox()
|
|
+ hbox.pack_start(label)
|
|
+ hbox.pack_start(widget, True, True)
|
|
+ retlist.append(hbox)
|
|
+
|
|
+ label = gtk.Label()
|
|
+ label.set_alignment(0, 0.5)
|
|
+ sgroup.add_widget(label)
|
|
+ label.set_markup('<b>Command:</b>')
|
|
+ widget = gtk.Entry()
|
|
+ commandnode = self.node.find('command')
|
|
+ if commandnode is not None:
|
|
+ command = commandnode.text
|
|
+ else:
|
|
+ command = ''
|
|
+ widget.props.text = command
|
|
+ widget.connect('changed', self.on_subnode_changed, 'command')
|
|
+
|
|
+ hbox = gtk.HBox()
|
|
+ hbox.pack_start(label)
|
|
+ hbox.pack_start(widget, True, True)
|
|
+ retlist.append(hbox)
|
|
+
|
|
+ return retlist
|
|
+
|
|
+ def on_subnode_changed(self, widget, tag):
|
|
+ text = widget.props.text
|
|
+ subnode = self.node.find(tag)
|
|
+ if text:
|
|
+ if subnode is None:
|
|
+ subnode = etree.SubElement(self.node, tag)
|
|
+ subnode.text = text
|
|
+ else:
|
|
+ if subnode is not None:
|
|
+ self.node.remove(subnode)
|
|
+
|
|
+ def on_name_mode_changed(self, widget):
|
|
+ namenode = self.node.find('name')
|
|
+ if widget.props.active:
|
|
+ if namenode is None:
|
|
+ namenode = etree.SubElement(self.node, 'name')
|
|
+ namenode.attrib['mode'] = 'exec'
|
|
+ elif 'mode' in namenode.attrib:
|
|
+ del namenode.attrib['mode']
|
|
+
|
|
+ def on_icon_mode_changed(self, widget):
|
|
+ iconnode = self.node.find('icon')
|
|
+ if widget.props.active:
|
|
+ if iconnode is None:
|
|
+ iconnode = etree.SubElement(self.node, 'icon')
|
|
+ iconnode.attrib['mode1'] = 'file'
|
|
+ elif 'mode1' in iconnode.attrib:
|
|
+ del iconnode.attrib['mode1']
|
|
|
|
class Windowlist(Item):
|
|
-
|
|
- def __init__(self, node=None):
|
|
- Item.__init__(self, node, type='windowlist')
|
|
-
|
|
- def get_type(self):
|
|
- return 'Windows list'
|
|
+
|
|
+ def __init__(self, node=None):
|
|
+ Item.__init__(self, node, type='windowlist')
|
|
+ self.editable = True
|
|
+
|
|
+ def get_icon(self):
|
|
+ iconnode = self.node.find('icon')
|
|
+ if iconnode is not None:
|
|
+ return iconnode.text
|
|
+ else:
|
|
+ return None
|
|
+
|
|
+ def get_icon_mode(self):
|
|
+ iconnode = self.node.find('icon')
|
|
+ if iconnode is not None:
|
|
+ if iconnode.attrib.get('mode1') == 'file':
|
|
+ return iconnode.attrib.get('mode1')
|
|
+ else:
|
|
+ return None
|
|
+
|
|
+ def get_options(self):
|
|
+ retlist = []
|
|
+ sgroup = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
|
|
+
|
|
+ label = gtk.Label()
|
|
+ label.set_alignment(0, 0.5)
|
|
+ sgroup.add_widget(label)
|
|
+ label.set_markup('<b>Icon:</b>')
|
|
+ widget = gtk.Entry()
|
|
+
|
|
+ iconnode = self.node.find('icon')
|
|
+ if iconnode is not None:
|
|
+ icon = iconnode.text
|
|
+ else:
|
|
+ icon = ''
|
|
+ widget.props.text = icon
|
|
+ widget.connect('changed', self.on_subnode_changed, 'icon')
|
|
+
|
|
+ hbox = gtk.HBox()
|
|
+ hbox.pack_start(label)
|
|
+ hbox.pack_start(widget, True, True)
|
|
+ retlist.append(hbox)
|
|
+
|
|
+ label = gtk.Label()
|
|
+ label.set_alignment(0, 0.5)
|
|
+ sgroup.add_widget(label)
|
|
+ label.set_markup('<b>Icon mode:</b>')
|
|
+ widget = gtk.combo_box_new_text()
|
|
+ widget.append_text('Normal')
|
|
+ widget.append_text('File Path')
|
|
+ widget.props.active = iconnode is not None and iconnode.attrib.get('mode1') == 'file'
|
|
+ widget.connect('changed', self.on_icon_mode_changed)
|
|
+
|
|
+ hbox = gtk.HBox()
|
|
+ hbox.pack_start(label)
|
|
+ hbox.pack_start(widget, True, True)
|
|
+ retlist.append(hbox)
|
|
+
|
|
+ return retlist
|
|
+
|
|
+ def on_subnode_changed(self, widget, tag):
|
|
+ text = widget.props.text
|
|
+ subnode = self.node.find(tag)
|
|
+ if text:
|
|
+ if subnode is None:
|
|
+ subnode = etree.SubElement(self.node, tag)
|
|
+ subnode.text = text
|
|
+ else:
|
|
+ if subnode is not None:
|
|
+ self.node.remove(subnode)
|
|
+
|
|
+ def on_icon_mode_changed(self, widget):
|
|
+ iconnode = self.node.find('icon')
|
|
+ if widget.props.active:
|
|
+ if iconnode is None:
|
|
+ iconnode = etree.SubElement(self.node, 'icon')
|
|
+ iconnode.attrib['mode1'] = 'file'
|
|
+ elif 'mode1' in iconnode.attrib:
|
|
+ del iconnode.attrib['mode1']
|
|
|
|
+ def get_type(self):
|
|
+ return 'Windows list'
|
|
|
|
class Viewportlist(Item):
|
|
-
|
|
- def __init__(self, node=None):
|
|
- Item.__init__(self, node, type='viewportlist')
|
|
- self.editable = True
|
|
- self.wrap = self.node.find('wrap')
|
|
-
|
|
- def get_type(self):
|
|
- return 'Viewports list'
|
|
-
|
|
- def get_options(self):
|
|
- retlist = []
|
|
- widget = gtk.CheckButton("Wrap Viewports")
|
|
- widget.props.active = self.get_wrap()
|
|
- widget.connect('toggled', self.on_wrap_changed)
|
|
- retlist.append(widget)
|
|
-
|
|
- return retlist
|
|
-
|
|
- def get_wrap(self):
|
|
- if self.wrap is not None:
|
|
- return self.wrap.text == 'true'
|
|
- return False
|
|
-
|
|
- def on_wrap_changed(self, widget):
|
|
- if self.wrap is None:
|
|
- self.wrap = etree.SubElement(self.node, 'wrap')
|
|
- if widget.props.active:
|
|
- text = 'true'
|
|
- else:
|
|
- text = 'false'
|
|
- self.wrap.text = text
|
|
-
|
|
-
|
|
-class Reload(Item):
|
|
-
|
|
- def __init__(self, node=None):
|
|
- Item.__init__(self, node, type='reload')
|
|
-
|
|
- def get_type(self):
|
|
- return 'Reload'
|
|
-
|
|
+
|
|
+ def __init__(self, node=None): #change to be an attribute of viewportlist
|
|
+ Item.__init__(self, node, type='viewportlist')
|
|
+ self.editable = True
|
|
+ self.wrap = self.node.find('wrap')
|
|
+
|
|
+ def get_type(self):
|
|
+ return 'Viewports list'
|
|
+
|
|
+ def get_icon(self):
|
|
+ iconnode = self.node.find('icon')
|
|
+ if iconnode is not None:
|
|
+ return iconnode.text
|
|
+ else:
|
|
+ return None
|
|
+
|
|
+ def get_icon_mode(self):
|
|
+ iconnode = self.node.find('icon')
|
|
+ if iconnode is not None:
|
|
+ if iconnode.attrib.get('mode1') == 'file':
|
|
+ return iconnode.attrib.get('mode1')
|
|
+ else:
|
|
+ return None
|
|
+
|
|
+
|
|
+ def get_options(self):
|
|
+ retlist = []
|
|
+ sgroup = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
|
|
+ widget = gtk.CheckButton("Wrap Viewports")
|
|
+ widget.props.active = self.get_wrap()
|
|
+ widget.connect('toggled', self.on_wrap_changed)
|
|
+ retlist.append(widget)
|
|
+
|
|
+ label = gtk.Label()
|
|
+ label.set_alignment(0, 0.5)
|
|
+ sgroup.add_widget(label)
|
|
+ label.set_markup('<b>Icon:</b>')
|
|
+ widget = gtk.Entry()
|
|
+
|
|
+ iconnode = self.node.find('icon')
|
|
+ if iconnode is not None:
|
|
+ icon = iconnode.text
|
|
+ else:
|
|
+ icon = ''
|
|
+ widget.props.text = icon
|
|
+ widget.connect('changed', self.on_subnode_changed, 'icon')
|
|
+
|
|
+ hbox = gtk.HBox()
|
|
+ hbox.pack_start(label)
|
|
+ hbox.pack_start(widget, True, True)
|
|
+ retlist.append(hbox)
|
|
+
|
|
+ label = gtk.Label()
|
|
+ label.set_alignment(0, 0.5)
|
|
+ sgroup.add_widget(label)
|
|
+ label.set_markup('<b>Icon mode:</b>')
|
|
+ widget = gtk.combo_box_new_text()
|
|
+ widget.append_text('Normal')
|
|
+ widget.append_text('File Path')
|
|
+ widget.props.active = iconnode is not None and iconnode.attrib.get('mode1') == 'file'
|
|
+ widget.connect('changed', self.on_icon_mode_changed)
|
|
+
|
|
+ hbox = gtk.HBox()
|
|
+ hbox.pack_start(label)
|
|
+ hbox.pack_start(widget, True, True)
|
|
+ retlist.append(hbox)
|
|
+
|
|
+ label = gtk.Label()
|
|
+ label.set_alignment(0, 0.5)
|
|
+ sgroup.add_widget(label)
|
|
+ label.set_markup('<b>Viewport Icon:</b>')
|
|
+ widget = gtk.Entry()
|
|
+
|
|
+ vpiconnode = self.node.find('vpicon')
|
|
+ if vpiconnode is not None:
|
|
+ icon = vpiconnode.text
|
|
+ else:
|
|
+ icon = ''
|
|
+ widget.props.text = icon
|
|
+ widget.connect('changed', self.on_subnode_changed, 'vpicon')
|
|
+
|
|
+ hbox = gtk.HBox()
|
|
+ hbox.pack_start(label)
|
|
+ hbox.pack_start(widget, True, True)
|
|
+ retlist.append(hbox)
|
|
+
|
|
+ label = gtk.Label()
|
|
+ label.set_alignment(0, 0.5)
|
|
+ sgroup.add_widget(label)
|
|
+ label.set_markup('<b>Viewport Icon mode:</b>')
|
|
+ widget = gtk.combo_box_new_text()
|
|
+ widget.append_text('Normal')
|
|
+ widget.append_text('File Path')
|
|
+ widget.props.active = vpiconnode is not None and vpiconnode.attrib.get('mode1') == 'file'
|
|
+ widget.connect('changed', self.on_vpicon_mode_changed)
|
|
+
|
|
+ hbox = gtk.HBox()
|
|
+ hbox.pack_start(label)
|
|
+ hbox.pack_start(widget, True, True)
|
|
+ retlist.append(hbox)
|
|
+
|
|
+ return retlist
|
|
+
|
|
+ def get_wrap(self):
|
|
+ if self.wrap is not None:
|
|
+ return self.wrap.text == 'true'
|
|
+ return False
|
|
+
|
|
+ def on_subnode_changed(self, widget, tag):
|
|
+ text = widget.props.text
|
|
+ subnode = self.node.find(tag)
|
|
+ if text:
|
|
+ if subnode is None:
|
|
+ subnode = etree.SubElement(self.node, tag)
|
|
+ subnode.text = text
|
|
+ else:
|
|
+ if subnode is not None:
|
|
+ self.node.remove(subnode)
|
|
+
|
|
+ def on_wrap_changed(self, widget):
|
|
+ if self.wrap is None:
|
|
+ self.wrap = etree.SubElement(self.node, 'wrap')
|
|
+ if widget.props.active:
|
|
+ text = 'true'
|
|
+ else:
|
|
+ text = 'false'
|
|
+ self.wrap.text = text
|
|
+
|
|
+ def on_icon_mode_changed(self, widget):
|
|
+ iconnode = self.node.find('icon')
|
|
+ if widget.props.active:
|
|
+ if iconnode is None:
|
|
+ iconnode = etree.SubElement(self.node, 'icon')
|
|
+ iconnode.attrib['mode1'] = 'file'
|
|
+ elif 'mode1' in iconnode.attrib:
|
|
+ del iconnode.attrib['mode1']
|
|
+
|
|
+ def on_vpicon_mode_changed(self, widget):
|
|
+ iconnode = self.node.find('vpicon')
|
|
+ if widget.props.active:
|
|
+ if iconnode is None:
|
|
+ iconnode = etree.SubElement(self.node, 'vpicon')
|
|
+ iconnode.attrib['mode1'] = 'file'
|
|
+ elif 'mode1' in iconnode.attrib:
|
|
+ del iconnode.attrib['mode1']
|
|
|
|
class Separator(object):
|
|
-
|
|
- def __init__(self, node=None, parent=None):
|
|
- self.node = node
|
|
- self.editable = False
|
|
- if self.node is None:
|
|
- self.node = etree.Element('separator')
|
|
-
|
|
- def get_name(self):
|
|
- return '---'
|
|
-
|
|
- def get_type(self):
|
|
- return 'Separator'
|
|
+
|
|
+ def __init__(self, node=None, parent=None):
|
|
+ self.node = node
|
|
+ self.editable = False
|
|
+ if self.node is None:
|
|
+ self.node = etree.Element('separator')
|
|
+
|
|
+ def get_name(self):
|
|
+ return '---'
|
|
+
|
|
+ def get_type(self):
|
|
+ return 'Separator'
|
|
+
|
|
+ def get_icon(self):
|
|
+ return None
|
|
+
|
|
+ def get_icon_mode(self):
|
|
+ return None
|
|
+
|
|
+class Pipe(object):
|
|
+
|
|
+ def __init__(self, node=None):
|
|
+ self.node = node
|
|
+ self.children = []
|
|
+ self.editable = True
|
|
+
|
|
+ if node is None:
|
|
+ self.node = etree.Element('pipe', command='')
|
|
+
|
|
+ for child in self.node.getchildren():
|
|
+ try:
|
|
+ self.children.append(self.make_child(child))
|
|
+ except KeyError:
|
|
+ pass
|
|
+
|
|
+
|
|
+ def make_child(self, child):
|
|
+ return elements[child.tag](child)
|
|
+
|
|
+ def get_name(self):
|
|
+ name = self.node.attrib.get('command', '')
|
|
+ return name
|
|
+
|
|
+ def get_icon(self):
|
|
+ return None
|
|
+
|
|
+ def get_icon_mode(self):
|
|
+ return None
|
|
+
|
|
+ def get_type(self):
|
|
+ return 'Pipeitem'
|
|
+
|
|
+ def get_options(self):
|
|
+
|
|
+ retlist = []
|
|
+ sgroup = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
|
|
+
|
|
+ label = gtk.Label()
|
|
+ label.set_alignment(0, 0.5)
|
|
+ label.set_markup('<b>Command:</b>')
|
|
+ widget = gtk.Entry()
|
|
+ widget.props.text = self.node.attrib.get('command', '')
|
|
+ widget.connect('changed', self.on_command_changed)
|
|
+
|
|
+ hbox = gtk.HBox()
|
|
+ hbox.pack_start(label)
|
|
+ hbox.pack_start(widget, True, True)
|
|
+ retlist.append(hbox)
|
|
|
|
- def get_icon(self):
|
|
- return None
|
|
+ return retlist
|
|
|
|
+ def on_command_changed(self, widget):
|
|
+ self.node.attrib['command'] = widget.props.text
|
|
|
|
class Menu(object):
|
|
|
|
- def __init__(self, node=None):
|
|
- self.node = node
|
|
- self.children = []
|
|
- self.editable = True
|
|
-
|
|
- if node is None:
|
|
- self.node = etree.Element('menu', name='')
|
|
-
|
|
- for child in self.node.getchildren():
|
|
- try:
|
|
- self.children.append(self.make_child(child))
|
|
- except KeyError:
|
|
- pass
|
|
-
|
|
-
|
|
- def make_child(self, child):
|
|
- return elements[child.tag](child)
|
|
-
|
|
- def get_name(self):
|
|
- return self.node.attrib.get('name', '')
|
|
-
|
|
- def get_type(self):
|
|
- return 'Menu'
|
|
-
|
|
- def get_icon(self):
|
|
- return None
|
|
-
|
|
- def get_options(self):
|
|
-
|
|
- retlist = []
|
|
- label = gtk.Label()
|
|
- label.set_alignment(0, 0.5)
|
|
- label.set_markup('<b>Name:</b>')
|
|
- widget = gtk.Entry()
|
|
- widget.props.text = self.node.attrib.get('name', '')
|
|
- widget.connect('changed', self.on_name_changed)
|
|
- hbox = gtk.HBox()
|
|
- hbox.pack_start(label)
|
|
- hbox.pack_start(widget, True, True)
|
|
- retlist.append(hbox)
|
|
-
|
|
- return retlist
|
|
-
|
|
- def on_name_changed(self, widget):
|
|
- self.node.attrib['name'] = widget.props.text
|
|
-
|
|
+ def __init__(self, node=None):
|
|
+ self.node = node
|
|
+ self.children = []
|
|
+ self.editable = True
|
|
+
|
|
+ if node is None:
|
|
+ self.node = etree.Element('menu', name='')
|
|
+
|
|
+ for child in self.node.getchildren():
|
|
+ try:
|
|
+ self.children.append(self.make_child(child))
|
|
+ except KeyError:
|
|
+ pass
|
|
+
|
|
+
|
|
+ def make_child(self, child):
|
|
+ return elements[child.tag](child)
|
|
+
|
|
+ def get_name(self):
|
|
+ name = self.node.attrib.get('name', '')
|
|
+ if self.node.attrib.get('mode') == 'exec':
|
|
+ name = 'exec: %s' %name
|
|
+ return name
|
|
+
|
|
+ def get_icon(self):
|
|
+ return self.node.attrib.get('icon', '')
|
|
+
|
|
+ def get_icon_mode(self):
|
|
+ if self.node.attrib.get('mode1') == 'file':
|
|
+ return self.node.attrib.get('mode1')
|
|
+ else:
|
|
+ return None
|
|
+
|
|
+ def get_type(self):
|
|
+ return 'Menu'
|
|
+
|
|
+ def get_options(self):
|
|
+
|
|
+ retlist = []
|
|
+ sgroup = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
|
|
+
|
|
+ label = gtk.Label()
|
|
+ label.set_alignment(0, 0.5)
|
|
+ label.set_markup('<b>Name:</b>')
|
|
+ widget = gtk.Entry()
|
|
+ widget.props.text = self.node.attrib.get('name', '')
|
|
+ widget.connect('changed', self.on_name_changed)
|
|
+
|
|
+ hbox = gtk.HBox()
|
|
+ hbox.pack_start(label)
|
|
+ hbox.pack_start(widget, True, True)
|
|
+ retlist.append(hbox)
|
|
+
|
|
+ label = gtk.Label()
|
|
+ label.set_alignment(0, 0.5)
|
|
+ sgroup.add_widget(label)
|
|
+ label.set_markup('<b>Name mode:</b>')
|
|
+ widget = gtk.combo_box_new_text()
|
|
+ widget.append_text('Normal')
|
|
+ widget.append_text('Execute')
|
|
+ widget.props.active = self.node.attrib.get('name') is not None and self.node.attrib.get('mode') == 'exec'
|
|
+ widget.connect('changed', self.on_name_mode_changed)
|
|
+
|
|
+ hbox = gtk.HBox()
|
|
+ hbox.pack_start(label)
|
|
+ hbox.pack_start(widget, True, True)
|
|
+ retlist.append(hbox)
|
|
+
|
|
+ #TODO:Make this actually edit icon
|
|
+ label = gtk.Label()
|
|
+ label.set_alignment(0, 0.5)
|
|
+ sgroup.add_widget(label)
|
|
+ label.set_markup('<b>Icon:</b>')
|
|
+ widget = gtk.Entry()
|
|
+ if self.node.attrib.get('icon') is not None:
|
|
+ widget.props.text = self.node.attrib.get('icon')
|
|
+ else:
|
|
+ widget.props.text = ''
|
|
+ #widget.props.text = self.node.attrib.get('icon')
|
|
+ widget.connect('changed', self.on_icon_changed)
|
|
+
|
|
+ hbox = gtk.HBox()
|
|
+ hbox.pack_start(label)
|
|
+ hbox.pack_start(widget, True, True)
|
|
+ retlist.append(hbox)
|
|
+
|
|
+ label = gtk.Label()
|
|
+ label.set_alignment(0, 0.5)
|
|
+ sgroup.add_widget(label)
|
|
+ label.set_markup('<b>Icon mode:</b>')
|
|
+ widget = gtk.combo_box_new_text()
|
|
+ widget.append_text('Normal')
|
|
+ widget.append_text('File Path')
|
|
+ widget.props.active = self.node.attrib.get('icon') is not None and self.node.attrib.get('mode1') == 'file'
|
|
+ widget.connect('changed', self.on_icon_mode_changed)
|
|
+
|
|
+ hbox = gtk.HBox()
|
|
+ hbox.pack_start(label)
|
|
+ hbox.pack_start(widget, True, True)
|
|
+ retlist.append(hbox)
|
|
+
|
|
+ return retlist
|
|
+
|
|
+ def on_name_changed(self, widget):
|
|
+ self.node.attrib['name'] = widget.props.text
|
|
+ def on_name_mode_changed(self, widget): #EDIT THIS
|
|
+ if widget.props.active:
|
|
+ self.node.attrib['mode'] = 'exec'
|
|
+ elif 'mode' in self.node.attrib:
|
|
+ del self.node.attrib['mode']
|
|
+ def on_icon_changed(self, widget):
|
|
+ if widget.props.text != '':
|
|
+ self.node.attrib['icon'] = widget.props.text
|
|
+ else:
|
|
+ del self.node.attrib['icon']
|
|
+ def on_icon_mode_changed(self, widget): #EDIT THIS
|
|
+ if widget.props.active:
|
|
+ self.node.attrib['mode1'] = 'file'
|
|
+ elif 'mode1' in self.node.attrib:
|
|
+ del self.node.attrib['mode1']
|
|
|
|
itemtypes = {
|
|
- 'launcher': Launcher,
|
|
- 'windowlist': Windowlist,
|
|
- 'viewportlist': Viewportlist,
|
|
- 'reload': Reload,
|
|
+ 'launcher': Launcher,
|
|
+ 'windowlist': Windowlist,
|
|
+ 'viewportlist': Viewportlist,
|
|
}
|
|
|
|
|
|
def make_item(node):
|
|
|
|
- itemtype = node.attrib.get('type')
|
|
- return itemtypes.get(itemtype, Item)(node)
|
|
+ itemtype = node.attrib.get('type')
|
|
+ return itemtypes.get(itemtype, Item)(node)
|
|
|
|
|
|
def indent(elem, level=0):
|
|
- i = "\n" + level*" "
|
|
- if len(elem):
|
|
- if not elem.text or not elem.text.strip():
|
|
- elem.text = i + " "
|
|
- for e in elem:
|
|
- indent(e, level+1)
|
|
- if not e.tail or not e.tail.strip():
|
|
- e.tail = i + " "
|
|
- if not e.tail or not e.tail.strip():
|
|
- e.tail = i
|
|
- else:
|
|
- if level and (not elem.tail or not elem.tail.strip()):
|
|
- elem.tail = i
|
|
+ i = "\n" + level*" "
|
|
+ if len(elem):
|
|
+ if not elem.text or not elem.text.strip():
|
|
+ elem.text = i + " "
|
|
+ for e in elem:
|
|
+ indent(e, level+1)
|
|
+ if not e.tail or not e.tail.strip():
|
|
+ e.tail = i + " "
|
|
+ if not e.tail or not e.tail.strip():
|
|
+ e.tail = i
|
|
+ else:
|
|
+ if level and (not elem.tail or not elem.tail.strip()):
|
|
+ elem.tail = i
|
|
|
|
def write_menu():
|
|
|
|
- indent(menu.node)
|
|
- menufile.write(open(os.path.join(configdir, 'menu.xml'), 'w'))
|
|
+ indent(menu.node)
|
|
+ menufile.write(open(filename, 'w'))
|
|
|
|
- if bus is not None:
|
|
- try:
|
|
- bus.get_object('org.compiz_fusion.deskmenu',
|
|
- '/org/compiz_fusion/deskmenu/menu').reload()
|
|
- except dbus.DBusException:
|
|
- return
|
|
-
|
|
-elements = {'menu': Menu, 'item': make_item, 'separator': Separator}
|
|
+elements = {'menu': Menu, 'item': make_item, 'separator': Separator, 'pipe': Pipe}
|
|
|
|
elementsbyname = {
|
|
- 'Launcher': Launcher,
|
|
- 'Windows List': Windowlist,
|
|
- 'Viewports List': Viewportlist,
|
|
- 'Reload': Reload,
|
|
- 'Separator': Separator,
|
|
- 'Menu': Menu,
|
|
+ 'Launcher': Launcher,
|
|
+ 'Windows List': Windowlist,
|
|
+ 'Viewports List': Viewportlist,
|
|
+ 'Separator': Separator,
|
|
+ 'Menu': Menu,
|
|
+ 'Pipeitem': Pipe
|
|
}
|
|
|
|
|
|
if __name__ == '__main__':
|
|
-
|
|
- if dbus:
|
|
- try:
|
|
- bus = dbus.SessionBus()
|
|
- except dbus.DBusException:
|
|
- bus = None
|
|
- else:
|
|
- bus = None
|
|
-
|
|
- filename = BaseDirectory.load_first_config('compiz/deskmenu/menu.xml')
|
|
- menufile = etree.parse(filename)
|
|
- root = menufile.getroot()
|
|
- menu = Menu(root)
|
|
- configdir = BaseDirectory.save_config_path('compiz/deskmenu')
|
|
- DeskmenuEditor()
|
|
- gtk.main()
|
|
-
|
|
+ if len(sys.argv) == 2 :
|
|
+ if open(sys.argv[1]):
|
|
+ filename = sys.argv[1]
|
|
+ else:
|
|
+ filename = BaseDirectory.load_first_config('compiz/deskmenu/menu.xml')
|
|
+ menufile = etree.parse(filename)
|
|
+ root = menufile.getroot()
|
|
+ menu = Menu(root)
|
|
+ DeskmenuEditor()
|
|
+ gtk.main()
|
|
diff -aur compiz-deskmenu/deskmenu-menu.c compiz-deskmenu3/deskmenu-menu.c
|
|
--- compiz-deskmenu/deskmenu-menu.c 2008-03-14 16:25:23.000000000 -0700
|
|
+++ compiz-deskmenu3/deskmenu-menu.c 2010-11-16 15:41:15.000000000 -0800
|
|
@@ -1,658 +1,774 @@
|
|
-/*
|
|
- * compiz-deskmenu is free software; you can redistribute it and/or modify
|
|
- * it under the terms of the GNU General Public License as published by
|
|
- * the Free Software Foundation; either version 2 of the License, or
|
|
- * (at your option) any later version.
|
|
- *
|
|
- * compiz-deskmenu is distributed in the hope that it will be useful,
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
- * GNU General Public License for more details.
|
|
- *
|
|
- * You should have received a copy of the GNU General Public License
|
|
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
- *
|
|
- * Copyright 2008 Christopher Williams <christopherw@verizon.net>
|
|
- */
|
|
-
|
|
-#include <stdlib.h>
|
|
-#include <string.h>
|
|
-#include <dbus/dbus-glib-lowlevel.h>
|
|
-#include <gtk/gtk.h>
|
|
-
|
|
-#define HAVE_WNCK 1
|
|
-
|
|
-#if HAVE_WNCK
|
|
-#include "deskmenu-wnck.h"
|
|
-#endif
|
|
-
|
|
-#include "deskmenu-menu.h"
|
|
-#include "deskmenu-glue.h"
|
|
-
|
|
-
|
|
-G_DEFINE_TYPE(Deskmenu, deskmenu, G_TYPE_OBJECT)
|
|
-
|
|
-GQuark
|
|
-deskmenu_error_quark (void)
|
|
-{
|
|
- static GQuark quark = 0;
|
|
- if (!quark)
|
|
- quark = g_quark_from_static_string ("deskmenu_error");
|
|
- return quark;
|
|
-}
|
|
-
|
|
-static void
|
|
-quit (GtkWidget *widget,
|
|
- gpointer data)
|
|
-{
|
|
- gtk_main_quit ();
|
|
-}
|
|
-
|
|
-static void
|
|
-launcher_activated (GtkWidget *widget,
|
|
- gchar *command)
|
|
-{
|
|
- GError *error = NULL;
|
|
- Deskmenu *deskmenu;
|
|
-
|
|
- deskmenu = g_object_get_data (G_OBJECT (widget), "deskmenu");
|
|
-
|
|
- if (!gdk_spawn_on_screen (gdk_screen_get_default (),
|
|
- g_get_home_dir (),
|
|
- g_strsplit (command, " ", 0),
|
|
- deskmenu->envp, G_SPAWN_SEARCH_PATH,
|
|
- NULL, NULL, NULL, &error))
|
|
- {
|
|
- GtkWidget *message = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_ERROR,
|
|
- GTK_BUTTONS_CLOSE, "%s", error->message);
|
|
- gtk_dialog_run (GTK_DIALOG (message));
|
|
- gtk_widget_destroy (message);
|
|
- }
|
|
-
|
|
-}
|
|
-
|
|
-static void
|
|
-launcher_name_exec_update (GtkWidget *label)
|
|
-{
|
|
- gchar *exec, *stdout;
|
|
- exec = g_object_get_data (G_OBJECT (label), "exec");
|
|
- if (g_spawn_command_line_sync (exec, &stdout, NULL, NULL, NULL))
|
|
- gtk_label_set_text (GTK_LABEL (label), g_strstrip(stdout));
|
|
- else
|
|
- gtk_label_set_text (GTK_LABEL (label), "execution error");
|
|
- g_free (stdout);
|
|
-}
|
|
-
|
|
-static void
|
|
-deskmenu_construct_item (Deskmenu *deskmenu)
|
|
-{
|
|
- DeskmenuItem *item = deskmenu->current_item;
|
|
- GtkWidget *menu_item;
|
|
- gchar *name, *icon, *command;
|
|
-
|
|
- switch (item->type)
|
|
- {
|
|
- case DESKMENU_ITEM_LAUNCHER:
|
|
- if (item->name_exec)
|
|
- {
|
|
- GtkWidget *label;
|
|
- GHook *hook;
|
|
-
|
|
- name = g_strstrip (item->name->str);
|
|
-
|
|
- menu_item = gtk_image_menu_item_new ();
|
|
- label = gtk_label_new_with_mnemonic (NULL);
|
|
- gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
|
|
-
|
|
- g_object_set_data (G_OBJECT (label), "exec", g_strdup (name));
|
|
- gtk_container_add (GTK_CONTAINER (menu_item), label);
|
|
- hook = g_hook_alloc (deskmenu->show_hooks);
|
|
-
|
|
- hook->data = (gpointer) label;
|
|
- hook->func = (GHookFunc *) launcher_name_exec_update;
|
|
- g_hook_append (deskmenu->show_hooks, hook);
|
|
- }
|
|
- else
|
|
- {
|
|
- if (item->name)
|
|
- name = g_strstrip (item->name->str);
|
|
- else
|
|
- name = "";
|
|
-
|
|
- menu_item = gtk_image_menu_item_new_with_mnemonic (name);
|
|
-
|
|
- }
|
|
-
|
|
- if (item->icon)
|
|
- {
|
|
- icon = g_strstrip (item->icon->str);
|
|
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),
|
|
- gtk_image_new_from_icon_name (icon, GTK_ICON_SIZE_MENU));
|
|
- }
|
|
-
|
|
- if (item->command)
|
|
- {
|
|
- command = g_strstrip (item->command->str);
|
|
- g_object_set_data (G_OBJECT (menu_item), "deskmenu", deskmenu);
|
|
- g_signal_connect (G_OBJECT (menu_item), "activate",
|
|
- G_CALLBACK (launcher_activated), g_strdup (command));
|
|
- }
|
|
-
|
|
- gtk_menu_shell_append (GTK_MENU_SHELL (deskmenu->current_menu),
|
|
- menu_item);
|
|
- break;
|
|
-
|
|
-#if HAVE_WNCK
|
|
- case DESKMENU_ITEM_WINDOWLIST:
|
|
- menu_item = gtk_menu_item_new_with_mnemonic ("_Windows");
|
|
-
|
|
- DeskmenuWindowlist *windowlist = deskmenu_windowlist_new ();
|
|
-
|
|
- gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item),
|
|
- windowlist->menu);
|
|
- gtk_menu_shell_append (GTK_MENU_SHELL (deskmenu->current_menu),
|
|
- menu_item);
|
|
- break;
|
|
-
|
|
- case DESKMENU_ITEM_VIEWPORTLIST:
|
|
- menu_item = gtk_menu_item_new_with_mnemonic ("_Viewports");
|
|
-
|
|
- DeskmenuVplist *vplist = deskmenu_vplist_new ();
|
|
-
|
|
- if (item->wrap
|
|
- && strcmp (g_strstrip (item->wrap->str), "true") == 0)
|
|
- vplist->wrap = TRUE;
|
|
-
|
|
- gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item),
|
|
- vplist->menu);
|
|
- gtk_menu_shell_append (GTK_MENU_SHELL (deskmenu->current_menu),
|
|
- menu_item);
|
|
- break;
|
|
-#endif
|
|
- case DESKMENU_ITEM_RELOAD:
|
|
- menu_item = gtk_image_menu_item_new_with_mnemonic ("_Reload");
|
|
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),
|
|
- gtk_image_new_from_stock (GTK_STOCK_REFRESH,
|
|
- GTK_ICON_SIZE_MENU));
|
|
- g_signal_connect (G_OBJECT (menu_item), "activate",
|
|
- G_CALLBACK (quit), NULL);
|
|
- gtk_menu_shell_append (GTK_MENU_SHELL (deskmenu->current_menu),
|
|
- menu_item);
|
|
- break;
|
|
-
|
|
- default:
|
|
- break;
|
|
- }
|
|
-
|
|
-}
|
|
-/* The handler functions. */
|
|
-
|
|
-static void
|
|
-start_element (GMarkupParseContext *context,
|
|
- const gchar *element_name,
|
|
- const gchar **attr_names,
|
|
- const gchar **attr_values,
|
|
- gpointer user_data,
|
|
- GError **error)
|
|
-{
|
|
- Deskmenu *deskmenu = DESKMENU (user_data);
|
|
- DeskmenuElementType element_type;
|
|
- const gchar **ncursor = attr_names, **vcursor = attr_values;
|
|
- GtkWidget *item, *menu;
|
|
-
|
|
- element_type = GPOINTER_TO_INT (g_hash_table_lookup
|
|
- (deskmenu->element_hash, element_name));
|
|
-
|
|
- if ((deskmenu->menu && !deskmenu->current_menu)
|
|
- || (!deskmenu->menu && element_type != DESKMENU_ELEMENT_MENU))
|
|
- {
|
|
- gint line_num, char_num;
|
|
- g_markup_parse_context_get_position (context, &line_num, &char_num);
|
|
- g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
|
|
- "Error on line %d char %d: Element '%s' declared outside of "
|
|
- "toplevel menu element", line_num, char_num, element_name);
|
|
- return;
|
|
- }
|
|
-
|
|
- switch (element_type)
|
|
- {
|
|
- case DESKMENU_ELEMENT_MENU:
|
|
-
|
|
- if (deskmenu->current_item != NULL)
|
|
- {
|
|
- gint line_num, char_num;
|
|
- g_markup_parse_context_get_position (context, &line_num,
|
|
- &char_num);
|
|
- g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
|
|
- "Error on line %d char %d: Element 'menu' cannot be nested "
|
|
- "inside of an item element", line_num, char_num);
|
|
- return;
|
|
- }
|
|
-
|
|
- if (!deskmenu->menu)
|
|
- {
|
|
- deskmenu->menu = gtk_menu_new ();
|
|
- g_object_set_data (G_OBJECT (deskmenu->menu), "parent menu",
|
|
- NULL);
|
|
- deskmenu->current_menu = deskmenu->menu;
|
|
- }
|
|
- else
|
|
- {
|
|
- gchar *name = NULL;
|
|
- while (*ncursor)
|
|
- {
|
|
- if (strcmp (*ncursor, "name") == 0)
|
|
- name = g_strdup (*vcursor);
|
|
- else
|
|
- g_set_error (error, G_MARKUP_ERROR,
|
|
- G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
|
|
- "Unknown attribute: %s", *ncursor);
|
|
- ncursor++;
|
|
- vcursor++;
|
|
- }
|
|
- if (name)
|
|
- item = gtk_menu_item_new_with_mnemonic (name);
|
|
- else
|
|
- item = gtk_menu_item_new_with_mnemonic ("");
|
|
- gtk_menu_shell_append (GTK_MENU_SHELL (deskmenu->current_menu),
|
|
- item);
|
|
- menu = gtk_menu_new ();
|
|
- g_object_set_data (G_OBJECT (menu), "parent menu",
|
|
- deskmenu->current_menu);
|
|
- deskmenu->current_menu = menu;
|
|
- gtk_menu_item_set_submenu (GTK_MENU_ITEM (item),
|
|
- deskmenu->current_menu);
|
|
- g_free (name);
|
|
- }
|
|
- break;
|
|
-
|
|
- case DESKMENU_ELEMENT_SEPARATOR:
|
|
- break; /* build it in the end function */
|
|
-
|
|
- case DESKMENU_ELEMENT_ITEM:
|
|
-
|
|
- if (deskmenu->current_item != NULL)
|
|
- {
|
|
- gint line_num, char_num;
|
|
- g_markup_parse_context_get_position (context, &line_num,
|
|
- &char_num);
|
|
- g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
|
|
- "Error on line %d char %d: Element 'item' cannot be nested "
|
|
- "inside of another item element", line_num, char_num);
|
|
- return;
|
|
- }
|
|
-
|
|
- deskmenu->current_item = g_slice_new0 (DeskmenuItem);
|
|
- while (*ncursor)
|
|
- {
|
|
- if (strcmp (*ncursor, "type") == 0)
|
|
- deskmenu->current_item->type = GPOINTER_TO_INT
|
|
- (g_hash_table_lookup (deskmenu->item_hash, *vcursor));
|
|
- else
|
|
- g_set_error (error, G_MARKUP_ERROR,
|
|
- G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
|
|
- "Unknown attribute: %s", *ncursor);
|
|
- ncursor++;
|
|
- vcursor++;
|
|
- }
|
|
- break;
|
|
-
|
|
- case DESKMENU_ELEMENT_NAME:
|
|
- while (*ncursor)
|
|
- {
|
|
- if ((strcmp (*ncursor, "mode") == 0)
|
|
- && (strcmp (*vcursor, "exec") == 0))
|
|
- deskmenu->current_item->name_exec = TRUE;
|
|
- ncursor++;
|
|
- vcursor++;
|
|
- } /* no break here to let it fall through */
|
|
- case DESKMENU_ELEMENT_ICON:
|
|
- case DESKMENU_ELEMENT_COMMAND:
|
|
- case DESKMENU_ELEMENT_WRAP:
|
|
- if (deskmenu->current_item)
|
|
- deskmenu->current_item->current_element = element_type;
|
|
- break;
|
|
-
|
|
- default:
|
|
- g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
|
|
- "Unknown element: %s", element_name);
|
|
- break;
|
|
- }
|
|
-}
|
|
-
|
|
-static void
|
|
-text (GMarkupParseContext *context,
|
|
- const gchar *text,
|
|
- gsize text_len,
|
|
- gpointer user_data,
|
|
- GError **error)
|
|
-{
|
|
- Deskmenu *deskmenu = DESKMENU (user_data);
|
|
- DeskmenuItem *item = deskmenu->current_item;
|
|
-
|
|
- if (!(item && item->current_element))
|
|
- return;
|
|
-
|
|
- switch (item->current_element)
|
|
- {
|
|
- case DESKMENU_ELEMENT_NAME:
|
|
- if (!item->name)
|
|
- item->name = g_string_new_len (text, text_len);
|
|
- else
|
|
- g_string_append_len (item->name, text, text_len);
|
|
- break;
|
|
-
|
|
- case DESKMENU_ELEMENT_ICON:
|
|
- if (!item->icon)
|
|
- item->icon = g_string_new_len (text, text_len);
|
|
- else
|
|
- g_string_append_len (item->icon, text, text_len);
|
|
- break;
|
|
-
|
|
- case DESKMENU_ELEMENT_COMMAND:
|
|
- if (!item->command)
|
|
- item->command = g_string_new_len (text, text_len);
|
|
- else
|
|
- g_string_append_len (item->command, text, text_len);
|
|
- break;
|
|
-
|
|
- case DESKMENU_ELEMENT_WRAP:
|
|
- if (!item->wrap)
|
|
- item->wrap = g_string_new_len (text, text_len);
|
|
- else
|
|
- g_string_append_len (item->wrap, text, text_len);
|
|
- break;
|
|
-
|
|
- default:
|
|
- break;
|
|
- }
|
|
-
|
|
-}
|
|
-
|
|
-static void
|
|
-end_element (GMarkupParseContext *context,
|
|
- const gchar *element_name,
|
|
- gpointer user_data,
|
|
- GError **error)
|
|
-{
|
|
-
|
|
- DeskmenuElementType element_type;
|
|
- Deskmenu *deskmenu = DESKMENU (user_data);
|
|
- GtkWidget *parent, *item;
|
|
- element_type = GPOINTER_TO_INT (g_hash_table_lookup
|
|
- (deskmenu->element_hash, element_name));
|
|
-
|
|
- switch (element_type)
|
|
- {
|
|
- case DESKMENU_ELEMENT_MENU:
|
|
-
|
|
- g_return_if_fail (deskmenu->current_item == NULL);
|
|
-
|
|
- parent = g_object_get_data (G_OBJECT (deskmenu->current_menu),
|
|
- "parent menu");
|
|
-
|
|
- deskmenu->current_menu = parent;
|
|
-
|
|
- break;
|
|
-
|
|
- case DESKMENU_ELEMENT_SEPARATOR:
|
|
- item = gtk_separator_menu_item_new ();
|
|
- gtk_menu_shell_append (GTK_MENU_SHELL (deskmenu->current_menu),
|
|
- item);
|
|
- break;
|
|
-
|
|
- case DESKMENU_ELEMENT_ITEM:
|
|
-
|
|
- g_return_if_fail (deskmenu->current_item != NULL);
|
|
-
|
|
- /* finally make the item ^_^ */
|
|
- deskmenu_construct_item (deskmenu);
|
|
-
|
|
- /* free data used to make it */
|
|
- if (deskmenu->current_item->name)
|
|
- g_string_free (deskmenu->current_item->name, TRUE);
|
|
- if (deskmenu->current_item->icon)
|
|
- g_string_free (deskmenu->current_item->icon, TRUE);
|
|
- if (deskmenu->current_item->command)
|
|
- g_string_free (deskmenu->current_item->command, TRUE);
|
|
- if (deskmenu->current_item->wrap)
|
|
- g_string_free (deskmenu->current_item->wrap, TRUE);
|
|
- g_slice_free (DeskmenuItem, deskmenu->current_item);
|
|
- deskmenu->current_item = NULL;
|
|
- break;
|
|
-
|
|
- default:
|
|
- break;
|
|
- }
|
|
-}
|
|
-
|
|
-/* The list of what handler does what. */
|
|
-static GMarkupParser parser = {
|
|
- start_element,
|
|
- end_element,
|
|
- text,
|
|
- NULL,
|
|
- NULL
|
|
-};
|
|
-
|
|
-
|
|
-/* Class init */
|
|
-static void
|
|
-deskmenu_class_init (DeskmenuClass *deskmenu_class)
|
|
-{
|
|
- dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (deskmenu_class),
|
|
- &dbus_glib_deskmenu_object_info);
|
|
-}
|
|
-
|
|
-/* Instance init */
|
|
-static void
|
|
-deskmenu_init (Deskmenu *deskmenu)
|
|
-{
|
|
-
|
|
- deskmenu->show_hooks = g_slice_new0 (GHookList);
|
|
-
|
|
- g_hook_list_init (deskmenu->show_hooks, sizeof (GHook));
|
|
-
|
|
-
|
|
- deskmenu->menu = NULL;
|
|
- deskmenu->current_menu = NULL;
|
|
- deskmenu->current_item = NULL;
|
|
-
|
|
- deskmenu->envp = NULL;
|
|
-
|
|
- deskmenu->item_hash = g_hash_table_new (g_str_hash, g_str_equal);
|
|
-
|
|
- g_hash_table_insert (deskmenu->item_hash, "launcher",
|
|
- GINT_TO_POINTER (DESKMENU_ITEM_LAUNCHER));
|
|
-#if HAVE_WNCK
|
|
- g_hash_table_insert (deskmenu->item_hash, "windowlist",
|
|
- GINT_TO_POINTER (DESKMENU_ITEM_WINDOWLIST));
|
|
- g_hash_table_insert (deskmenu->item_hash, "viewportlist",
|
|
- GINT_TO_POINTER (DESKMENU_ITEM_VIEWPORTLIST));
|
|
-#endif
|
|
- g_hash_table_insert (deskmenu->item_hash, "reload",
|
|
- GINT_TO_POINTER (DESKMENU_ITEM_RELOAD));
|
|
-
|
|
- deskmenu->element_hash = g_hash_table_new (g_str_hash, g_str_equal);
|
|
-
|
|
- g_hash_table_insert (deskmenu->element_hash, "menu",
|
|
- GINT_TO_POINTER (DESKMENU_ELEMENT_MENU));
|
|
- g_hash_table_insert (deskmenu->element_hash, "separator",
|
|
- GINT_TO_POINTER (DESKMENU_ELEMENT_SEPARATOR));
|
|
- g_hash_table_insert (deskmenu->element_hash, "item",
|
|
- GINT_TO_POINTER (DESKMENU_ELEMENT_ITEM));
|
|
- g_hash_table_insert (deskmenu->element_hash, "name",
|
|
- GINT_TO_POINTER (DESKMENU_ELEMENT_NAME));
|
|
- g_hash_table_insert (deskmenu->element_hash, "icon",
|
|
- GINT_TO_POINTER (DESKMENU_ELEMENT_ICON));
|
|
- g_hash_table_insert (deskmenu->element_hash, "command",
|
|
- GINT_TO_POINTER (DESKMENU_ELEMENT_COMMAND));
|
|
- g_hash_table_insert (deskmenu->element_hash, "wrap",
|
|
- GINT_TO_POINTER (DESKMENU_ELEMENT_WRAP));
|
|
-
|
|
-}
|
|
-
|
|
-static void
|
|
-deskmenu_parse_file (Deskmenu *deskmenu,
|
|
- gchar *configpath)
|
|
-{
|
|
- GError *error = NULL;
|
|
- gboolean success = FALSE;
|
|
- gchar *text;
|
|
- gsize length;
|
|
-
|
|
- if (!configpath)
|
|
- configpath = g_build_path (G_DIR_SEPARATOR_S,
|
|
- g_get_user_config_dir (),
|
|
- "compiz",
|
|
- "deskmenu",
|
|
- "menu.xml",
|
|
- NULL);
|
|
-
|
|
- GMarkupParseContext *context = g_markup_parse_context_new (&parser,
|
|
- 0, deskmenu, NULL);
|
|
-
|
|
- if (!g_file_get_contents (configpath, &text, &length, NULL))
|
|
- {
|
|
- const gchar* const *cursor = g_get_system_config_dirs ();
|
|
- gchar *path = NULL;
|
|
- while (*cursor)
|
|
- {
|
|
- g_free (configpath);
|
|
- g_free (path);
|
|
- path = g_strdup (*cursor);
|
|
- configpath = g_build_path (G_DIR_SEPARATOR_S,
|
|
- path,
|
|
- "compiz",
|
|
- "deskmenu",
|
|
- "menu.xml",
|
|
- NULL);
|
|
-
|
|
- if (g_file_get_contents (configpath, &text, &length, NULL))
|
|
- {
|
|
- success = TRUE;
|
|
- g_free (path);
|
|
- break;
|
|
- }
|
|
- cursor++;
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- success = TRUE;
|
|
- }
|
|
-
|
|
- if (!success)
|
|
- {
|
|
- g_printerr ("Couldn't find a menu file\n");
|
|
- exit (1);
|
|
- }
|
|
-
|
|
- if (!g_markup_parse_context_parse (context, text, length, &error)
|
|
- || !g_markup_parse_context_end_parse (context, &error))
|
|
- {
|
|
- g_printerr ("Parse of %s failed with message: %s \n",
|
|
- configpath, error->message);
|
|
- g_error_free (error);
|
|
- exit (1);
|
|
- }
|
|
-
|
|
- g_free(text);
|
|
- g_free (configpath);
|
|
- g_markup_parse_context_free (context);
|
|
-
|
|
- gtk_widget_show_all (deskmenu->menu);
|
|
-}
|
|
-
|
|
-/* The show method */
|
|
-gboolean
|
|
-deskmenu_show (Deskmenu *deskmenu,
|
|
- gchar **env,
|
|
- GError **error)
|
|
-{
|
|
- g_hook_list_invoke (deskmenu->show_hooks, FALSE);
|
|
-
|
|
- if (deskmenu->envp)
|
|
- g_strfreev (deskmenu->envp);
|
|
-
|
|
- deskmenu->envp = g_strdupv (env);
|
|
-
|
|
- gtk_menu_popup (GTK_MENU (deskmenu->menu),
|
|
- NULL, NULL, NULL, NULL,
|
|
- 0, 0);
|
|
- return TRUE;
|
|
-}
|
|
-
|
|
-/* The reload method */
|
|
-gboolean
|
|
-deskmenu_reload (Deskmenu *deskmenu,
|
|
- GError **error)
|
|
-{
|
|
- gtk_main_quit ();
|
|
- return TRUE;
|
|
-}
|
|
-
|
|
-int
|
|
-main (int argc,
|
|
- char **argv)
|
|
-{
|
|
- DBusGConnection *connection;
|
|
- GError *error = NULL;
|
|
- GObject *deskmenu;
|
|
-
|
|
- g_type_init ();
|
|
-
|
|
- gchar *filename = NULL;
|
|
- GOptionContext *context;
|
|
- GOptionEntry entries[] =
|
|
- {
|
|
- { "menu", 'm', 0, G_OPTION_ARG_FILENAME, &filename,
|
|
- "Use FILE instead of the default menu file", "FILE" },
|
|
- { NULL, 0, 0, 0, NULL, NULL, NULL }
|
|
- };
|
|
-
|
|
- context = g_option_context_new (NULL);
|
|
- g_option_context_add_main_entries (context, entries, NULL);
|
|
- g_option_context_add_group (context, gtk_get_option_group (TRUE));
|
|
- if (!g_option_context_parse (context, &argc, &argv, &error))
|
|
- {
|
|
- g_printerr ("option parsing failed: %s", error->message);
|
|
- g_error_free (error);
|
|
- exit (1);
|
|
- }
|
|
- g_option_context_free (context);
|
|
-
|
|
- /* Obtain a connection to the session bus */
|
|
- connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
|
|
- if (connection == NULL)
|
|
- {
|
|
- g_printerr ("Failed to open connection to bus: %s", error->message);
|
|
- g_error_free (error);
|
|
- exit (1);
|
|
- }
|
|
-
|
|
-#if HAVE_WNCK
|
|
- wnck_set_client_type (WNCK_CLIENT_TYPE_PAGER);
|
|
-#endif
|
|
-
|
|
- gtk_init (&argc, &argv);
|
|
-
|
|
- deskmenu = g_object_new (DESKMENU_TYPE, NULL);
|
|
-
|
|
- deskmenu_parse_file (DESKMENU (deskmenu), filename);
|
|
-
|
|
- dbus_g_connection_register_g_object (connection,
|
|
- DESKMENU_PATH_DBUS,
|
|
- deskmenu);
|
|
-
|
|
- if (!dbus_bus_request_name (dbus_g_connection_get_connection (connection),
|
|
- DESKMENU_SERVICE_DBUS,
|
|
- DBUS_NAME_FLAG_REPLACE_EXISTING,
|
|
- NULL))
|
|
- return 1;
|
|
-
|
|
- gtk_main ();
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
+/*
|
|
+ * compiz-deskmenu is free software; you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation; either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * compiz-deskmenu is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License
|
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
+ *
|
|
+ * Copyright 2008 Christopher Williams <christopherw@verizon.net>
|
|
+ */
|
|
+
|
|
+ /*
|
|
+Roadmap:
|
|
+Necessary:
|
|
+ TODO: Add a viewport # indicator for the window list for accesiblity reasons difficulty: hard
|
|
+ TODO: Add configuration for menu icon size difficulty: easy
|
|
+ TODO: Add toggle of tearables difficulty: easy
|
|
+ TODO: Add a sane icon dialog difficulty: medium-hard
|
|
+ TODO: Make the editor able to edit non-default files
|
|
+For fun, might not implement:
|
|
+TODO: Add ability to call up menus from the menu.xml file by name, if this is really, really needed or requested
|
|
+ */
|
|
+
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include <gtk/gtk.h>
|
|
+
|
|
+#define HAVE_WNCK 1
|
|
+
|
|
+#if HAVE_WNCK
|
|
+#include "deskmenu-wnck.h"
|
|
+#endif
|
|
+
|
|
+#include "deskmenu-menu.h"
|
|
+
|
|
+
|
|
+G_DEFINE_TYPE(Deskmenu, deskmenu, G_TYPE_OBJECT) //this is calling deskmenu_class_init
|
|
+
|
|
+GQuark
|
|
+deskmenu_error_quark (void)
|
|
+{
|
|
+ static GQuark quark = 0;
|
|
+ if (!quark)
|
|
+ quark = g_quark_from_static_string ("deskmenu_error");
|
|
+ return quark;
|
|
+}
|
|
+
|
|
+static void
|
|
+quit (GtkWidget *widget,
|
|
+ gpointer data)
|
|
+{
|
|
+ gtk_main_quit ();
|
|
+}
|
|
+
|
|
+//stolen from openbox, possibly move this outside in order to make it a function to parse launchers and icon location
|
|
+gchar *parse_expand_tilde(const gchar *f)
|
|
+{
|
|
+gchar *ret;
|
|
+GRegex *regex;
|
|
+
|
|
+if (!f)
|
|
+ return NULL;
|
|
+
|
|
+regex = g_regex_new("(?:^|(?<=[ \\t]))~(?:(?=[/ \\t])|$)",
|
|
+ G_REGEX_MULTILINE | G_REGEX_RAW, 0, NULL);
|
|
+ret = g_regex_replace_literal(regex, f, -1, 0, g_get_home_dir(), 0, NULL);
|
|
+g_regex_unref(regex);
|
|
+
|
|
+return ret;
|
|
+}
|
|
+//end stolen
|
|
+
|
|
+//This is how menu command is launched
|
|
+static void
|
|
+launcher_activated (GtkWidget *widget,
|
|
+ gchar *command)
|
|
+{
|
|
+ GError *error = NULL;
|
|
+ Deskmenu *deskmenu;
|
|
+
|
|
+ deskmenu = g_object_get_data (G_OBJECT (widget), "deskmenu");
|
|
+ if (!gdk_spawn_command_line_on_screen (gdk_screen_get_default (), parse_expand_tilde(command), &error))
|
|
+ {
|
|
+ GtkWidget *message = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_ERROR,
|
|
+ GTK_BUTTONS_CLOSE, "%s", error->message);
|
|
+ gtk_dialog_run (GTK_DIALOG (message));
|
|
+ gtk_widget_destroy (message);
|
|
+ }
|
|
+
|
|
+}
|
|
+
|
|
+//place & in front of stdout for standard stdout, how a command is launched as an exec
|
|
+static void
|
|
+launcher_name_exec_update (GtkWidget *label)
|
|
+{
|
|
+ gchar *exec, *stdout;
|
|
+ exec = g_object_get_data (G_OBJECT (label), "exec");
|
|
+ if (g_spawn_command_line_sync (parse_expand_tilde(exec), &stdout, NULL, NULL, NULL))
|
|
+ gtk_label_set_text (GTK_LABEL (label), g_strstrip(stdout));
|
|
+ else
|
|
+ gtk_label_set_text (GTK_LABEL (label), "execution error");
|
|
+ g_free (stdout);
|
|
+}
|
|
+
|
|
+static void
|
|
+deskmenu_construct_item (Deskmenu *deskmenu)
|
|
+{
|
|
+ DeskmenuItem *item = deskmenu->current_item;
|
|
+ GtkWidget *menu_item;
|
|
+ gchar *name, *icon, *command, *vpicon;
|
|
+ gint w, h;
|
|
+//constructs the items in menu
|
|
+ switch (item->type)
|
|
+ {
|
|
+ case DESKMENU_ITEM_LAUNCHER:
|
|
+ if (item->name_exec)
|
|
+ {
|
|
+ GtkWidget *label;
|
|
+ GHook *hook;
|
|
+
|
|
+ name = g_strstrip (item->name->str);
|
|
+
|
|
+ menu_item = gtk_image_menu_item_new ();
|
|
+ label = gtk_label_new_with_mnemonic (NULL);
|
|
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
|
|
+
|
|
+ g_object_set_data (G_OBJECT (label), "exec", g_strdup (name));
|
|
+ gtk_container_add (GTK_CONTAINER (menu_item), label);
|
|
+ hook = g_hook_alloc (deskmenu->show_hooks);
|
|
+
|
|
+ hook->data = (gpointer) label;
|
|
+ hook->func = (GHookFunc *) launcher_name_exec_update;
|
|
+ g_hook_append (deskmenu->show_hooks, hook);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if (item->name)
|
|
+ name = g_strstrip (item->name->str);
|
|
+ else
|
|
+ name = "";
|
|
+
|
|
+ menu_item = gtk_image_menu_item_new_with_mnemonic (name);
|
|
+
|
|
+ }
|
|
+ if (item->icon)
|
|
+ {
|
|
+ icon = g_strstrip (item->icon->str);
|
|
+ if (item->icon_file) {
|
|
+ gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &w, &h);
|
|
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM
|
|
+ (menu_item), gtk_image_new_from_pixbuf (gdk_pixbuf_new_from_file_at_size (parse_expand_tilde(icon), w, h, NULL)));
|
|
+ }
|
|
+ else {
|
|
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),
|
|
+ gtk_image_new_from_icon_name (icon, GTK_ICON_SIZE_MENU));
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (item->command)
|
|
+ {
|
|
+
|
|
+ command = g_strstrip (item->command->str);
|
|
+ g_object_set_data (G_OBJECT (menu_item), "deskmenu", deskmenu);
|
|
+ g_signal_connect (G_OBJECT (menu_item), "activate",
|
|
+ G_CALLBACK (launcher_activated), g_strdup (command));
|
|
+ }
|
|
+
|
|
+ gtk_menu_shell_append (GTK_MENU_SHELL (deskmenu->current_menu),
|
|
+ menu_item);
|
|
+ break;
|
|
+#if HAVE_WNCK
|
|
+ case DESKMENU_ITEM_WINDOWLIST:
|
|
+ menu_item = gtk_image_menu_item_new_with_mnemonic ("_Windows");
|
|
+
|
|
+ DeskmenuWindowlist *windowlist = deskmenu_windowlist_new ();
|
|
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item),
|
|
+ windowlist->menu);
|
|
+ gtk_menu_shell_append (GTK_MENU_SHELL (deskmenu->current_menu),
|
|
+ menu_item);
|
|
+ if (item->icon)
|
|
+ {
|
|
+ windowlist->images = TRUE;
|
|
+ icon = g_strstrip (item->icon->str);
|
|
+ if (item->icon_file) {
|
|
+ gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &w, &h);
|
|
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM
|
|
+ (menu_item), gtk_image_new_from_pixbuf (gdk_pixbuf_new_from_file_at_size (parse_expand_tilde(icon), w, h, NULL)));
|
|
+ }
|
|
+ else {
|
|
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),
|
|
+ gtk_image_new_from_icon_name (icon, GTK_ICON_SIZE_MENU));
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case DESKMENU_ITEM_VIEWPORTLIST:
|
|
+ menu_item = gtk_image_menu_item_new_with_mnemonic ("_Viewports");
|
|
+
|
|
+ DeskmenuVplist *vplist = deskmenu_vplist_new ();
|
|
+ if (item->wrap
|
|
+ && strcmp (g_strstrip (item->wrap->str), "true") == 0)
|
|
+ vplist->wrap = TRUE;
|
|
+
|
|
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (menu_item),
|
|
+ vplist->menu);
|
|
+ gtk_menu_shell_append (GTK_MENU_SHELL (deskmenu->current_menu),
|
|
+ menu_item);
|
|
+ if (item->icon)
|
|
+ {
|
|
+ vplist->images = TRUE;
|
|
+ icon = g_strstrip (item->icon->str);
|
|
+ if (item->icon_file) {
|
|
+ gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &w, &h);
|
|
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM
|
|
+ (menu_item), gtk_image_new_from_pixbuf (gdk_pixbuf_new_from_file_at_size (parse_expand_tilde(icon), w, h, NULL)));
|
|
+ }
|
|
+ else {
|
|
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item),
|
|
+ gtk_image_new_from_icon_name (icon, GTK_ICON_SIZE_MENU));
|
|
+ }
|
|
+ }
|
|
+ if (item->vpicon)
|
|
+ {
|
|
+ vpicon = g_strstrip (parse_expand_tilde(item->vpicon->str));
|
|
+ if (item->vpicon_file) {
|
|
+ vplist->file = TRUE;
|
|
+ }
|
|
+ vplist->icon = vpicon;
|
|
+ }
|
|
+ break;
|
|
+#endif
|
|
+
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+}
|
|
+/* The handler functions. */
|
|
+
|
|
+static void
|
|
+start_element (GMarkupParseContext *context,
|
|
+ const gchar *element_name,
|
|
+ const gchar **attr_names,
|
|
+ const gchar **attr_values,
|
|
+ gpointer user_data,
|
|
+ GError **error)
|
|
+{
|
|
+ Deskmenu *deskmenu = DESKMENU (user_data);
|
|
+ DeskmenuElementType element_type;
|
|
+ const gchar **ncursor = attr_names, **vcursor = attr_values;
|
|
+ GtkWidget *item, *menu;
|
|
+
|
|
+ element_type = GPOINTER_TO_INT (g_hash_table_lookup
|
|
+ (deskmenu->element_hash, element_name));
|
|
+
|
|
+ //TODO: maybe this could be edited to see the new compiz-deskmenu element, if this is needed in order to make pipes
|
|
+ if ((deskmenu->menu && !deskmenu->current_menu)
|
|
+ || (!deskmenu->menu && element_type != DESKMENU_ELEMENT_MENU))
|
|
+ {
|
|
+ gint line_num, char_num;
|
|
+ g_markup_parse_context_get_position (context, &line_num, &char_num);
|
|
+ g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
|
|
+ "Error on line %d char %d: Element '%s' declared outside of "
|
|
+ "toplevel menu element", line_num, char_num, element_name);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ switch (element_type)
|
|
+ {
|
|
+ case DESKMENU_ELEMENT_MENU:
|
|
+
|
|
+ if (deskmenu->current_item != NULL)
|
|
+ {
|
|
+ gint line_num, char_num;
|
|
+ g_markup_parse_context_get_position (context, &line_num,
|
|
+ &char_num);
|
|
+ g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
|
|
+ "Error on line %d char %d: Element 'menu' cannot be nested "
|
|
+ "inside of an item element", line_num, char_num);
|
|
+ return;
|
|
+ }
|
|
+ if (!deskmenu->menu)
|
|
+ {
|
|
+ deskmenu->menu = gtk_menu_new ();
|
|
+ g_object_set_data (G_OBJECT (deskmenu->menu), "parent menu",
|
|
+ NULL);
|
|
+ deskmenu->current_menu = deskmenu->menu;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ gchar *name = NULL;
|
|
+ gchar *icon = NULL;
|
|
+ gboolean name_exec = FALSE;
|
|
+ gboolean icon_file = FALSE;
|
|
+ gint w, h;
|
|
+ while (*ncursor)
|
|
+ {
|
|
+ if (strcmp (*ncursor, "name") == 0)
|
|
+ name = g_strdup (*vcursor);
|
|
+ else if (strcmp (*ncursor, "icon") == 0)
|
|
+ icon = g_strdup (*vcursor);
|
|
+ else if ((strcmp (*ncursor, "mode") == 0)
|
|
+ && (strcmp (*vcursor, "exec") == 0))
|
|
+ name_exec = TRUE;
|
|
+ else if ((strcmp (*ncursor, "mode1") == 0)
|
|
+ && (strcmp (*vcursor, "file") == 0))
|
|
+ icon_file = TRUE;
|
|
+ else
|
|
+ g_set_error (error, G_MARKUP_ERROR,
|
|
+ G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
|
|
+ "Unknown attribute: %s", *ncursor);
|
|
+ ncursor++;
|
|
+ vcursor++;
|
|
+ }
|
|
+ if (name_exec)
|
|
+ {
|
|
+ GtkWidget *label;
|
|
+ GHook *hook;
|
|
+
|
|
+ item = gtk_image_menu_item_new ();
|
|
+ label = gtk_label_new_with_mnemonic (NULL);
|
|
+ gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
|
|
+
|
|
+ g_object_set_data (G_OBJECT (label), "exec", g_strdup (name));
|
|
+ gtk_container_add (GTK_CONTAINER (item), label);
|
|
+ hook = g_hook_alloc (deskmenu->show_hooks);
|
|
+
|
|
+ hook->data = (gpointer) label;
|
|
+ hook->func = (GHookFunc *) launcher_name_exec_update;
|
|
+ g_hook_append (deskmenu->show_hooks, hook);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if (name)
|
|
+ item = gtk_image_menu_item_new_with_mnemonic (name); //allow menus to have icons
|
|
+
|
|
+ else
|
|
+ item = gtk_image_menu_item_new_with_mnemonic ("");
|
|
+ gtk_menu_shell_append (GTK_MENU_SHELL (deskmenu->current_menu),
|
|
+ item);
|
|
+ }
|
|
+ if (icon)
|
|
+ {
|
|
+ if (icon_file) {
|
|
+ gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &w, &h);
|
|
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM
|
|
+ (item), gtk_image_new_from_pixbuf (gdk_pixbuf_new_from_file_at_size (parse_expand_tilde(icon), w, h, NULL)));
|
|
+ }
|
|
+ else {
|
|
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
|
|
+ gtk_image_new_from_icon_name (icon, GTK_ICON_SIZE_MENU));
|
|
+ }
|
|
+ }
|
|
+ menu = gtk_menu_new ();
|
|
+ g_object_set_data (G_OBJECT (menu), "parent menu",
|
|
+ deskmenu->current_menu);
|
|
+ deskmenu->current_menu = menu;
|
|
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (item),
|
|
+ deskmenu->current_menu);
|
|
+ g_free (name);
|
|
+ g_free (icon);
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case DESKMENU_ELEMENT_SEPARATOR:
|
|
+ break; /* build it in the end function */
|
|
+
|
|
+ case DESKMENU_ELEMENT_ITEM:
|
|
+
|
|
+ if (deskmenu->current_item != NULL)
|
|
+ {
|
|
+ gint line_num, char_num;
|
|
+ g_markup_parse_context_get_position (context, &line_num,
|
|
+ &char_num);
|
|
+ g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE,
|
|
+ "Error on line %d char %d: Element 'item' cannot be nested "
|
|
+ "inside of another item element", line_num, char_num);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ deskmenu->current_item = g_slice_new0 (DeskmenuItem);
|
|
+ while (*ncursor)
|
|
+ {
|
|
+ if (strcmp (*ncursor, "type") == 0)
|
|
+ deskmenu->current_item->type = GPOINTER_TO_INT
|
|
+ (g_hash_table_lookup (deskmenu->item_hash, *vcursor));
|
|
+ else
|
|
+ g_set_error (error, G_MARKUP_ERROR,
|
|
+ G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
|
|
+ "Unknown attribute: %s", *ncursor);
|
|
+ ncursor++;
|
|
+ vcursor++;
|
|
+ }
|
|
+ break;
|
|
+
|
|
+ case DESKMENU_ELEMENT_NAME:
|
|
+ while (*ncursor)
|
|
+ {
|
|
+ if ((strcmp (*ncursor, "mode") == 0)
|
|
+ && (strcmp (*vcursor, "exec") == 0))
|
|
+ deskmenu->current_item->name_exec = TRUE;
|
|
+ ncursor++;
|
|
+ vcursor++;
|
|
+ } /* no break here to let it fall through */
|
|
+ case DESKMENU_ELEMENT_ICON:
|
|
+ while (*ncursor)
|
|
+ {
|
|
+ if ((strcmp (*ncursor, "mode1") == 0)
|
|
+ && (strcmp (*vcursor, "file") == 0))
|
|
+ deskmenu->current_item->icon_file = TRUE;
|
|
+ ncursor++;
|
|
+ vcursor++;
|
|
+ } /* no break here to let it fall through */
|
|
+ case DESKMENU_ELEMENT_VPICON:
|
|
+ while (*ncursor)
|
|
+ {
|
|
+ if ((strcmp (*ncursor, "mode1") == 0)
|
|
+ && (strcmp (*vcursor, "file") == 0))
|
|
+ deskmenu->current_item->vpicon_file = TRUE;
|
|
+ ncursor++;
|
|
+ vcursor++;
|
|
+ } /* no break here to let it fall through */
|
|
+ case DESKMENU_ELEMENT_COMMAND:
|
|
+ case DESKMENU_ELEMENT_WRAP:
|
|
+ if (deskmenu->current_item)
|
|
+ deskmenu->current_item->current_element = element_type;
|
|
+ break;
|
|
+ default:
|
|
+ g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
|
|
+ "Unknown element: %s", element_name);
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+//dealing with empty attributes
|
|
+static void
|
|
+text (GMarkupParseContext *context,
|
|
+ const gchar *text,
|
|
+ gsize text_len,
|
|
+ gpointer user_data,
|
|
+ GError **error)
|
|
+{
|
|
+ Deskmenu *deskmenu = DESKMENU (user_data);
|
|
+ DeskmenuItem *item = deskmenu->current_item;
|
|
+
|
|
+ if (!(item && item->current_element))
|
|
+ return;
|
|
+
|
|
+ switch (item->current_element)
|
|
+ {
|
|
+ case DESKMENU_ELEMENT_NAME:
|
|
+ if (!item->name)
|
|
+ item->name = g_string_new_len (text, text_len);
|
|
+ else
|
|
+ g_string_append_len (item->name, text, text_len);
|
|
+ break;
|
|
+
|
|
+ case DESKMENU_ELEMENT_ICON:
|
|
+ if (!item->icon)
|
|
+ item->icon = g_string_new_len (text, text_len);
|
|
+ else
|
|
+ g_string_append_len (item->icon, text, text_len);
|
|
+ break;
|
|
+
|
|
+ case DESKMENU_ELEMENT_VPICON:
|
|
+ if (!item->vpicon)
|
|
+ item->vpicon = g_string_new_len (text, text_len);
|
|
+ else
|
|
+ g_string_append_len (item->vpicon, text, text_len);
|
|
+ break;
|
|
+
|
|
+ case DESKMENU_ELEMENT_COMMAND:
|
|
+ if (!item->command)
|
|
+ item->command = g_string_new_len (text, text_len);
|
|
+ else
|
|
+ g_string_append_len (item->command, text, text_len);
|
|
+ break;
|
|
+
|
|
+ case DESKMENU_ELEMENT_WRAP:
|
|
+ if (!item->wrap)
|
|
+ item->wrap = g_string_new_len (text, text_len);
|
|
+ else
|
|
+ g_string_append_len (item->wrap, text, text_len);
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+}
|
|
+
|
|
+static void
|
|
+end_element (GMarkupParseContext *context,
|
|
+ const gchar *element_name,
|
|
+ gpointer user_data,
|
|
+ GError **error)
|
|
+{
|
|
+
|
|
+ DeskmenuElementType element_type;
|
|
+ Deskmenu *deskmenu = DESKMENU (user_data);
|
|
+ GtkWidget *parent, *item;
|
|
+ element_type = GPOINTER_TO_INT (g_hash_table_lookup
|
|
+ (deskmenu->element_hash, element_name));
|
|
+
|
|
+ switch (element_type)
|
|
+ {
|
|
+ case DESKMENU_ELEMENT_MENU:
|
|
+
|
|
+ g_return_if_fail (deskmenu->current_item == NULL);
|
|
+
|
|
+ parent = g_object_get_data (G_OBJECT (deskmenu->current_menu),
|
|
+ "parent menu");
|
|
+
|
|
+ deskmenu->current_menu = parent;
|
|
+
|
|
+ break;
|
|
+
|
|
+ case DESKMENU_ELEMENT_SEPARATOR:
|
|
+ item = gtk_separator_menu_item_new ();
|
|
+ gtk_menu_shell_append (GTK_MENU_SHELL (deskmenu->current_menu),
|
|
+ item);
|
|
+ break;
|
|
+
|
|
+ case DESKMENU_ELEMENT_ITEM:
|
|
+
|
|
+ g_return_if_fail (deskmenu->current_item != NULL);
|
|
+
|
|
+ /* finally make the item ^_^ */
|
|
+ deskmenu_construct_item (deskmenu);
|
|
+
|
|
+ /* free data used to make it */
|
|
+ if (deskmenu->current_item->name)
|
|
+ g_string_free (deskmenu->current_item->name, TRUE);
|
|
+ if (deskmenu->current_item->icon)
|
|
+ g_string_free (deskmenu->current_item->icon, TRUE);
|
|
+ if (deskmenu->current_item->command)
|
|
+ g_string_free (deskmenu->current_item->command, TRUE);
|
|
+ if (deskmenu->current_item->wrap)
|
|
+ g_string_free (deskmenu->current_item->wrap, TRUE);
|
|
+ if (deskmenu->current_item->vpicon)
|
|
+ g_string_free (deskmenu->current_item->vpicon, TRUE);
|
|
+ g_slice_free (DeskmenuItem, deskmenu->current_item);
|
|
+ deskmenu->current_item = NULL;
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+/* The list of what handler does what. */
|
|
+//this parses menus
|
|
+static GMarkupParser parser = {
|
|
+ start_element,
|
|
+ end_element,
|
|
+ text,
|
|
+ NULL,
|
|
+ NULL
|
|
+};
|
|
+
|
|
+
|
|
+// Class init
|
|
+static void
|
|
+deskmenu_class_init (DeskmenuClass *deskmenu_class)
|
|
+{
|
|
+ //G_TYPE_FROM_CLASS (deskmenu_class); //I have NO idea what's going on here, but apparently, just initializing this function makes it work
|
|
+}
|
|
+
|
|
+/* Instance init, matches up words to types, note how there's no handler for pipe since it's replaced in its own chunk */
|
|
+static void
|
|
+deskmenu_init (Deskmenu *deskmenu)
|
|
+{
|
|
+
|
|
+ deskmenu->show_hooks = g_slice_new0 (GHookList);
|
|
+
|
|
+ g_hook_list_init (deskmenu->show_hooks, sizeof (GHook));
|
|
+
|
|
+
|
|
+ deskmenu->menu = NULL;
|
|
+ deskmenu->current_menu = NULL;
|
|
+ deskmenu->current_item = NULL;
|
|
+
|
|
+ deskmenu->item_hash = g_hash_table_new (g_str_hash, g_str_equal);
|
|
+
|
|
+ g_hash_table_insert (deskmenu->item_hash, "launcher",
|
|
+ GINT_TO_POINTER (DESKMENU_ITEM_LAUNCHER));
|
|
+#if HAVE_WNCK
|
|
+ g_hash_table_insert (deskmenu->item_hash, "windowlist",
|
|
+ GINT_TO_POINTER (DESKMENU_ITEM_WINDOWLIST));
|
|
+ g_hash_table_insert (deskmenu->item_hash, "viewportlist",
|
|
+ GINT_TO_POINTER (DESKMENU_ITEM_VIEWPORTLIST));
|
|
+#endif
|
|
+
|
|
+ deskmenu->element_hash = g_hash_table_new (g_str_hash, g_str_equal);
|
|
+
|
|
+ g_hash_table_insert (deskmenu->element_hash, "menu",
|
|
+ GINT_TO_POINTER (DESKMENU_ELEMENT_MENU));
|
|
+ g_hash_table_insert (deskmenu->element_hash, "separator",
|
|
+ GINT_TO_POINTER (DESKMENU_ELEMENT_SEPARATOR));
|
|
+ g_hash_table_insert (deskmenu->element_hash, "item",
|
|
+ GINT_TO_POINTER (DESKMENU_ELEMENT_ITEM));
|
|
+ g_hash_table_insert (deskmenu->element_hash, "name",
|
|
+ GINT_TO_POINTER (DESKMENU_ELEMENT_NAME));
|
|
+ g_hash_table_insert (deskmenu->element_hash, "icon",
|
|
+ GINT_TO_POINTER (DESKMENU_ELEMENT_ICON));
|
|
+ g_hash_table_insert (deskmenu->element_hash, "vpicon",
|
|
+ GINT_TO_POINTER (DESKMENU_ELEMENT_VPICON));
|
|
+ g_hash_table_insert (deskmenu->element_hash, "command",
|
|
+ GINT_TO_POINTER (DESKMENU_ELEMENT_COMMAND));
|
|
+ g_hash_table_insert (deskmenu->element_hash, "wrap",
|
|
+ GINT_TO_POINTER (DESKMENU_ELEMENT_WRAP));
|
|
+
|
|
+}
|
|
+
|
|
+static void
|
|
+deskmenu_parse_file (Deskmenu *deskmenu,
|
|
+ gchar *configpath)
|
|
+{
|
|
+ GError *error = NULL;
|
|
+ gboolean success = FALSE;
|
|
+ gchar *text, *exec, *stdout;
|
|
+ gsize length;
|
|
+ GRegex *regex, *command;
|
|
+ int i;
|
|
+
|
|
+ if (!configpath)
|
|
+ configpath = g_build_path (G_DIR_SEPARATOR_S,
|
|
+ g_get_user_config_dir (),
|
|
+ "compiz",
|
|
+ "deskmenu",
|
|
+ "menu.xml",
|
|
+ NULL);
|
|
+
|
|
+ GMarkupParseContext *context = g_markup_parse_context_new (&parser,
|
|
+ 0, deskmenu, NULL);
|
|
+
|
|
+ if (!g_file_get_contents (configpath, &text, &length, NULL))
|
|
+ {
|
|
+ const gchar* const *cursor = g_get_system_config_dirs ();
|
|
+ gchar *path = NULL;
|
|
+ while (*cursor)
|
|
+ {
|
|
+ g_free (configpath);
|
|
+ g_free (path);
|
|
+ path = g_strdup (*cursor);
|
|
+ configpath = g_build_path (G_DIR_SEPARATOR_S,
|
|
+ path,
|
|
+ "compiz",
|
|
+ "deskmenu",
|
|
+ "menu.xml",
|
|
+ NULL);
|
|
+
|
|
+ if (g_file_get_contents (configpath, &text, &length, NULL))
|
|
+ {
|
|
+ success = TRUE;
|
|
+ g_free (path);
|
|
+ break;
|
|
+ }
|
|
+ cursor++;
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ success = TRUE;
|
|
+ }
|
|
+
|
|
+ if (!success)
|
|
+ {
|
|
+ g_printerr ("Couldn't find a menu file\n");
|
|
+ exit (1);
|
|
+ }
|
|
+
|
|
+ i = 0;
|
|
+ regex = g_regex_new("(<pipe command=\".*\"/>)", G_REGEX_MULTILINE | G_REGEX_RAW, 0, NULL);
|
|
+ command = g_regex_new("<pipe command=\"|\"/>", G_REGEX_MULTILINE | G_REGEX_RAW, 0, NULL);
|
|
+ gchar **menu_chunk = g_regex_split (regex, text, 0); //this splits the menu into parsable chunks, needed for pipe item capabilities
|
|
+
|
|
+ g_free(text); //we no longer need the loaded file
|
|
+
|
|
+ //this loop will replace the pipeitem chunk with its output, other chunks are let through as is
|
|
+ while (menu_chunk[i])
|
|
+ {
|
|
+ if (g_regex_match (regex,menu_chunk[i],0,0))
|
|
+ {
|
|
+ exec = parse_expand_tilde(g_strstrip(g_regex_replace_literal(command, menu_chunk[i], -1, 0, "", 0, NULL)));
|
|
+ g_spawn_command_line_sync (exec, &stdout, NULL, NULL, NULL);
|
|
+ menu_chunk[i] = stdout;
|
|
+ }
|
|
+ i++;
|
|
+ }
|
|
+ g_regex_unref(regex); //free the pipeitem chunk checker
|
|
+ g_regex_unref(command); //free the pipe command extractor
|
|
+
|
|
+ i = 0;
|
|
+ while (menu_chunk[i])
|
|
+ {
|
|
+ g_markup_parse_context_parse (context, menu_chunk[i], strlen(menu_chunk[i]), &error);
|
|
+ //fix error reporting here, otherwise, it works fine
|
|
+ i++;
|
|
+ }
|
|
+
|
|
+ g_strfreev(menu_chunk); //free the menu chunks and their container
|
|
+ g_free (configpath); //free the file path
|
|
+ g_markup_parse_context_free (context); //free the parser
|
|
+
|
|
+ gtk_widget_show_all (deskmenu->menu);
|
|
+}
|
|
+
|
|
+/* The show method */
|
|
+gboolean
|
|
+deskmenu_show (Deskmenu *deskmenu,
|
|
+ GError **error)
|
|
+{
|
|
+ g_hook_list_invoke (deskmenu->show_hooks, FALSE);
|
|
+
|
|
+//sloppy fix until dbus is removed
|
|
+ g_signal_connect_swapped (GTK_MENU (deskmenu->menu), "deactivate",
|
|
+ G_CALLBACK (quit), NULL);
|
|
+
|
|
+ gtk_menu_popup (GTK_MENU (deskmenu->menu),
|
|
+ NULL, NULL, NULL, NULL,
|
|
+ 0, 0);
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+int
|
|
+main (int argc,
|
|
+ char **argv)
|
|
+{
|
|
+ GError *error = NULL;
|
|
+ GObject *deskmenu;
|
|
+
|
|
+ g_type_init ();
|
|
+
|
|
+ gchar *filename = NULL;
|
|
+ GOptionContext *context;
|
|
+ GOptionEntry entries[] =
|
|
+ {
|
|
+ { "menu", 'm', 0, G_OPTION_ARG_FILENAME, &filename,
|
|
+ "Use FILE instead of the default menu file", "FILE" },
|
|
+ { NULL, 0, 0, 0, NULL, NULL, NULL }
|
|
+ };
|
|
+
|
|
+ context = g_option_context_new (NULL);
|
|
+ g_option_context_add_main_entries (context, entries, NULL);
|
|
+ g_option_context_add_group (context, gtk_get_option_group (TRUE));
|
|
+ if (!g_option_context_parse (context, &argc, &argv, &error))
|
|
+ {
|
|
+ g_printerr ("option parsing failed: %s", error->message);
|
|
+ g_error_free (error);
|
|
+ exit (1);
|
|
+ }
|
|
+ g_option_context_free (context);
|
|
+
|
|
+#if HAVE_WNCK
|
|
+ wnck_set_client_type (WNCK_CLIENT_TYPE_PAGER);
|
|
+#endif
|
|
+
|
|
+ gtk_init (&argc, &argv);
|
|
+
|
|
+ deskmenu = g_object_new (DESKMENU_TYPE, NULL);
|
|
+
|
|
+ deskmenu_parse_file (DESKMENU (deskmenu), filename);
|
|
+
|
|
+ deskmenu_show (DESKMENU (deskmenu), &error);
|
|
+
|
|
+ gtk_main ();
|
|
+
|
|
+ return 0;
|
|
+}
|
|
diff -aur compiz-deskmenu/deskmenu-menu.h compiz-deskmenu3/deskmenu-menu.h
|
|
--- compiz-deskmenu/deskmenu-menu.h 2008-03-14 16:25:23.000000000 -0700
|
|
+++ compiz-deskmenu3/deskmenu-menu.h 2010-11-16 15:39:49.000000000 -0800
|
|
@@ -15,8 +15,6 @@
|
|
* Copyright 2008 Christopher Williams <christopherw@verizon.net>
|
|
*/
|
|
|
|
-#include "deskmenu-common.h"
|
|
-
|
|
typedef struct Deskmenu Deskmenu;
|
|
typedef struct DeskmenuClass DeskmenuClass;
|
|
typedef struct DeskmenuItem DeskmenuItem;
|
|
@@ -28,8 +26,7 @@
|
|
DESKMENU_ITEM_NONE = 0,
|
|
DESKMENU_ITEM_LAUNCHER,
|
|
DESKMENU_ITEM_WINDOWLIST,
|
|
- DESKMENU_ITEM_VIEWPORTLIST,
|
|
- DESKMENU_ITEM_RELOAD
|
|
+ DESKMENU_ITEM_VIEWPORTLIST
|
|
} DeskmenuItemType;
|
|
|
|
typedef enum
|
|
@@ -41,7 +38,8 @@
|
|
DESKMENU_ELEMENT_NAME,
|
|
DESKMENU_ELEMENT_ICON,
|
|
DESKMENU_ELEMENT_COMMAND,
|
|
- DESKMENU_ELEMENT_WRAP
|
|
+ DESKMENU_ELEMENT_WRAP,
|
|
+ DESKMENU_ELEMENT_VPICON
|
|
} DeskmenuElementType;
|
|
|
|
|
|
@@ -51,12 +49,14 @@
|
|
DeskmenuElementType current_element;
|
|
GString *name;
|
|
gboolean name_exec;
|
|
+ gboolean icon_file;
|
|
+ gboolean vpicon_file;
|
|
GString *icon;
|
|
+ GString *vpicon;
|
|
GString *command;
|
|
GString *wrap;
|
|
};
|
|
|
|
-
|
|
struct Deskmenu
|
|
{
|
|
GObject parent;
|
|
@@ -69,7 +69,6 @@
|
|
GHashTable *item_hash;
|
|
GHashTable *element_hash;
|
|
GHookList *show_hooks;
|
|
- gchar **envp;
|
|
};
|
|
|
|
struct DeskmenuClass
|
|
@@ -79,8 +78,8 @@
|
|
|
|
|
|
#define DESKMENU_TYPE (deskmenu_get_type ())
|
|
-#define DESKMENU(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), DESKMENU_TYPE, Deskmenu))
|
|
-#define DESKMENU_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DESKMENU_TYPE, DeskmenuClass))
|
|
+#define DESKMENU(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), DESKMENU_TYPE, Deskmenu)) //looks to see if it isn't a deskmenu already, if it isn't, make it one
|
|
+#define DESKMENU_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DESKMENU_TYPE, DeskmenuClass)) //looks to see if class cast, if it isn't, cast it
|
|
#define IS_DESKMENU(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), DESKMENU_TYPE))
|
|
#define IS_DESKMENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DESKMENU_TYPE))
|
|
#define DESKMENU_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DESKMENU_TYPE, DeskMenu))
|
|
@@ -92,9 +91,3 @@
|
|
|
|
GQuark deskmenu_error_quark (void);
|
|
#define DESKMENU_ERROR deskmenu_error_quark ()
|
|
-
|
|
-
|
|
-gboolean deskmenu_show (Deskmenu *deskmenu, gchar **env, GError **error);
|
|
-gboolean deskmenu_reload (Deskmenu *deskmenu, GError **error);
|
|
-
|
|
-
|
|
diff -aur compiz-deskmenu/deskmenu-wnck.c compiz-deskmenu3/deskmenu-wnck.c
|
|
--- compiz-deskmenu/deskmenu-wnck.c 2008-03-14 16:25:23.000000000 -0700
|
|
+++ compiz-deskmenu3/deskmenu-wnck.c 2010-11-15 18:46:24.000000000 -0800
|
|
@@ -113,18 +113,28 @@
|
|
mnemonic = "_";
|
|
else
|
|
mnemonic = "";
|
|
-
|
|
+ //wnck_window_get_workspace (dmwin->window)
|
|
+ //TODO: get this to calculate right
|
|
+ /*
|
|
+ column = wnck_workspace_get_viewport_x (wnck_window_get_workspace (dmwin->window));
|
|
+ width = wnck_workspace_get_width (wnck_screen_get_workspace (wnck_screen_get_default (), 0))/wnck_screen_get_width (wnck_screen_get_default ());
|
|
+ row = wnck_workspace_get_viewport_y (wnck_window_get_workspace (dmwin->window));
|
|
+ vpidNumber = column + ((row) * width);
|
|
+ vpid = g_strdup_printf ("%d %d %d %d :",vpidNumber,width,column,row);
|
|
+ g_print(vpid);
|
|
+ decorated_name = g_strconcat ("[",vpid, "] ", ante, mnemonic, name->str, post, NULL);
|
|
+ */
|
|
decorated_name = g_strconcat (ante, mnemonic, name->str, post, NULL);
|
|
|
|
unescaped = g_strconcat (ante, wnck_window_get_name (dmwin->window),
|
|
post, NULL);
|
|
-
|
|
gtk_label_set_text_with_mnemonic (GTK_LABEL (dmwin->label), decorated_name);
|
|
|
|
gtk_widget_set_size_request (dmwin->label,
|
|
wnck_selector_get_width (dmwin->windowlist->menu, unescaped), -1);
|
|
|
|
g_string_free (name, TRUE);
|
|
+ //g_free (vpid);
|
|
g_free (decorated_name);
|
|
g_free (unescaped);
|
|
}
|
|
@@ -171,19 +181,18 @@
|
|
{
|
|
GdkPixbuf *pixbuf;
|
|
gboolean free_pixbuf;
|
|
-
|
|
- pixbuf = wnck_window_get_mini_icon (window);
|
|
- free_pixbuf = FALSE;
|
|
- if (wnck_window_is_minimized (window))
|
|
- {
|
|
- pixbuf = wnck_selector_dimm_icon (pixbuf);
|
|
- free_pixbuf = TRUE;
|
|
- }
|
|
-
|
|
- gtk_image_set_from_pixbuf (GTK_IMAGE (dmwin->image), pixbuf);
|
|
-
|
|
- if (free_pixbuf)
|
|
- g_object_unref (pixbuf);
|
|
+ pixbuf = wnck_window_get_mini_icon (window);
|
|
+ free_pixbuf = FALSE;
|
|
+ if (wnck_window_is_minimized (window))
|
|
+ {
|
|
+ pixbuf = wnck_selector_dimm_icon (pixbuf);
|
|
+ free_pixbuf = TRUE;
|
|
+ }
|
|
+
|
|
+ gtk_image_set_from_pixbuf (GTK_IMAGE (dmwin->image), pixbuf);
|
|
+
|
|
+ if (free_pixbuf)
|
|
+ g_object_unref (pixbuf);
|
|
}
|
|
|
|
static void
|
|
@@ -257,10 +266,11 @@
|
|
gtk_label_set_ellipsize (GTK_LABEL (dmwin->label), PANGO_ELLIPSIZE_END);
|
|
|
|
dmwin->image = gtk_image_new ();
|
|
-
|
|
+ if(windowlist->images) {
|
|
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (dmwin->item),
|
|
dmwin->image);
|
|
-
|
|
+ }
|
|
+
|
|
g_signal_connect (G_OBJECT (dmwin->item), "activate",
|
|
G_CALLBACK (activate_window), window);
|
|
|
|
@@ -466,8 +476,8 @@
|
|
{
|
|
GtkWidget *item;
|
|
item = gtk_image_menu_item_new_with_mnemonic (name);
|
|
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
|
|
- gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_MENU));
|
|
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
|
|
+ gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_MENU));
|
|
g_object_set_data (G_OBJECT (item), "direction",
|
|
GINT_TO_POINTER (direction));
|
|
g_signal_connect (G_OBJECT (item), "activate",
|
|
@@ -520,6 +530,17 @@
|
|
gtk_widget_hide (vplist->go_up);
|
|
gtk_widget_hide (vplist->go_down);
|
|
|
|
+ if(!vplist->images) //this rips off those arrows if you don't want images AT ALL
|
|
+ {
|
|
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (vplist->go_left),
|
|
+ gtk_image_new_from_stock ("", GTK_ICON_SIZE_MENU));
|
|
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (vplist->go_right),
|
|
+ gtk_image_new_from_stock ("", GTK_ICON_SIZE_MENU));
|
|
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (vplist->go_up),
|
|
+ gtk_image_new_from_stock ("", GTK_ICON_SIZE_MENU));
|
|
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (vplist->go_up),
|
|
+ gtk_image_new_from_stock ("", GTK_ICON_SIZE_MENU));
|
|
+ }
|
|
gtk_widget_set_no_show_all (vplist->go_left,
|
|
!deskmenu_vplist_can_move (vplist, WNCK_MOTION_LEFT));
|
|
gtk_widget_set_no_show_all (vplist->go_right,
|
|
@@ -531,15 +552,34 @@
|
|
|
|
GtkWidget *item;
|
|
guint i;
|
|
+ gint w, h;
|
|
+ gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &w, &h);
|
|
|
|
if (new_count > vplist->old_count)
|
|
{
|
|
gchar *text;
|
|
-
|
|
+//TODO: edit this section to add thumnbnails for ports, possibly just set the thumbnails to be viewport wallpapers?
|
|
for (i = vplist->old_count; i < new_count; i++)
|
|
{
|
|
text = g_strdup_printf ("Viewport _%i", i + 1);
|
|
- item = gtk_menu_item_new_with_mnemonic (text);
|
|
+ item = gtk_image_menu_item_new_with_mnemonic (text);
|
|
+ if (vplist->images)
|
|
+ { //this'll set viewport thumbnail later if I can figure out how
|
|
+ if (vplist->icon){
|
|
+ if (vplist->file) {
|
|
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM
|
|
+ (item), gtk_image_new_from_pixbuf (gdk_pixbuf_new_from_file_at_size (vplist->icon, w, h, NULL)));
|
|
+ }
|
|
+ else {
|
|
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
|
|
+ gtk_image_new_from_icon_name (vplist->icon, GTK_ICON_SIZE_MENU));
|
|
+ }
|
|
+ }
|
|
+ else {
|
|
+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
|
|
+ gtk_image_new_from_icon_name ("user-desktop", GTK_ICON_SIZE_MENU));
|
|
+ }
|
|
+ }
|
|
g_object_set_data (G_OBJECT (item), "viewport",
|
|
GUINT_TO_POINTER (i + 1));
|
|
g_signal_connect (G_OBJECT (item), "activate",
|
|
@@ -613,4 +653,3 @@
|
|
|
|
return vplist;
|
|
}
|
|
-
|
|
diff -aur compiz-deskmenu/deskmenu-wnck.h compiz-deskmenu3/deskmenu-wnck.h
|
|
--- compiz-deskmenu/deskmenu-wnck.h 2008-03-14 16:25:23.000000000 -0700
|
|
+++ compiz-deskmenu3/deskmenu-wnck.h 2010-11-15 17:34:36.000000000 -0800
|
|
@@ -8,6 +8,7 @@
|
|
GtkWidget *menu;
|
|
GtkWidget *empty_item;
|
|
GList *windows;
|
|
+ gboolean images; //toggles use of icons
|
|
} DeskmenuWindowlist;
|
|
|
|
typedef struct DeskmenuWindow
|
|
@@ -30,6 +31,8 @@
|
|
GtkWidget *go_down;
|
|
GPtrArray *goto_items;
|
|
gboolean wrap;
|
|
+ gboolean images; //toggles use of icons
|
|
+ gboolean file; // whether the icon of choice is from theme or not
|
|
/* store some calculations */
|
|
guint hsize; /* 1-indexed horizontal viewport count */
|
|
guint vsize;
|
|
@@ -43,6 +46,7 @@
|
|
guint workspace_height;
|
|
guint old_count; /* store old hsize * vsize */
|
|
guint old_vpid; /* store old viewport number */
|
|
+ gchar *icon; /* stores viewport icon of choice */
|
|
} DeskmenuVplist;
|
|
|
|
DeskmenuWindowlist* deskmenu_windowlist_new (void);
|