[alacarte] util: Replace our own DesktopParser with GKeyFile



commit df217421c15adedb9a9404c811af0cafca9d3ed5
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Tue May 1 16:45:24 2012 -0400

    util: Replace our own DesktopParser with GKeyFile

 Alacarte/MainWindow.py |   27 +++-------
 Alacarte/MenuEditor.py |  134 +++++++++++++++++++++++-------------------------
 Alacarte/util.py       |   70 +++++--------------------
 3 files changed, 88 insertions(+), 143 deletions(-)
---
diff --git a/Alacarte/MainWindow.py b/Alacarte/MainWindow.py
index f8d917a..ace856e 100644
--- a/Alacarte/MainWindow.py
+++ b/Alacarte/MainWindow.py
@@ -17,7 +17,7 @@
 #   License along with this library; if not, write to the Free Software
 #   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
-from gi.repository import Gtk, GObject, Gio, GdkPixbuf, Gdk, GMenu
+from gi.repository import Gtk, GObject, Gio, GdkPixbuf, Gdk, GMenu, GLib
 import cgi, os
 import gettext
 import subprocess
@@ -362,15 +362,7 @@ class MainWindow:
             file_path = os.path.join(util.getUserItemPath(), item.get_desktop_file_id())
             file_type = 'Item'
         elif isinstance(item, GMenu.TreeDirectory):
-            if item.get_desktop_file_path() == None:
-                file_path = util.getUniqueFileId('alacarte-made', '.directory')
-                parser = util.DesktopParser(file_path, 'Directory')
-                parser.set('Name', item.get_name())
-                parser.set('Comment', item.get_comment())
-                parser.set('Icon', item.get_icon())
-                parser.write(open(file_path))
-            else:
-                file_path = os.path.join(util.getUserDirectoryPath(), os.path.split(item.get_desktop_file_path())[1])
+            file_path = os.path.join(util.getUserDirectoryPath(), os.path.split(item.get_desktop_file_path())[1])
             file_type = 'Menu'
 
         if not os.path.isfile(file_path):
@@ -566,15 +558,14 @@ class MainWindow:
             content_type = file_info.get_content_type()
             if content_type == 'application/x-desktop':
                 input_stream = myfile.read()
-                (fd, tmppath) = tempfile.mkstemp(prefix='alacarte-dnd', suffix='.desktop')
-                os.close(fd)
-                f = os.open(tmppath, 'w')
-                f.write(input_stream.read())
-                f.close()
-                parser = util.DesktopParser(tmppath)
-                self.editor.createItem(parent, parser.get('Icon'), parser.get('Name', self.editor.locale), parser.get('Comment', self.editor.locale), parser.get('Exec'), parser.get('Terminal'), before, after)
+                keyfile = GLib.KeyFile()
+                keyfile.load_from_data(input_stream.read())
+                self.editor.createItem(parent, before, after, KeyFile=keyfile)
             elif content_type in ('application/x-shellscript', 'application/x-executable'):
-                self.editor.createItem(parent, None, os.path.split(file_path)[1].strip(), None, file_path.replace('file://', '').strip(), False, before, after)
+                self.editor.createItem(parent, before, after,
+                                       Name=os.path.split(file_path)[1].strip(),
+                                       Exec=file_path.replace('file://', '').strip(),
+                                       Terminal=False)
         self.drag_data = None
 
     def on_item_tree_key_press_event(self, item_tree, event):
diff --git a/Alacarte/MenuEditor.py b/Alacarte/MenuEditor.py
index 21255ba..7dacf7c 100644
--- a/Alacarte/MenuEditor.py
+++ b/Alacarte/MenuEditor.py
@@ -17,7 +17,7 @@
 #   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
 import os, sys, re, xml.dom.minidom, locale
-from gi.repository import GMenu
+from gi.repository import GMenu, GLib
 from Alacarte import util
 
 class Menu:
@@ -107,10 +107,10 @@ class MenuEditor:
         item_type = item_iter.next()
         while item_type != GMenu.TreeItemType.INVALID:
             if item_type == GMenu.TreeItemType.DIRECTORY:
