home *** CD-ROM | disk | FTP | other *** search
/ tusportal.tus.k12.pa.us / tusportal.tus.k12.pa.us.tar / tusportal.tus.k12.pa.us / Wyse / latest-image.raw / 0.img / usr / lib / gnome-panel / gnome-panel-add < prev    next >
Text File  |  2010-05-12  |  10KB  |  280 lines

  1. #!/usr/bin/python
  2. # vim: set ts=4 sw=4 et:
  3.  
  4. #
  5. # Copyright (C) 2009 Novell, Inc.
  6. #
  7. # Authors: Vincent Untz <vuntz@gnome.org>
  8. #
  9. # This program is free software; you can redistribute it and/or modify
  10. # it under the terms of the GNU General Public License as published by
  11. # the Free Software Foundation; either version 2 of the License, or
  12. # (at your option) any later version.
  13. #
  14. # This program is distributed in the hope that it will be useful,
  15. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. # GNU General Public License for more details.
  18. #
  19. # You should have received a copy of the GNU General Public License
  20. # along with this program; if not, write to the Free Software
  21. # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22. #
  23.  
  24. import optparse
  25. import os
  26. import shutil
  27. import sys
  28. import urllib
  29.  
  30. import bonobo
  31. import gconf
  32.  
  33. PANEL_SCHEMAS_OBJECTS_DIR='/schemas/apps/panel/objects'
  34.  
  35. PANEL_TOPLEVELS_DIR='/apps/panel/toplevels'
  36. PANEL_TOPLEVELS_KEY='/apps/panel/general/toplevel_id_list'
  37. PANEL_APPLETS_DIR='/apps/panel/applets'
  38. PANEL_APPLETS_KEY='/apps/panel/general/applet_id_list'
  39. PANEL_OBJECTS_DIR='/apps/panel/objects'
  40. PANEL_OBJECTS_KEY='/apps/panel/general/object_id_list'
  41.  
  42. PANEL_LAUNCHER_USER_DIR=os.path.join(os.path.expanduser('~'), '.gnome2', 'panel2.d', 'default', 'launchers')
  43.  
  44. PANEL_TYPE_NONE = 0
  45. PANEL_TYPE_APPLET = 1
  46. PANEL_TYPE_LAUNCHER = 2
  47.  
  48. class PanelAddException(Exception):
  49.     pass
  50.  
  51. class PanelAdder:
  52.  
  53.     def __init__(self, toplevel, position, right_stick, applet_iid = None, launcher_path = None, copy_launcher = False):
  54.         self.toplevel = toplevel
  55.         self.position = position
  56.         self.right_stick = right_stick
  57.  
  58.         # FIXME workaround: -1 and right_click don't play well together. Just
  59.         # use an arbitrary value so that the applet ends up at the left of all
  60.         # right-click applets (it'd be surprising to have a config with more
  61.         # than 10 applets...)
  62.         if self.right_stick and self.position < 0:
  63.             self.position = 10
  64.  
  65.         self.type = PANEL_TYPE_NONE
  66.         self.applet_iid = None
  67.         self.launcher_path = None
  68.         self.copy_launcher = False
  69.  
  70.         self.client = None
  71.  
  72.         if applet_iid:
  73.             self._set_applet_iid(applet_iid)
  74.             self.type = PANEL_TYPE_APPLET
  75.         elif launcher_path:
  76.             self._set_launcher_path(launcher_path)
  77.             self.copy_launcher = copy_launcher
  78.             self.type = PANEL_TYPE_LAUNCHER
  79.  
  80.     def _panel_get_subdirs(self, key):
  81.         return [ os.path.basename(s) for s in self.client.all_dirs(key) ]
  82.  
  83.     def _panel_get_list(self, key):
  84.         list_v = self.client.get(key)
  85.  
  86.         if not list_v:
  87.             return []
  88.  
  89.         if list_v.type != gconf.VALUE_LIST or list_v.get_list_type() != gconf.VALUE_STRING:
  90.             return []
  91.  
  92.         return [ v.get_string() for v in list_v.get_list() ]
  93.  
  94.     def _toplevel_id_ensure(self):
  95.         toplevel_subdirs = self._panel_get_subdirs(PANEL_TOPLEVELS_DIR)
  96.         toplevel_id_list = self._panel_get_list(PANEL_TOPLEVELS_KEY)
  97.  
  98.         if self.toplevel:
  99.             if not self.toplevel in toplevel_subdirs or not self.toplevel in toplevel_id_list:
  100.                 raise PanelAddException('%s is not an existing panel identifier' % self.toplevel)
  101.         else:
  102.             for toplevel in toplevel_id_list:
  103.                 if toplevel in toplevel_subdirs:
  104.                     self.toplevel = toplevel
  105.                     return
  106.  
  107.             raise PanelAddException('Cannot find a panel identifier')
  108.  
  109.     def _set_applet_iid(self, applet_iid):
  110.         if not applet_iid:
  111.             raise PanelAddException('No applet specified')
  112.  
  113.         applets = bonobo.activation.query ("has_all (repo_ids, ['IDL:Bonobo/Control:1.0', 'IDL:GNOME/Vertigo/PanelAppletShell:1.0'])")
  114.         if not applet_iid in [ a.iid for a in applets ]:
  115.             raise PanelAddException('%s is not a valid applet' % applet_iid)
  116.  
  117.         self.applet_iid = applet_iid
  118.  
  119.     def _set_launcher_path(self, launcher_path):
  120.         if not launcher_path:
  121.             raise PanelAddException('No launcher specified')
  122.  
  123.         if not launcher_path.endswith('.desktop'):
  124.             raise PanelAddException('%s does not have a .desktop extension' % launcher_path)
  125.  
  126.         if not os.path.exists(launcher_path):
  127.             raise PanelAddException('%s is not an existing launcher' % launcher_path)
  128.  
  129.         self.launcher_path = launcher_path
  130.  
  131.     def _object_id_find_unused(self):
  132.         if self.type == PANEL_TYPE_APPLET:
  133.             subdirs = self._panel_get_subdirs(PANEL_APPLETS_DIR)
  134.             id_list = self._panel_get_list(PANEL_APPLETS_KEY)
  135.             prefix = 'applet'
  136.         else:
  137.             subdirs = self._panel_get_subdirs(PANEL_OBJECTS_DIR)
  138.             id_list = self._panel_get_list(PANEL_OBJECTS_KEY)
  139.             prefix = 'object'
  140.  
  141.         i = 0
  142.         while i < 1000:
  143.             id = '%s_%d' % (prefix, i)
  144.             if id not in subdirs and id not in id_list:
  145.                 return id
  146.             i += 1
  147.  
  148.         return None
  149.  
  150.     def _launcher_find_unused(self):
  151.         basename = os.path.basename(self.launcher_path)
  152.         if not os.path.exists(os.path.join(PANEL_LAUNCHER_USER_DIR, basename)):
  153.             return basename
  154.  
  155.         dot = basename.rfind('.')
  156.         prefix = basename[:dot]
  157.         extension = basename[dot:]
  158.  
  159.         i = 0
  160.         while i < 1000:
  161.             basename = '%s-%d%s' % (prefix, i, extension)
  162.             if not os.path.exists(os.path.join(PANEL_LAUNCHER_USER_DIR, basename)):
  163.                 return basename
  164.             i += 1
  165.  
  166.         raise PanelAddException('Copying %s would overwrite existing launchers' % self.launcher_path)
  167.  
  168.     def _associate_schemas(self, engine, schema_dir, dest_dir):
  169.         entries = self.client.all_entries(schema_dir)
  170.         for entry in entries:
  171.             dest_key = os.path.basename(entry.key)
  172.             engine.associate_schema(os.path.join(dest_dir, dest_key), entry.key)
  173.  
  174.         subdirs = self.client.all_dirs(schema_dir)
  175.         for subdir in subdirs:
  176.             dest_subdir = os.path.join(subdir)
  177.             self._associate_schemas(engine, subdir, os.path.join(dest_dir, dest_subdir))
  178.  
  179.     def run(self):
  180.         self.client = gconf.client_get_default ()
  181.         self._toplevel_id_ensure()
  182.  
  183.         id = self._object_id_find_unused()
  184.         if not id:
  185.             raise PanelAddException('No identifier available for the new object')
  186.  
  187.         if self.type == PANEL_TYPE_APPLET:
  188.             dir = os.path.join(PANEL_APPLETS_DIR, id)
  189.  
  190.         elif self.type == PANEL_TYPE_LAUNCHER:
  191.             dir = os.path.join(PANEL_OBJECTS_DIR, id)
  192.  
  193.             if self.copy_launcher:
  194.                 try:
  195.                     if not os.path.exists(PANEL_LAUNCHER_USER_DIR):
  196.                         os.makedirs(PANEL_LAUNCHER_USER_DIR)
  197.                     unused = self._launcher_find_unused()
  198.                     dest = os.path.join (PANEL_LAUNCHER_USER_DIR, unused)
  199.                     shutil.copyfile(self.launcher_path, dest)
  200.  
  201.                     launcher_location = unused
  202.                 except (OSError, IOError), e:
  203.                     raise PanelAddException('Cannot copy launcher: %s' % e)
  204.             else:
  205.                 launcher_location = 'file://' + urllib.pathname2url(os.path.realpath(self.launcher_path))
  206.  
  207.         else:
  208.             raise PanelAddException('Unknown panel object type %d' % self.type)
  209.  
  210.         engine = gconf.engine_get_default()
  211.         self._associate_schemas(engine, PANEL_SCHEMAS_OBJECTS_DIR, dir)
  212.  
  213.         self.client.set_string(os.path.join(dir, 'toplevel_id'), self.toplevel)
  214.         self.client.set_int(os.path.join(dir, 'position'), self.position)
  215.         self.client.set_bool(os.path.join(dir, 'panel_right_stick'), self.right_stick)
  216.  
  217.         if self.type == PANEL_TYPE_APPLET:
  218.             self.client.set_string(os.path.join(dir, 'object_type'), 'bonobo-applet')
  219.             self.client.set_string(os.path.join(dir, 'bonobo_iid'), self.applet_iid)
  220.             id_list = self._panel_get_list(PANEL_APPLETS_KEY)
  221.             id_list.append(id)
  222.             self.client.set_list(PANEL_APPLETS_KEY, gconf.VALUE_STRING, id_list)
  223.  
  224.         elif self.type == PANEL_TYPE_LAUNCHER:
  225.             self.client.set_string(os.path.join(dir, 'object_type'), 'launcher-object')
  226.             self.client.set_string(os.path.join(dir, 'launcher_location'), launcher_location)
  227.             id_list = self._panel_get_list(PANEL_OBJECTS_KEY)
  228.             id_list.append(id)
  229.             self.client.set_list(PANEL_OBJECTS_KEY, gconf.VALUE_STRING, id_list)
  230.  
  231.         else:
  232.             raise PanelAddException('Unknown panel object type %d' % self.type)
  233.  
  234. def main(args):
  235.     parser = optparse.OptionParser()
  236.  
  237.     parser.add_option('--applet', dest='applet',
  238.                       help='Applet to add')
  239.     parser.add_option('--copy-launcher', dest='copy_launcher',
  240.                       action='store_true', default=False,
  241.                       help='Copy the launcher to the user directory')
  242.     parser.add_option('--launcher', dest='launcher',
  243.                       help='Launcher to add')
  244.     parser.add_option('--panel', dest='toplevel',
  245.                       help='Identifier of the panel where to add the applet')
  246.     parser.add_option('--position', dest='position',
  247.                       help='Position on the panel where to add the applet')
  248.     parser.add_option('--right-stick', dest='right_stick',
  249.                       action='store_true', default=False,
  250.                       help='Make the applet right-aligned on the panel')
  251.  
  252.     (options, args) = parser.parse_args()
  253.  
  254.     if not options.applet and not options.launcher:
  255.         print parser.format_help()
  256.         return 1
  257.  
  258.     if options.applet and options.launcher:
  259.         raise PanelAddException('Cannot add an applet and a launcher at the same time')
  260.  
  261.     if options.position:
  262.         try:
  263.             position = int(options.position)
  264.         except ValueError:
  265.             raise PanelAddException('%s is not an integer, required for position' % options.position)
  266.     else:
  267.         position = -1
  268.  
  269.     adder = PanelAdder(options.toplevel, position, options.right_stick, options.applet, options.launcher, options.copy_launcher)
  270.     adder.run()
  271.  
  272. if __name__ == '__main__':
  273.     try:
  274.       main(sys.argv)
  275.     except PanelAddException, e:
  276.         print >> sys.stderr, e
  277.         sys.exit(1)
  278.     except KeyboardInterrupt:
  279.       pass
  280.