[gnome-panel] [panel] Add gnome-panel-add script to allow easy addition of applets



commit 6b219799dae2aa6e2acd1f5a37bb13b3ef91d2bf
Author: Vincent Untz <vuntz gnome org>
Date:   Tue Aug 11 18:36:37 2009 +0200

    [panel] Add gnome-panel-add script to allow easy addition of applets
    
    This is mainly useful for administrators to add applets or launchers,
    therefore it's installed in libexecdir.
    
    http://bugzilla.gnome.org/show_bug.cgi?id=166623

 gnome-panel/Makefile.am     |    5 +-
 gnome-panel/gnome-panel-add |  278 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 282 insertions(+), 1 deletions(-)
---
diff --git a/gnome-panel/Makefile.am b/gnome-panel/Makefile.am
index b72f231..94eaf96 100644
--- a/gnome-panel/Makefile.am
+++ b/gnome-panel/Makefile.am
@@ -179,6 +179,8 @@ ui_DATA =					\
 	panel-properties-dialog.ui		\
 	panel-run-dialog.ui
 
+libexec_SCRIPTS = gnome-panel-add
+
 EXTRA_DIST =					\
 	$(ui_DATA)				\
 	nothing.cP				\
@@ -189,7 +191,8 @@ EXTRA_DIST =					\
 	panel-marshal.list			\
 	gnome-panelrc				\
 	$(entries_DATA)				\
-	$(desktop_DATA)
+	$(desktop_DATA)				\
+	$(libexec_SCRIPTS)
 
 @INTLTOOL_DESKTOP_RULE@
 