-                item = item_iter.get_directory();
+                item = item_iter.get_directory()
                 self.revertTree(item)
             elif item_type == GMenu.TreeItemType.ENTRY:
-                item = item_iter.get_entry();
+                item = item_iter.get_entry()
                 self.revertItem(item)
             item_type = item_iter.next()
         self.revertMenu(menu)
@@ -239,7 +239,7 @@ class MenuEditor:
             menu_xml = self.__getXmlMenu(self.__getPath(item.get_parent()), dom, dom)
             if visible:
                 self.__addXmlFilename(menu_xml, dom, item.get_desktop_file_id(), 'Include')
-                self.__writeItem(item, no_display=False)
+                self.__writeItem(item, NoDisplay=False)
             else:
                 self.__addXmlFilename(menu_xml, dom, item.get_desktop_file_id(), 'Exclude')
             self.__addXmlTextElement(menu_xml, 'AppDir', util.getUserItemPath(), dom)
@@ -253,15 +253,12 @@ class MenuEditor:
             menu_xml = self.__getXmlMenu(self.__getPath(item), dom, dom)
             for node in self.__getXmlNodesByName(['Deleted', 'NotDeleted'], menu_xml):
                 node.parentNode.removeChild(node)
-            if visible:
-                self.__writeMenu(item, no_display=False)
-            else:
-                self.__writeMenu(item, no_display=True)
+            self.__writeMenu(item, NoDisplay=visible)
             self.__addXmlTextElement(menu_xml, 'DirectoryDir', util.getUserDirectoryPath(), dom)
         self.save()
 
-    def createItem(self, parent, icon, name, comment, command, use_term, before=None, after=None):
-        file_id = self.__writeItem(None, icon, name, comment, command, use_term)
+    def createItem(self, parent, before, after, **kwargs):
+        file_id = self.__writeItem(None, **kwargs)
         self.insertExternalItem(file_id, parent.get_menu_id(), before, after)
 
     def insertExternalItem(self, file_id, parent_id, before=None, after=None):
@@ -279,10 +276,6 @@ class MenuEditor:
         self.save()
         self.applications.tree.get_root_directory()
 
-    def createMenu(self, parent, icon, name, comment, before=None, after=None):
-        file_id = self.__writeMenu(None, icon, name, comment)
-        self.insertExternalMenu(file_id, parent.get_menu_id(), before, after)
-
     def insertExternalMenu(self, file_id, parent_id, before=None, after=None):
         menu_id = file_id.rsplit('.', 1)[0]
         parent = self.__findMenu(parent_id)
@@ -309,7 +302,7 @@ class MenuEditor:
             parent = item.get_parent()
         if final:
             self.__addUndo([self.__getMenu(parent), item])
-        self.__writeItem(item, icon, name, comment, command, use_term)
+        self.__writeItem(item, Icon=icon, Name=name, Comment=comment, Exec=command, Terminal=use_term)
         if final:
             dom = self.__getMenu(parent).dom
             menu_xml = self.__getXmlMenu(self.__getPath(parent), dom, dom)
@@ -324,7 +317,7 @@ class MenuEditor:
         #otherwise changes won't show up
         dom = self.__getMenu(menu).dom
         menu_xml = self.__getXmlMenu(self.__getPath(menu), dom, dom)
-        file_id = self.__writeMenu(menu, icon, name, comment)
+        self.__writeMenu(menu, Icon=icon, Name=name, Comment=comment)
         if final:
             self.__addXmlTextElement(menu_xml, 'DirectoryDir', util.getUserDirectoryPath(), dom)
             self.__addUndo([self.__getMenu(menu), menu])
@@ -333,14 +326,21 @@ class MenuEditor:
     def copyItem(self, item, new_parent, before=None, after=None):
         dom = self.__getMenu(new_parent).dom
         file_path = item.get_desktop_file_path()
-        keyfile = util.DesktopParser(file_path)
-        #erase Categories in new file
-        keyfile.set('Categories', ('',))
-        keyfile.set('Hidden', False)
+        keyfile = GLib.KeyFile()
+        keyfile.load_from_file(file_path, util.KEY_FILE_FLAGS)
+
+        util.fillKeyFile(keyfile, dict(Categories=[], Hidden=False))
+
         app_info = item.get_info()
         file_id = util.getUniqueFileId(app_info.get_name().replace(os.sep, '-'), '.desktop')
         out_path = os.path.join(util.getUserItemPath(), file_id)
