home *** CD-ROM | disk | FTP | other *** search
Wrap
# Source Generated with Decompyle++ # File: in.pyc (Python 2.6) ''' CLass to edit XDG Menus ''' from xdg.Menu import * from xdg.BaseDirectory import * from xdg.Exceptions import * from xdg.DesktopEntry import * from xdg.Config import * import xml.dom.minidom as xml import os import re class MenuEditor: def __init__(self, menu = None, filename = None, root = False): self.menu = None self.filename = None self.doc = None self.parse(menu, filename, root) self.filenames = [] def parse(self, menu = None, filename = None, root = False): if root == True: setRootMode(True) if isinstance(menu, Menu): self.menu = menu elif menu: self.menu = parse(menu) else: self.menu = parse() if root == True: self.filename = self.menu.Filename elif filename: self.filename = filename else: self.filename = os.path.join(xdg_config_dirs[0], 'menus', os.path.split(self.menu.Filename)[1]) try: self.doc = xml.dom.minidom.parse(self.filename) except IOError: self.doc = xml.dom.minidom.parseString('<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" "http://standards.freedesktop.org/menu-spec/menu-1.0.dtd"><Menu><Name>Applications</Name><MergeFile type="parent">' + self.menu.Filename + '</MergeFile></Menu>') except xml.parsers.expat.ExpatError: raise ParsingError('Not a valid .menu file', self.filename) self._MenuEditor__remove_whilespace_nodes(self.doc) def save(self): self._MenuEditor__saveEntries(self.menu) self._MenuEditor__saveMenu() def createMenuEntry(self, parent, name, command = None, genericname = None, comment = None, icon = None, terminal = None, after = None, before = None): menuentry = MenuEntry(self._MenuEditor__getFileName(name, '.desktop')) menuentry = self.editMenuEntry(menuentry, name, genericname, comment, command, icon, terminal) self._MenuEditor__addEntry(parent, menuentry, after, before) sort(self.menu) return menuentry def createMenu(self, parent, name, genericname = None, comment = None, icon = None, after = None, before = None): menu = Menu() menu.Parent = parent menu.Depth = parent.Depth + 1 menu.Layout = parent.DefaultLayout menu.DefaultLayout = parent.DefaultLayout menu = self.editMenu(menu, name, genericname, comment, icon) self._MenuEditor__addEntry(parent, menu, after, before) sort(self.menu) return menu def createSeparator(self, parent, after = None, before = None): separator = Separator(parent) self._MenuEditor__addEntry(parent, separator, after, before) sort(self.menu) return separator def moveMenuEntry(self, menuentry, oldparent, newparent, after = None, before = None): self._MenuEditor__deleteEntry(oldparent, menuentry, after, before) self._MenuEditor__addEntry(newparent, menuentry, after, before) sort(self.menu) return menuentry def moveMenu(self, menu, oldparent, newparent, after = None, before = None): self._MenuEditor__deleteEntry(oldparent, menu, after, before) self._MenuEditor__addEntry(newparent, menu, after, before) root_menu = self._MenuEditor__getXmlMenu(self.menu.Name) if oldparent.getPath(True) != newparent.getPath(True): self._MenuEditor__addXmlMove(root_menu, os.path.join(oldparent.getPath(True), menu.Name), os.path.join(newparent.getPath(True), menu.Name)) sort(self.menu) return menu def moveSeparator(self, separator, parent, after = None, before = None): self._MenuEditor__deleteEntry(parent, separator, after, before) self._MenuEditor__addEntry(parent, separator, after, before) sort(self.menu) return separator def copyMenuEntry(self, menuentry, oldparent, newparent, after = None, before = None): self._MenuEditor__addEntry(newparent, menuentry, after, before) sort(self.menu) return menuentry def editMenuEntry(self, menuentry, name = None, genericname = None, comment = None, command = None, icon = None, terminal = None, nodisplay = None, hidden = None): deskentry = menuentry.DesktopEntry if name: if not deskentry.hasKey('Name'): deskentry.set('Name', name) deskentry.set('Name', name, locale = True) if comment: if not deskentry.hasKey('Comment'): deskentry.set('Comment', comment) deskentry.set('Comment', comment, locale = True) if genericname: if not deskentry.hasKey('GnericNe'): deskentry.set('GenericName', genericname) deskentry.set('GenericName', genericname, locale = True) if command: deskentry.set('Exec', command) if icon: deskentry.set('Icon', icon) if terminal == True: deskentry.set('Terminal', 'true') elif terminal == False: deskentry.set('Terminal', 'false') if nodisplay == True: deskentry.set('NoDisplay', 'true') elif nodisplay == False: deskentry.set('NoDisplay', 'false') if hidden == True: deskentry.set('Hidden', 'true') elif hidden == False: deskentry.set('Hidden', 'false') menuentry.updateAttributes() if len(menuentry.Parents) > 0: sort(self.menu) return menuentry def editMenu(self, menu, name = None, genericname = None, comment = None, icon = None, nodisplay = None, hidden = None): if isinstance(menu.Directory, MenuEntry) and menu.Directory.Filename == '.directory': xml_menu = self._MenuEditor__getXmlMenu(menu.getPath(True, True)) self._MenuEditor__addXmlTextElement(xml_menu, 'Directory', menu.Name + '.directory') menu.Directory.setAttributes(menu.Name + '.directory') elif not isinstance(menu.Directory, MenuEntry): if not name: name = menu.Name filename = self._MenuEditor__getFileName(name, '.directory').replace('/', '') if not menu.Name: menu.Name = filename.replace('.directory', '') xml_menu = self._MenuEditor__getXmlMenu(menu.getPath(True, True)) self._MenuEditor__addXmlTextElement(xml_menu, 'Directory', filename) menu.Directory = MenuEntry(filename) deskentry = menu.Directory.DesktopEntry if name: if not deskentry.hasKey('Name'): deskentry.set('Name', name) deskentry.set('Name', name, locale = True) if genericname: if not deskentry.hasKey('GenericName'): deskentry.set('GenericName', genericname) deskentry.set('GenericName', genericname, locale = True) if comment: if not deskentry.hasKey('Comment'): deskentry.set('Comment', comment) deskentry.set('Comment', comment, locale = True) if icon: deskentry.set('Icon', icon) if nodisplay == True: deskentry.set('NoDisplay', 'true') elif nodisplay == False: deskentry.set('NoDisplay', 'false') if hidden == True: deskentry.set('Hidden', 'true') elif hidden == False: deskentry.set('Hidden', 'false') menu.Directory.updateAttributes() if isinstance(menu.Parent, Menu): sort(self.menu) return menu def hideMenuEntry(self, menuentry): self.editMenuEntry(menuentry, nodisplay = True) def unhideMenuEntry(self, menuentry): self.editMenuEntry(menuentry, nodisplay = False, hidden = False) def hideMenu(self, menu): self.editMenu(menu, nodisplay = True) def unhideMenu(self, menu): self.editMenu(menu, nodisplay = False, hidden = False) xml_menu = self._MenuEditor__getXmlMenu(menu.getPath(True, True), False) for node in self._MenuEditor__getXmlNodesByName([ 'Deleted', 'NotDeleted'], xml_menu): node.parentNode.removeChild(node) def deleteMenuEntry(self, menuentry): if self.getAction(menuentry) == 'delete': self._MenuEditor__deleteFile(menuentry.DesktopEntry.filename) for parent in menuentry.Parents: self._MenuEditor__deleteEntry(parent, menuentry) sort(self.menu) return menuentry def revertMenuEntry(self, menuentry): if self.getAction(menuentry) == 'revert': self._MenuEditor__deleteFile(menuentry.DesktopEntry.filename) menuentry.Original.Parents = [] for parent in menuentry.Parents: index = parent.Entries.index(menuentry) parent.Entries[index] = menuentry.Original index = parent.MenuEntries.index(menuentry) parent.MenuEntries[index] = menuentry.Original menuentry.Original.Parents.append(parent) sort(self.menu) return menuentry def deleteMenu(self, menu): if self.getAction(menu) == 'delete': self._MenuEditor__deleteFile(menu.Directory.DesktopEntry.filename) self._MenuEditor__deleteEntry(menu.Parent, menu) xml_menu = self._MenuEditor__getXmlMenu(menu.getPath(True, True)) xml_menu.parentNode.removeChild(xml_menu) sort(self.menu) return menu def revertMenu(self, menu): if self.getAction(menu) == 'revert': self._MenuEditor__deleteFile(menu.Directory.DesktopEntry.filename) menu.Directory = menu.Directory.Original sort(self.menu) return menu def deleteSeparator(self, separator): self._MenuEditor__deleteEntry(separator.Parent, separator, after = True) sort(self.menu) return separator def getAction(self, entry): if isinstance(entry, Menu): if not isinstance(entry.Directory, MenuEntry): return 'none' if entry.Directory.getType() == 'Both': return 'revert' if entry.Directory.getType() == 'User' and len(entry.Submenus) + len(entry.MenuEntries) == 0: return 'delete' elif isinstance(entry, MenuEntry): if entry.getType() == 'Both': return 'revert' if entry.getType() == 'User': return 'delete' return 'none' return 'none' def __saveEntries(self, menu): if not menu: menu = self.menu if isinstance(menu.Directory, MenuEntry): menu.Directory.save() for entry in menu.getEntries(hidden = True): if isinstance(entry, MenuEntry): entry.save() continue if isinstance(entry, Menu): self._MenuEditor__saveEntries(entry) continue def __saveMenu(self): if not os.path.isdir(os.path.dirname(self.filename)): os.makedirs(os.path.dirname(self.filename)) fd = open(self.filename, 'w') fd.write(re.sub('\n[\\s]*([^\n<]*)\n[\\s]*</', '\\1</', self.doc.toprettyxml().replace('<?xml version="1.0" ?>\n', ''))) fd.close() def __getFileName(self, name, extension): postfix = 0 while postfix == 0: filename = name + extension filename = name + '-' + str(postfix) + extension if extension == '.desktop': dir = 'applications' elif extension == '.directory': dir = 'desktop-directories' if filename not in self.filenames and not os.path.isfile(os.path.join(xdg_data_dirs[0], dir, filename)): self.filenames.append(filename) break continue postfix += 1 continue return filename def __getXmlMenu(self, path, create = True, element = None): if not element: element = self.doc if '/' in path: (name, path) = path.split('/', 1) else: name = path path = '' found = None for node in self._MenuEditor__getXmlNodesByName('Menu', element): for child in self._MenuEditor__getXmlNodesByName('Name', node): if child.childNodes[0].nodeValue == name: if path: found = self._MenuEditor__getXmlMenu(path, create, node) else: found = node break continue if found: break continue if not found and create == True: node = self._MenuEditor__addXmlMenuElement(element, name) if path: found = self._MenuEditor__getXmlMenu(path, create, node) else: found = node return found def __addXmlMenuElement(self, element, name): node = self.doc.createElement('Menu') self._MenuEditor__addXmlTextElement(node, 'Name', name) return element.appendChild(node) def __addXmlTextElement(self, element, name, text): node = self.doc.createElement(name) text = self.doc.createTextNode(text) node.appendChild(text) return element.appendChild(node) def __addXmlFilename(self, element, filename, type = 'Include'): for node in self._MenuEditor__getXmlNodesByName([ 'Include', 'Exclude'], element): if node.childNodes[0].nodeName == 'Filename' and node.childNodes[0].childNodes[0].nodeValue == filename: element.removeChild(node) continue node = self.doc.createElement(type) node.appendChild(self._MenuEditor__addXmlTextElement(node, 'Filename', filename)) return element.appendChild(node) def __addXmlMove(self, element, old, new): node = self.doc.createElement('Move') node.appendChild(self._MenuEditor__addXmlTextElement(node, 'Old', old)) node.appendChild(self._MenuEditor__addXmlTextElement(node, 'New', new)) return element.appendChild(node) def __addXmlLayout(self, element, layout): for node in self._MenuEditor__getXmlNodesByName('Layout', element): element.removeChild(node) node = self.doc.createElement('Layout') for order in layout.order: if order[0] == 'Separator': child = self.doc.createElement('Separator') node.appendChild(child) continue if order[0] == 'Filename': child = self._MenuEditor__addXmlTextElement(node, 'Filename', order[1]) continue if order[0] == 'Menuname': child = self._MenuEditor__addXmlTextElement(node, 'Menuname', order[1]) continue if order[0] == 'Merge': child = self.doc.createElement('Merge') child.setAttribute('type', order[1]) node.appendChild(child) continue return element.appendChild(node) def __getXmlNodesByName(self, name, element): for child in element.childNodes: if child.nodeType == xml.dom.Node.ELEMENT_NODE and child.nodeName in name: yield child continue def __addLayout(self, parent): layout = Layout() layout.order = [] layout.show_empty = parent.Layout.show_empty layout.inline = parent.Layout.inline layout.inline_header = parent.Layout.inline_header layout.inline_alias = parent.Layout.inline_alias layout.inline_limit = parent.Layout.inline_limit layout.order.append([ 'Merge', 'menus']) for entry in parent.Entries: if isinstance(entry, Menu): layout.parseMenuname(entry.Name) continue if isinstance(entry, MenuEntry): layout.parseFilename(entry.DesktopFileID) continue if isinstance(entry, Separator): layout.parseSeparator() continue layout.order.append([ 'Merge', 'files']) parent.Layout = layout return layout def __addEntry(self, parent, entry, after = None, before = None): if after or before: if after: index = parent.Entries.index(after) + 1 elif before: index = parent.Entries.index(before) parent.Entries.insert(index, entry) else: parent.Entries.append(entry) xml_parent = self._MenuEditor__getXmlMenu(parent.getPath(True, True)) if isinstance(entry, MenuEntry): parent.MenuEntries.append(entry) entry.Parents.append(parent) self._MenuEditor__addXmlFilename(xml_parent, entry.DesktopFileID, 'Include') elif isinstance(entry, Menu): parent.addSubmenu(entry) if after or before: self._MenuEditor__addLayout(parent) self._MenuEditor__addXmlLayout(xml_parent, parent.Layout) def __deleteEntry(self, parent, entry, after = None, before = None): parent.Entries.remove(entry) xml_parent = self._MenuEditor__getXmlMenu(parent.getPath(True, True)) if isinstance(entry, MenuEntry): entry.Parents.remove(parent) parent.MenuEntries.remove(entry) self._MenuEditor__addXmlFilename(xml_parent, entry.DesktopFileID, 'Exclude') elif isinstance(entry, Menu): parent.Submenus.remove(entry) if after or before: self._MenuEditor__addLayout(parent) self._MenuEditor__addXmlLayout(xml_parent, parent.Layout) def __deleteFile(self, filename): try: os.remove(filename) except OSError: pass try: self.filenames.remove(filename) except ValueError: pass def __remove_whilespace_nodes(self, node): remove_list = [] for child in node.childNodes: if child.nodeType == xml.dom.minidom.Node.TEXT_NODE: child.data = child.data.strip() if not child.data.strip(): remove_list.append(child) child.data.strip() if child.hasChildNodes(): self._MenuEditor__remove_whilespace_nodes(child) continue for node in remove_list: node.parentNode.removeChild(node)