diff options
author | Perberos <[email protected]> | 2011-12-01 22:56:10 -0300 |
---|---|---|
committer | Perberos <[email protected]> | 2011-12-01 22:56:10 -0300 |
commit | c51ef797a707f4e2c6f9688d4378f2b0e9898a66 (patch) | |
tree | 019ae92bb53c19b30077545cb14743cbd1b57aef /mate-panel/mate-panel-add.in | |
download | mate-panel-c51ef797a707f4e2c6f9688d4378f2b0e9898a66.tar.bz2 mate-panel-c51ef797a707f4e2c6f9688d4378f2b0e9898a66.tar.xz |
moving from https://github.com/perberos/mate-desktop-environment
Diffstat (limited to 'mate-panel/mate-panel-add.in')
-rw-r--r-- | mate-panel/mate-panel-add.in | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/mate-panel/mate-panel-add.in b/mate-panel/mate-panel-add.in new file mode 100644 index 00000000..b50669cd --- /dev/null +++ b/mate-panel/mate-panel-add.in @@ -0,0 +1,325 @@ +#!@PYTHON@ +# vim: set ts=4 sw=4 et: + +# +# Copyright (C) 2009 Novell, Inc. +# +# Authors: Vincent Untz <[email protected]> +# +# 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 ConfigParser + +try: + import matecomponent + has_matecomponent = True +except ImportError: + has_matecomponent = False + +import mateconf + +PANEL_SCHEMAS_OBJECTS_DIR='/schemas/apps/panel/objects' + +PANEL_TOPLEVELS_DIR='/apps/panel/toplevels' +PANEL_TOPLEVELS_KEY='/apps/panel/general/toplevel_id_list' +MATE_PANEL_APPLETS_DIR='/apps/panel/applets' +MATE_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('~'), '.mate2', 'panel2.d', 'default', 'launchers') + +PANEL_TYPE_NONE = 0 +PANEL_TYPE_APPLET = 1 +PANEL_TYPE_LAUNCHER = 2 + +MATE_PANEL_APPLETS_EXTENSION='.mate-panel-applet' +MATE_PANEL_APPLETS_PATH='@MATE_PANEL_APPLETS_DIR@' +MATE_PANEL_APPLET_FACTORY_GROUP='Applet Factory' + +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 != mateconf.VALUE_LIST or list_v.get_list_type() != mateconf.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 _get_applet_list(self): + dirs = os.getenv('MATE_PANEL_APPLETS_DIR') + if not dirs: + dirs = MATE_PANEL_APPLETS_PATH + + retval = [] + dups = [] + for path in dirs.split(":"): + if not os.path.isdir(path): + continue + + if path in dups: + continue + + dups.append(path) + + for f in os.listdir(path): + if not f.endswith(MATE_PANEL_APPLETS_EXTENSION): + continue + + config = ConfigParser.RawConfigParser() + try: + config.read(os.path.join(path, f)) + except ConfigParser.ParsingError: + continue + + fid = config.get(MATE_PANEL_APPLET_FACTORY_GROUP, 'Id') + retval.extend(["%s::%s" % (fid, s) for s in config.sections() if s != MATE_PANEL_APPLET_FACTORY_GROUP]) + + return retval + + def _set_applet_iid(self, applet_iid): + if not applet_iid: + raise PanelAddException('No applet specified') + + applets = self._get_applet_list () + if not applet_iid in applets: + if has_matecomponent: + applets = matecomponent.activation.query ("has_all (repo_ids, ['IDL:MateComponent/Control:1.0', 'IDL:MATE/Vertigo/MatePanelAppletShell:1.0'])") + if not applet_iid in [ a.iid for a in applets ]: + raise PanelAddException('%s is not a valid applet' % applet_iid) + else: + 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(MATE_PANEL_APPLETS_DIR) + id_list = self._panel_get_list(MATE_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 = mateconf.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(MATE_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 = mateconf.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'), 'matecomponent-applet') + self.client.set_string(os.path.join(dir, 'applet_iid'), self.applet_iid) + id_list = self._panel_get_list(MATE_PANEL_APPLETS_KEY) + id_list.append(id) + self.client.set_list(MATE_PANEL_APPLETS_KEY, mateconf.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, mateconf.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 |