-        keyfile.write(open(out_path, 'w'))
+
+        contents, length = keyfile.to_data()
+
+        f = open(out_path, 'w')
+        f.write(contents)
+        f.close()
+
         self.__addItem(new_parent, file_id, dom)
         self.__positionItem(new_parent, ('Item', file_id), before, after)
         self.__addUndo([self.__getMenu(new_parent), ('Item', file_id)])
@@ -405,7 +405,7 @@ class MenuEditor:
 
     def deleteItem(self, item):
         self.__addUndo([item,])
-        self.__writeItem(item, hidden=True)
+        self.__writeItem(item, Hidden=True)
         self.save()
 
     def deleteMenu(self, menu):
@@ -585,65 +585,61 @@ class MenuEditor:
         node = dom.createElement('Deleted')
         return element.appendChild(node)
 
-    def __writeItem(self, item=None, icon=None, name=None, comment=None, command=None, use_term=None, no_display=None, startup_notify=None, hidden=None):
-        if item:
+    def __makeKeyFile(self, file_path, kwargs):
+        if 'KeyFile' in kwargs:
+            return kwargs['KeyFile']
+
+        keyfile = GLib.KeyFile()
+
+        if file_path is not None:
+            keyfile.load_from_file(file_path, util.KEY_FILE_FLAGS)
+
+        util.fillKeyFile(keyfile, kwargs)
+        return keyfile
+
+    def __writeItem(self, item, **kwargs):
+        if item is not None:
             file_path = item.get_desktop_file_path()
+        else:
+            file_path = None
+
+        keyfile = self.__makeKeyFile(file_path, kwargs)
+
+        if item is not None:
             file_id = item.get_desktop_file_id()
-            keyfile = util.DesktopParser(file_path)
-        elif item == None and name == None:
-            raise Exception('New menu items need a name')
         else:
-            file_id = util.getUniqueFileId(name, '.desktop')
-            keyfile = util.DesktopParser()
-        if icon:
-            keyfile.set('Icon', icon)
-            keyfile.set('Icon', icon, self.locale)
-        if name:
-            keyfile.set('Name', name)
-            keyfile.set('Name', name, self.locale)
-        if comment:
-            keyfile.set('Comment', comment)
-            keyfile.set('Comment', comment, self.locale)
-        if command:
-            keyfile.set('Exec', command)
-        if use_term != None:
-            keyfile.set('Terminal', use_term)
-        if no_display != None:
-            keyfile.set('NoDisplay', no_display)
-        if startup_notify != None:
-            keyfile.set('StartupNotify', startup_notify)
-        if hidden != None:
-            keyfile.set('Hidden', hidden)
-        out_path = os.path.join(util.getUserItemPath(), file_id)
-        keyfile.write(open(out_path, 'w'))
+            file_id = util.getUniqueFileId(keyfile.get_string(GLib.KEY_FILE_DESKTOP_GROUP, 'Name'), '.desktop')
+
+        contents, length = keyfile.to_data()
+
+        f = open(os.path.join(util.getUserItemPath(), file_id), 'w')
+        f.write(contents)
+        f.close()
         return file_id
 
-    def __writeMenu(self, menu=None, icon=None, name=None, comment=None, no_display=None):
-        if menu:
+    def __writeMenu(self, menu, **kwargs):
+        if menu is not None:
             file_id = os.path.split(menu.get_desktop_file_path())[1]
             file_path = menu.get_desktop_file_path()
-            keyfile = util.DesktopParser(file_path)
-        elif menu == None and name == None:
+            keyfile = GLib.KeyFile()
+            keyfile.load_from_file(file_path, util.KEY_FILE_FLAGS)
+        elif menu is None and 'Name' not in kwargs:
             raise Exception('New menus need a name')
         else:
