move drlaunch in drlaunch
[drlaunch] / src / xdg / MenuEditor.py
diff --git a/src/xdg/MenuEditor.py b/src/xdg/MenuEditor.py
deleted file mode 100644 (file)
index cc5ce54..0000000
+++ /dev/null
@@ -1,511 +0,0 @@
-""" 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
-import os
-import re
-
-# XML-Cleanups: Move / Exclude
-# FIXME: proper reverte/delete
-# FIXME: pass AppDirs/DirectoryDirs around in the edit/move functions
-# FIXME: catch Exceptions
-# FIXME: copy functions
-# FIXME: More Layout stuff
-# FIXME: unod/redo function / remove menu...
-# FIXME: Advanced MenuEditing Stuff: LegacyDir/MergeFile
-#        Complex Rules/Deleted/OnlyAllocated/AppDirs/DirectoryDirs
-
-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)
-
-        # fix for creating two menus with the same name on the fly
-        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.__remove_whilespace_nodes(self.doc)
-
-    def save(self):
-        self.__saveEntries(self.menu)
-        self.__saveMenu()
-
-    def createMenuEntry(self, parent, name, command=None, genericname=None, comment=None, icon=None, terminal=None, after=None, before=None):
-        menuentry = MenuEntry(self.__getFileName(name, ".desktop"))
-        menuentry = self.editMenuEntry(menuentry, name, genericname, comment, command, icon, terminal)
-
-        self.__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.__addEntry(parent, menu, after, before)
-
-        sort(self.menu)
-
-        return menu
-
-    def createSeparator(self, parent, after=None, before=None):
-        separator = Separator(parent)
-
-        self.__addEntry(parent, separator, after, before)
-
-        sort(self.menu)
-
-        return separator
-
-    def moveMenuEntry(self, menuentry, oldparent, newparent, after=None, before=None):
-        self.__deleteEntry(oldparent, menuentry, after, before)
-        self.__addEntry(newparent, menuentry, after, before)
-
-        sort(self.menu)
-
-        return menuentry
-
-    def moveMenu(self, menu, oldparent, newparent, after=None, before=None):
-        self.__deleteEntry(oldparent, menu, after, before)
-        self.__addEntry(newparent, menu, after, before)
-
-        root_menu = self.__getXmlMenu(self.menu.Name)
-        if oldparent.getPath(True) != newparent.getPath(True):
-            self.__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.__deleteEntry(parent, separator, after, before)
-        self.__addEntry(parent, separator, after, before)
-
-        sort(self.menu)
-
-        return separator
-
-    def copyMenuEntry(self, menuentry, oldparent, newparent, after=None, before=None):
-        self.__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):
-        # Hack for legacy dirs
-        if isinstance(menu.Directory, MenuEntry) and menu.Directory.Filename == ".directory":
-            xml_menu = self.__getXmlMenu(menu.getPath(True, True))
-            self.__addXmlTextElement(xml_menu, 'Directory', menu.Name + ".directory")
-            menu.Directory.setAttributes(menu.Name + ".directory")
-        # Hack for New Entries
-        elif not isinstance(menu.Directory, MenuEntry):
-            if not name:
-                name = menu.Name
-            filename = self.__getFileName(name, ".directory").replace("/", "")
-            if not menu.Name:
-                menu.Name = filename.replace(".directory", "")
-            xml_menu = self.__getXmlMenu(menu.getPath(True, True))
-            self.__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.__getXmlMenu(menu.getPath(True,True), False)
-        for node in self.__getXmlNodesByName(["Deleted", "NotDeleted"], xml_menu):
-            node.parentNode.removeChild(node)
-
-    def deleteMenuEntry(self, menuentry):
-        if self.getAction(menuentry) == "delete":
-            self.__deleteFile(menuentry.DesktopEntry.filename)
-            for parent in menuentry.Parents:
-                self.__deleteEntry(parent, menuentry)
-            sort(self.menu)
-        return menuentry
-
-    def revertMenuEntry(self, menuentry):
-        if self.getAction(menuentry) == "revert":
-            self.__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.__deleteFile(menu.Directory.DesktopEntry.filename)
-            self.__deleteEntry(menu.Parent, menu)
-            xml_menu = self.__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.__deleteFile(menu.Directory.DesktopEntry.filename)
-            menu.Directory = menu.Directory.Original
-            sort(self.menu)
-        return menu
-
-    def deleteSeparator(self, separator):
-        self.__deleteEntry(separator.Parent, separator, after=True)
-
-        sort(self.menu)
-
-        return separator
-
-    """ Private Stuff """
-    def getAction(self, entry):
-        if isinstance(entry, Menu):
-            if not isinstance(entry.Directory, MenuEntry):
-                return "none"
-            elif entry.Directory.getType() == "Both":
-                return "revert"
-            elif entry.Directory.getType() == "User" \
-            and (len(entry.Submenus) + len(entry.MenuEntries)) == 0:
-                return "delete"
-
-        elif isinstance(entry, MenuEntry):
-            if entry.getType() == "Both":
-                return "revert"
-            elif entry.getType() == "User":
-                return "delete"
-            else:
-                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()
-            elif isinstance(entry, Menu):
-                self.__saveEntries(entry)
-
-    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 1:
-            if postfix == 0:
-                filename = name + extension
-            else:
-                filename = name + "-" + str(postfix) + extension
-            if extension == ".desktop":
-                dir = "applications"
-            elif extension == ".directory":
-                dir = "desktop-directories"
-            if not filename in self.filenames and not \
-                os.path.isfile(os.path.join(xdg_data_dirs[0], dir, filename)):
-                self.filenames.append(filename)
-                break
-            else:
-                postfix += 1
-
-        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.__getXmlNodesByName("Menu", element):
-            for child in self.__getXmlNodesByName("Name", node):
-                if child.childNodes[0].nodeValue == name:
-                    if path:
-                        found = self.__getXmlMenu(path, create, node)
-                    else:
-                        found = node
-                    break
-            if found:
-                break
-        if not found and create == True:
-            node = self.__addXmlMenuElement(element, name)
-            if path:
-                found = self.__getXmlMenu(path, create, node)
-            else:
-                found = node
-
-        return found
-
-    def __addXmlMenuElement(self, element, name):
-        node = self.doc.createElement('Menu')
-        self.__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"):
-        # remove old filenames
-        for node in self.__getXmlNodesByName(["Include", "Exclude"], element):
-            if node.childNodes[0].nodeName == "Filename" and node.childNodes[0].childNodes[0].nodeValue == filename:
-                element.removeChild(node)
-
-        # add new filename
-        node = self.doc.createElement(type)
-        node.appendChild(self.__addXmlTextElement(node, 'Filename', filename))
-        return element.appendChild(node)
-
-    def __addXmlMove(self, element, old, new):
-        node = self.doc.createElement("Move")
-        node.appendChild(self.__addXmlTextElement(node, 'Old', old))
-        node.appendChild(self.__addXmlTextElement(node, 'New', new))
-        return element.appendChild(node)
-
-    def __addXmlLayout(self, element, layout):
-        # remove old layout
-        for node in self.__getXmlNodesByName("Layout", element):
-            element.removeChild(node)
-
-        # add new layout
-        node = self.doc.createElement("Layout")
-        for order in layout.order:
-            if order[0] == "Separator":
-                child = self.doc.createElement("Separator")
-                node.appendChild(child)
-            elif order[0] == "Filename":
-                child = self.__addXmlTextElement(node, "Filename", order[1])
-            elif order[0] == "Menuname":
-                child = self.__addXmlTextElement(node, "Menuname", order[1])
-            elif order[0] == "Merge":
-                child = self.doc.createElement("Merge")
-                child.setAttribute("type", order[1])
-                node.appendChild(child)
-        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
-
-    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)
-            elif isinstance(entry, MenuEntry):
-                layout.parseFilename(entry.DesktopFileID)
-            elif isinstance(entry, Separator):
-                layout.parseSeparator()
-        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.__getXmlMenu(parent.getPath(True, True))
-
-        if isinstance(entry, MenuEntry):
-            parent.MenuEntries.append(entry)
-            entry.Parents.append(parent)
-            self.__addXmlFilename(xml_parent, entry.DesktopFileID, "Include")
-        elif isinstance(entry, Menu):
-            parent.addSubmenu(entry)
-
-        if after or before:
-            self.__addLayout(parent)
-            self.__addXmlLayout(xml_parent, parent.Layout)
-
-    def __deleteEntry(self, parent, entry, after=None, before=None):
-        parent.Entries.remove(entry)
-
-        xml_parent = self.__getXmlMenu(parent.getPath(True, True))
-
-        if isinstance(entry, MenuEntry):
-            entry.Parents.remove(parent)
-            parent.MenuEntries.remove(entry)
-            self.__addXmlFilename(xml_parent, entry.DesktopFileID, "Exclude")
-        elif isinstance(entry, Menu):
-            parent.Submenus.remove(entry)
-
-        if after or before:
-            self.__addLayout(parent)
-            self.__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)
-            elif child.hasChildNodes():
-                self.__remove_whilespace_nodes(child)
-        for node in remove_list:
-            node.parentNode.removeChild(node)