diff --git a/gnome-panel/gnome-panel-add b/gnome-panel/gnome-panel-add
new file mode 100755
index 0000000..49d0b5f
--- /dev/null
+++ b/gnome-panel/gnome-panel-add
@@ -0,0 +1,278 @@
+# vim: set ts=4 sw=4 et:
+
+#
+# Copyright (C) 2009 Novell, Inc.
+#
+# Authors: Vincent Untz <vuntz gnome org>
+#
+# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+import optparse
+import os
+import shutil
+import sys
+import urllib
+
+import bonobo
+import gconf
+
+PANEL_SCHEMAS_OBJECTS_DIR='/schemas/apps/panel/objects'
+
+PANEL_TOPLEVELS_DIR='/apps/panel/toplevels'
+PANEL_TOPLEVELS_KEY='/apps/panel/general/toplevel_id_list'
+PANEL_APPLETS_DIR='/apps/panel/applets'
+PANEL_APPLETS_KEY='/apps/panel/general/applet_id_list'
+PANEL_OBJECTS_DIR='/apps/panel/objects'
+PANEL_OBJECTS_KEY='/apps/panel/general/object_id_list'
+
+PANEL_LAUNCHER_USER_DIR=os.path.join(os.path.expanduser('~'), '.gnome2', 'panel2.d', 'default', 'launchers')
+
+PANEL_TYPE_NONE = 0
+PANEL_TYPE_APPLET = 1
+PANEL_TYPE_LAUNCHER = 2
+
+class PanelAddException(Exception):
+    pass
+
+class PanelAdder:
+
+    def __init__(self, toplevel, position, right_stick, applet_iid = None, launcher_path = None, copy_launcher = False):
+        self.toplevel = toplevel
+        self.position = position
+        self.right_stick = right_stick
+
+        # FIXME workaround: -1 and right_click don't play well together. Just
+        # use an arbitrary value so that the applet ends up at the left of all
+        # right-click applets (it'd be surprising to have a config with more
+        # than 10 applets...)
+        if self.right_stick and self.position < 0:
+            self.position = 10
+
+        self.type = PANEL_TYPE_NONE
+        self.applet_iid = None
+        self.launcher_path = None
+        self.copy_launcher = False
+
+        self.client = None
+
+        if applet_iid:
+            self._set_applet_iid(applet_iid)
+            self.type = PANEL_TYPE_APPLET
+        elif launcher_path:
+            self._set_launcher_path(launcher_path)
+            self.copy_launcher = copy_launcher
+            self.type = PANEL_TYPE_LAUNCHER
+
+    def _panel_get_subdirs(self, key):
+        return [ os.path.basename(s) for s in self.client.all_dirs(key) ]
+
+    def _panel_get_list(self, key):
+        list_v = self.client.get(key)
+
+        if not list_v:
+            return []
+
+        if list_v.type != gconf.VALUE_LIST or list_v.get_list_type() != gconf.VALUE_STRING:
+            return []
+
+        return [ v.get_string() for v in list_v.get_list() ]
+
+    def _toplevel_id_ensure(self):
+        toplevel_subdirs = self._panel_get_subdirs(PANEL_TOPLEVELS_DIR)
+        toplevel_id_list = self._panel_get_list(PANEL_TOPLEVELS_KEY)
+
+        if self.toplevel:
+            if not self.toplevel in toplevel_subdirs or not self.toplevel in toplevel_id_list:
+                raise PanelAddException('%s is not an existing panel identifier' % self.toplevel)
+        else:
+            for toplevel in toplevel_id_list:
+                if toplevel in toplevel_subdirs:
+                    self.toplevel = toplevel
+                    return
+
+            raise PanelAddException('Cannot find a panel identifier')
+
+    def _set_applet_iid(self, applet_iid):
+        if not applet_iid:
+            raise PanelAddException('No applet specified')
+
+        applets = bonobo.activation.query ("has_all (repo_ids, ['IDL:Bonobo/Control:1.0', 'IDL:GNOME/Vertigo/PanelAppletShell:1.0'])")
+        if not applet_iid in [ a.iid for a in applets ]:
+            raise PanelAddException('%s is not a valid applet' % applet_iid)
+
+        self.applet_iid = applet_iid
+
+    def _set_launcher_path(self, launcher_path):
+        if not launcher_path:
+            raise PanelAddException('No launcher specified')
+
+        if not launcher_path.endswith('.desktop'):
+            raise PanelAddException('%s does not have a .desktop extension' % launcher_path)
+
+        if not os.path.exists(launcher_path):
+            raise PanelAddException('%s is not an existing launcher' % launcher_path)
+
+        self.launcher_path = launcher_path
+
+    def _object_id_find_unused(self):
+        if self.type == PANEL_TYPE_APPLET:
+            subdirs = self._panel_get_subdirs(PANEL_APPLETS_DIR)
+            id_list = self._panel_get_list(PANEL_APPLETS_KEY)
+            prefix = 'applet'
+        else:
+            subdirs = self._panel_get_subdirs(PANEL_OBJECTS_DIR)
+            id_list = self._panel_get_list(PANEL_OBJECTS_KEY)
+            prefix = 'object'
+
+        i = 0
+        while i < 1000:
+            id = '%s_%d' % (prefix, i)
+            if id not in subdirs and id not in id_list:
+                return id
+            i += 1
+
+        return None
+
+    def _launcher_find_unused(self):
+        basename = os.path.basename(self.launcher_path)
+        if not os.path.exists(os.path.join(PANEL_LAUNCHER_USER_DIR, basename)):
+            return basename
+
+        dot = basename.rfind('.')
+        prefix = basename[:dot]
+        extension = basename[dot:]
+
+        i = 0
+        while i < 1000:
+            basename = '%s-%d%s' % (prefix, i, extension)
+            if not os.path.exists(os.path.join(PANEL_LAUNCHER_USER_DIR, basename)):
+                return basename
+            i += 1
+
+        raise PanelAddException('Copying %s would overwrite existing launchers' % self.launcher_path)
+
+    def _associate_schemas(self, engine, schema_dir, dest_dir):
+        entries = self.client.all_entries(schema_dir)
+        for entry in entries:
+            dest_key = os.path.basename(entry.key)
+            engine.associate_schema(os.path.join(dest_dir, dest_key), entry.key)
+
+        subdirs = self.client.all_dirs(schema_dir)
+        for subdir in subdirs:
+            dest_subdir = os.path.join(subdir)
+            self._associate_schemas(engine, subdir, os.path.join(dest_dir, dest_subdir))
+
+    def run(self):
+        self.client = gconf.client_get_default ()
+        self._toplevel_id_ensure()
+
+        id = self._object_id_find_unused()
+        if not id:
+            raise PanelAddException('No identifier available for the new object')
+
+        if self.type == PANEL_TYPE_APPLET:
+            dir = os.path.join(PANEL_APPLETS_DIR, id)
+
+        elif self.type == PANEL_TYPE_LAUNCHER:
+            dir = os.path.join(PANEL_OBJECTS_DIR, id)
+
+            if self.copy_launcher:
+                try:
+                    if not os.path.exists(PANEL_LAUNCHER_USER_DIR):
+                        os.makedirs(PANEL_LAUNCHER_USER_DIR)
+                    unused = self._launcher_find_unused()
+                    dest = os.path.join (PANEL_LAUNCHER_USER_DIR, unused)
+                    shutil.copyfile(self.launcher_path, dest)
+
+                    launcher_location = unused
+                except (OSError, IOError), e:
+                    raise PanelAddException('Cannot copy launcher: %s' % e)
+            else:
+                launcher_location = 'file://' + urllib.pathname2url(os.path.realpath(self.launcher_path))
+
+        else:
+            raise PanelAddException('Unknown panel object type %d' % self.type)
+
+        engine = gconf.engine_get_default()
+        self._associate_schemas(engine, PANEL_SCHEMAS_OBJECTS_DIR, dir)
+
+        self.client.set_string(os.path.join(dir, 'toplevel_id'), self.toplevel)
+        self.client.set_int(os.path.join(dir, 'position'), self.position)
+        self.client.set_bool(os.path.join(dir, 'panel_right_stick'), self.right_stick)
+
+        if self.type == PANEL_TYPE_APPLET:
+            self.client.set_string(os.path.join(dir, 'object_type'), 'bonobo-applet')
+            self.client.set_string(os.path.join(dir, 'bonobo_iid'), self.applet_iid)
+            id_list = self._panel_get_list(PANEL_APPLETS_KEY)
+            id_list.append(id)
+            self.client.set_list(PANEL_APPLETS_KEY, gconf.VALUE_STRING, id_list)
+
+        elif self.type == PANEL_TYPE_LAUNCHER:
+            self.client.set_string(os.path.join(dir, 'object_type'), 'launcher-object')
+            self.client.set_string(os.path.join(dir, 'launcher_location'), launcher_location)
+            id_list = self._panel_get_list(PANEL_OBJECTS_KEY)
+            id_list.append(id)
+            self.client.set_list(PANEL_OBJECTS_KEY, gconf.VALUE_STRING, id_list)
+
+        else:
+            raise PanelAddException('Unknown panel object type %d' % self.type)
+
+def main(args):
+    parser = optparse.OptionParser()
+
+    parser.add_option('--applet', dest='applet',
+                      help='Applet to add')
+    parser.add_option('--copy-launcher', dest='copy_launcher',
+                      action='store_true', default=False,
+                      help='Copy the launcher to the user directory')
+    parser.add_option('--launcher', dest='launcher',
+                      help='Launcher to add')
+    parser.add_option('--panel', dest='toplevel',
+                      help='Identifier of the panel where to add the applet')
+    parser.add_option('--position', dest='position',
+                      help='Position on the panel where to add the applet')
+    parser.add_option('--right-stick', dest='right_stick',
+                      action='store_true', default=False,
+                      help='Make the applet right-aligned on the panel')
+
+    (options, args) = parser.parse_args()
+
+    if not options.applet and not options.launcher:
+        print parser.format_help()
+        return 1
+
+    if options.applet and options.launcher:
+        raise PanelAddException('Cannot add an applet and a launcher at the same time')
+
+    if options.position:
+        try:
+            position = int(options.position)
+        except ValueError:
+            raise PanelAddException('%s is not an integer, required for position' % options.position)
+    else:
+        position = -1
+
+    adder = PanelAdder(options.toplevel, position, options.right_stick, options.applet, options.launcher, options.copy_launcher)
+    adder.run()
+
+if __name__ == '__main__':
+    try:
+      main(sys.argv)
+    except PanelAddException, e:
+        print >> sys.stderr, e
+        sys.exit(1)
+    except KeyboardInterrupt:
+      pass



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