-            file_id = util.getUniqueFileId(name, '.directory')
-            keyfile = util.DesktopParser(file_type='Directory')
-        if icon:
-            keyfile.set('Icon', icon)
-        if name:
-            keyfile.set('Name', name)
-            keyfile.set('Name', name, self.locale)
-        if comment:
-            keyfile.set('Comment', comment)
-            keyfile.set('Comment', comment, self.locale)
-        if no_display != None:
-            keyfile.set('NoDisplay', no_display)
-        out_path = os.path.join(util.getUserDirectoryPath(), file_id)
-        keyfile.write(open(out_path, 'w'))
+            file_id = util.getUniqueFileId(kwargs['Name'], '.directory')
+            keyfile = GLib.KeyFile()
+
+        util.fillKeyFile(keyfile, kwargs)
+
+        contents, length = keyfile.to_data()
+
+        f = open(os.path.join(util.getUserDirectoryPath(), file_id), 'w')
+        f.write(contents)
+        f.close()
         return file_id
 
     def __getXmlNodesByName(self, name, element):
-        for    child in element.childNodes:
+        for child in element.childNodes:
             if child.nodeType == xml.dom.Node.ELEMENT_NODE:
                 if isinstance(name, str) and child.nodeName == name:
                     yield child
diff --git a/Alacarte/util.py b/Alacarte/util.py
index 0cba0ec..91af674 100644
--- a/Alacarte/util.py
+++ b/Alacarte/util.py
@@ -17,65 +17,23 @@
 #   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
 import os
-from gi.repository import Gtk, GdkPixbuf, GMenu
-from ConfigParser import ConfigParser
-
-class DesktopParser(ConfigParser):
-    def __init__(self, filename=None, file_type='Application'):
-        ConfigParser.__init__(self)
-        self.filename = filename
-        self.file_type = file_type
-        if filename:
-            if len(self.read(filename)) == 0:
-                #file doesn't exist
-                self.add_section('Desktop Entry')
-        else:
-            self.add_section('Desktop Entry')
-        self._list_separator = ';'
-
-    def optionxform(self, option):
-        #makes keys not be lowercase
-        return option
-
-    def get(self, option, locale=None):
-        locale_option = option + '[%s]' % locale
-        try:
-            value = ConfigParser.get(self, 'Desktop Entry', locale_option)
-        except:
-            try:
-                value = ConfigParser.get(self, 'Desktop Entry', option)
-            except:
-                return None
-        if self._list_separator in value:
-            value = value.split(self._list_separator)
-        if value == 'true':
-            value = True
-        if value == 'false':
-            value = False
-        return value
-
-    def set(self, option, value, locale=None):
-        if locale:
-            option = option + '[%s]' % locale
-        if value == True:
-            value = 'true'
-        if value == False:
-            value = 'false'
-        if isinstance(value, tuple) or isinstance(value, list):
-            value = self._list_separator.join(value) + ';'
-        ConfigParser.set(self, 'Desktop Entry', option, value)
-
-    def write(self, file_object):
-        file_object.write('[Desktop Entry]\n')
-        items = []
-        if not self.filename:
-            file_object.write('Encoding=UTF-8\n')
-            file_object.write('Type=' + str(self.file_type) + '\n')
-        for item in self.items('Desktop Entry'):
-            items.append(item)
-        items.sort()
-        for item in items:
-            file_object.write(item[0] + '=' + item[1] + '\n')
+from collections import Sequence
+from gi.repository import Gtk, GdkPixbuf, GMenu, GLib
+
+DESKTOP_GROUP = GLib.KEY_FILE_DESKTOP_GROUP
+KEY_FILE_FLAGS = GLib.KeyFileFlags.KEEP_COMMENTS | GLib.KeyFileFlags.KEEP_TRANSLATIONS
+
+def fillKeyFile(keyfile, items):
+    for key, item in items.iteritems():
+        if item is None:
+            continue
+
+        if isinstance(item, bool):
+            keyfile.set_boolean(DESKTOP_GROUP, key, item)
+        elif isinstance(item, Sequence):
+            keyfile.set_string_list(DESKTOP_GROUP, key, item)
+        elif isinstance(item, basestring):
+            keyfile.set_string(DESKTOP_GROUP, key, item)
 
 def getUniqueFileId(name, extension):
     append = 0



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]