#!/usr/bin/python
#
# Openbox Menu Editor 1.0 beta
#
# Copyright 2005 Manuel Colmenero
#
# This program 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.
#
# This program 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, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# ObMenu can be used as a module in python scripts, for example, to
# Generate dynamic menus (pipemenus)
import xml.dom.minidom
class ObMenu:
# Internal functions =============================================
# (These mess with the xml tree)
# given its ID, and its parent (or None for top-level)
# returns the dom tree of the menu. Recursively.
def _get_dom_menu(self, menu, parent=None):
if not menu: return None
if not parent: parent = self.dom.documentElement
for item in parent.childNodes:
if item.nodeName == "menu" and item.hasChildNodes():
if item.attributes["id"].nodeValue == menu: return item
else:
b = self._get_dom_menu(menu, item)
if b: return b
return None
# given its ID, and its parent (or None for top-level)
# returns the dom tree of the menu. Recursively.
def _get_dom_ref(self, menu, parent):
if not parent: parent = self.dom.documentElement
for item in parent.childNodes:
if item.nodeName == "menu":
if not item.hasChildNodes():
if item.attributes["id"].nodeValue == menu: return item
else:
b = self._get_dom_menu(menu, item)
if b: return b
return None
# Get an item of 'menu', given its number (order)
def _get_dom_item(self,menu,num):
if not menu:
item = self.dom.documentElement
else:
item = self._get_dom_menu(menu)
if not item: return None
i = 0
for it in item.childNodes:
if it.nodeType == 1:
if i == num: return it
i += 1
# Insert a node in the xml tree
def _put_dom_item(self, menu, nodo, pos=None):
parent = self._get_dom_menu(menu)
if not parent: parent = self.dom.documentElement
if pos == None or pos > self._get_menu_len(menu):
parent.appendChild(nodo)
elif pos >= 0:
ant = self._get_dom_item(menu, pos)
parent.insertBefore(nodo, ant)
# Get the number of items of a menu
def _get_menu_len(self,menu):
if menu:
item = self._get_dom_menu(menu)
else:
item = self.dom.documentElement
i = 0
for it in item.childNodes:
if it.nodeType == 1:
i += 1
return i
# Get "real" item number (counting with comments, text, etc in the xml)
def _get_real_num(self,menu,num):
if menu:
item = self._get_dom_menu(menu)
else:
item = self.dom.documentElement
i = 0
n = 0
for it in item.childNodes:
if it.nodeType == 1:
if i == num: return n
i += 1
n += 1
# get the properties of an item from the xml, and returns them as a
# dictionary.
def _get_item_props(self,node):
etiqueta = node.attributes["label"].nodeValue
accion = ""
param = ""
for it in node.childNodes:
if it.nodeType == 1:
accion = it.attributes["name"].nodeValue
if accion.lower() == "execute":
for itm in it.childNodes:
if itm.nodeType == 1 and itm.nodeName.lower() == "execute":
for item in itm.childNodes:
if item.nodeType == 3:
param = item.nodeValue.strip()
return { "type": "item", "label": etiqueta, "action": accion, "execute": param }
# get the properties of a menu from the xml, and returns them as a
# dictionary.
def _get_menu_props(self, node):
lb = ""
ex = ""
act = ""
mid = node.attributes["id"].nodeValue
if node.hasAttribute("label"):
lb = node.attributes["label"].nodeValue
else:
mnu = self._get_dom_menu(mid)
if mnu: lb = mnu.attributes["label"].nodeValue
else: lb = mid
if not node.hasChildNodes():
if node.hasAttribute("execute"):
ex = node.attributes["execute"].nodeValue
act = "Pipemenu"
else:
act = "Link"
if node.hasAttribute("execute"): ex = node.attributes["execute"].nodeValue
return { "type": "menu", "label": lb, "action": act, "execute": ex, "id": mid }
# Public functions ===================================================
# Most of them are self-explanatory
def loadMenu(self, filename):
fil = open(filename)
self.dom = xml.dom.minidom.parseString(fil.read())
fil.close()
def newMenu(self):
self.dom = xml.dom.minidom.parseString(
"")
#self.dom._set_async(False)
def newPipe(self):
self.dom = xml.dom.minidom.parseString(
"")
def saveMenu(self, filename):
output = open(filename, "w")
for line in self.dom.toprettyxml("\t","\n","utf-8").splitlines():
if line.strip() != "":
output.write("%s\n" %(line))
output.close()
def printXml(self):
for line in self.dom.toprettyxml("\t","\n","utf-8").splitlines():
if line.strip() != "":
print line
def getXml(self):
res = ""
for line in self.dom.toprettyxml("\t","\n","utf-8").splitlines():
if line.strip() != "":
res = res + "%s\n" % (line)
return res
def removeItem(self,menu, num):
if menu:
dom_mnu = self._get_dom_menu(menu)
else:
dom_mnu = self.dom.documentElement
item = self._get_dom_item(menu,num)
dom_mnu.removeChild(item)
item.unlink()
def removeMenu(self,menu):
dom_mnu = self._get_dom_menu(menu)
if not dom_mnu.parentNode:
self.dom.documentElement.removeChild(dom_mnu)
else:
dom_mnu.parentNode.removeChild(dom_mnu)
dom_mnu.unlink()
def createSep(self, menu, pos=None):
nodo = self.dom.createElement("separator")
self._put_dom_item(menu, nodo, pos)
def createItem(self, menu, label, action, execute, pos=None):
nodo = self.dom.createElement("item")
nodo.attributes["label"] = label
accion = self.dom.createElement("action")
accion.attributes["name"] = "Execute"
exe = self.dom.createElement("execute")
txt = self.dom.createTextNode("")
txt.nodeValue = execute
exe.appendChild(txt)
accion.appendChild(exe)
nodo.appendChild(accion)
self._put_dom_item(menu, nodo, pos)
def createLink(self, menu, mid, pos=None):
nodo = self.dom.createElement("menu")
nodo.attributes["id"] = mid
self._put_dom_item(menu, nodo, pos)
def createPipe(self, menu, mid, label, execute, pos=None):
nodo = self.dom.createElement("menu")
nodo.attributes["id"] = mid
nodo.attributes["label"] = label
nodo.attributes["execute"] = execute
self._put_dom_item(menu, nodo, pos)
def createMenu(self, menu, label, mid, pos=None):
nodo = self.dom.createElement("menu")
nodo.attributes["label"] = label
nodo.attributes["id"] = mid
txt = self.dom.createTextNode("")
txt.nodeValue = "\n"
nodo.appendChild(txt)
self._put_dom_item(menu, nodo, pos)
def interchange(self, menu, n1, n2):
if not menu:
dom_mnu = self.dom.documentElement
else:
dom_mnu = self._get_dom_menu(menu)
i1 = self._get_real_num(menu, n1)
i2 = self._get_real_num(menu, n2)
uno = dom_mnu.childNodes[i1]
dom_mnu.childNodes[i1] = dom_mnu.childNodes[i2]
dom_mnu.childNodes[i2] = uno
def setItemProps(self, menu, n, label, action, exe):
itm = self._get_dom_item(menu,n)
itm.attributes["label"].nodeValue = label
for it in itm.childNodes:
if it.nodeType == 1:
it.attributes["name"].nodeValue = action
if action == "Execute":
if not it.childNodes:
elm = xml.dom.minidom.Element("execute")
txt = xml.dom.minidom.Text()
txt.nodeValue = exe
elm.appendChild(txt)
it.appendChild(elm)
else:
for i in it.childNodes:
if i.nodeType == 1 and i.nodeName == "execute":
for item in i.childNodes:
if item.nodeType == 3:
item.nodeValue = exe
else:
for item in it.childNodes:
it.removeChild(item)
def setMenuLabel(self, menu, label):
mnu = self._get_dom_menu(menu)
if mnu: mnu.attributes["label"].nodeValue = label
def getMenuLabel(self,menu):
mnu = self._get_dom_menu(menu)
if mnu: return mnu.attributes["label"].nodeValue
def setRefLabel(self, parent, mid, label):
prnt = self._get_dom_menu(parent)
if prnt: mnu = self._get_dom_ref(mid, prnt)
if mnu: mnu.setAttribute("label", label)
def setRefId(self, parent, mid, new_id):
prnt = self._get_dom_menu(parent)
if prnt: mnu = self._get_dom_ref(mid, prnt)
if mnu: mnu.setAttribute("id", new_id)
def setMenuExecute(self, parent, mid, execute):
prnt = self._get_dom_menu(parent)
if prnt: mnu = self._get_dom_ref(mid, prnt)
if mnu: mnu.setAttribute("execute", execute)
# Return just an item, given its parent menu an its number
def getItem(self,menu,num):
mnu = self._get_dom_menu(menu)
if not mnu: return
n = 0
for i in mnu.childNodes:
if i.nodeType == 1:
if n == num:
if i.nodeName == "menu":
return self._get_menu_props(i)
elif i.nodeName == "separator":
return { "type": "separator" }
elif i.nodeName == "item":
return self.get_item_props(i)
n += 1
# Is menu? Returns True if it's an existing ID
def isMenu(self,menu):
dom = self._get_dom_menu(menu)
if dom:
return True
else:
return False
# Returns a whole menu, as a list of dictionaries.
# Each dictionary has the items properties.
def getMenu(self,menu):
lst = []
if menu:
mnu = self._get_dom_menu(menu)
if not mnu: return
else:
mnu = self.dom.documentElement
for i in mnu.childNodes:
if i.nodeType == 1:
if i.nodeName == "menu":
d = self._get_menu_props(i)
d["parent"] = menu
lst.append(d)
elif i.nodeName == "separator":
lst.append({"type": "separator", "parent": menu})
elif i.nodeName == "item":
d = self._get_item_props(i)
d["parent"] = menu
lst.append(d)
return lst
# replace all old_id's in file with new_id's
# parent shuld start with None
def replaceId(self, old_id, new_id, parent=None):
if not parent: parent = self.dom.documentElement
for item in parent.childNodes:
if item.nodeName == "menu":
if item.attributes["id"].nodeValue == old_id:
item.setAttribute("id", new_id)
elif item.hasChildNodes():
self.replaceId(old_id, new_id, item)
if __name__ == "__main__":
print "This is a module. Use obmenu instead."
exit(0)