#!/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)