home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / lib / deskbar-applet / handlers / programs.py < prev    next >
Encoding:
Python Source  |  2006-08-29  |  9.7 KB  |  318 lines

  1. import os, ConfigParser, cgi, re
  2. import glob
  3. from os.path import join, isfile, abspath, splitext, expanduser, exists, isdir
  4. from gettext import gettext as _
  5. from deskbar.defs import VERSION
  6. import gobject
  7. import gtk
  8. import deskbar, deskbar.Indexer, deskbar.Utils
  9. import deskbar.Handler, deskbar.Match, deskbar.gnomedesktop
  10. from deskbar.Utils import get_xdg_data_dirs
  11.  
  12. HANDLERS = {
  13.     "ProgramsHandler" : {
  14.         "name": _("Programs"),
  15.         "description": _("Launch a program by its name and/or description"),
  16.         "version": VERSION,
  17.     },
  18.     "GnomeDictHandler" : {
  19.         "name": _("Dictionary"),
  20.         "description": _("Look up word definitions in the dictionary"),
  21.         "version": VERSION,
  22.     },
  23.     "GnomeSearchHandler" : {
  24.         "name": _("Files and Folders Search"),
  25.         "description": _("Find files and folders by searching for a name pattern"),
  26.         "version": VERSION,
  27.     },
  28.     "DevhelpHandler" : {
  29.         "name": _("Developer Documentation"),
  30.         "description": _("Search Devhelp for a function name"),
  31.         "version": VERSION,
  32.     },
  33. }
  34.  
  35. EXACT_MATCH_PRIO = 100
  36. EXACT_WORD_PRIO = 50
  37.  
  38. class GenericProgramMatch(deskbar.Match.Match):
  39.     def __init__(self, backend, use_arg=False, desktop=None, desktop_file=None, **args):
  40.         deskbar.Match.Match.__init__(self, backend, **args)
  41.         
  42.         self.desktop_file = desktop_file
  43.         self.use_arg = use_arg
  44.         
  45.         self._priority = EXACT_WORD_PRIO
  46.         self._icon = deskbar.Utils.load_icon_for_desktop_icon(self.icon)
  47.         self._desktop = desktop
  48.         if desktop == None:
  49.             self._desktop = parse_desktop_filename(desktop_file)
  50.             if self._desktop == None:
  51.                 raise Exception("Desktop file not found, ignoring")
  52.         
  53.         # Strip %U or whatever arguments in Exec field
  54.         exe = re.sub("%\w+", "", self._desktop.get_string("Exec"))
  55.         # Strip any absolute path like /usr/bin/something to display only something
  56.         i = exe.split(" ")[0].rfind("/")
  57.         if i != -1:
  58.             exe = exe[i+1:]
  59.         
  60.         self._display_prog = cgi.escape(exe).strip()
  61.     
  62.     def get_hash(self, text=None):
  63.         return self._display_prog
  64.         
  65.     def action(self, text=None):
  66.         if self.use_arg and text != None:
  67.             args = [self._desktop.get_string("Exec")]
  68.             if hasattr(self, "_args"):
  69.                 args = args + self._args
  70.             args = args + text.split(" ")
  71.  
  72.             gobject.spawn_async(args, flags=gobject.SPAWN_SEARCH_PATH)
  73.             # FIXME: This does not launch the App with passed parameters because they are not files..
  74.             #self._desktop.launch(text.split(" "), deskbar.gnomedesktop.LAUNCH_APPEND_PATHS|deskbar.gnomedesktop.LAUNCH_ONLY_ONE)
  75.         else:
  76.             self._desktop.launch([])
  77.  
  78.     def get_category(self):
  79.         return "actions"
  80.     
  81.     def get_verb(self):
  82.         #translators: First %s is the programs full name, second is the executable name
  83.         #translators: For example: Launch Text Editor (gedit)
  84.         return _("Launch <b>%(name)s</b> (%(prog)s)")
  85.         
  86.     def get_name(self, text=None):
  87.         return {
  88.             "name": self.name,
  89.             "prog": self._display_prog,
  90.         }
  91.         
  92. class GnomeDictMatch(GenericProgramMatch):
  93.     def __init__(self, backend, use_arg=True, **args):
  94.         GenericProgramMatch.__init__(self, backend, use_arg=use_arg, **args)
  95.         self._args = ["--look-up"]
  96.     
  97.     def get_verb(self):
  98.         return _("Lookup %s in dictionary") % "<b>%(text)s</b>"
  99.  
  100. class GnomeSearchMatch(GenericProgramMatch):
  101.     def __init__(self, backend, use_arg=True, **args):
  102.         GenericProgramMatch.__init__(self, backend, use_arg=use_arg, **args)
  103.         self._args = ["--start", "--path", expanduser("~"), "--named"]
  104.         
  105.     def get_verb(self):
  106.         return _("Search for file names like %s") % "<b>%(text)s</b>"
  107.  
  108. class DevhelpMatch(GenericProgramMatch):
  109.     def __init__(self, backend, use_arg=True, **args):
  110.         GenericProgramMatch.__init__(self, backend, use_arg=use_arg, **args)
  111.         self._args = ["-s"]
  112.         
  113.     def get_verb(self):
  114.         return _("Search in Devhelp for %s") % "<b>%(text)s</b>"
  115.  
  116. class SpecialProgramHandler(deskbar.Handler.Handler):
  117.     def __init__(self, desktop, icon=gtk.STOCK_EXECUTE):
  118.         deskbar.Handler.Handler.__init__(self, icon)
  119.         self._desktop = desktop
  120.         self._match = None
  121.         
  122.     def initialize(self):
  123.         result = parse_desktop_filename(self._desktop, False)
  124.         if result != None:
  125.             self._match = self.create_match(result, self._desktop)
  126.     
  127.     def create_match(self, desktop, f):
  128.         raise NotImplementedError
  129.         
  130.     def query(self, qstring):
  131.         if self._match != None:
  132.             self._match._priority = get_priority_for_name(qstring, self._match._desktop.get_string("Exec"))
  133.             return [self._match]
  134.         else:
  135.             return []
  136.         
  137. class GnomeDictHandler(SpecialProgramHandler):
  138.     def __init__(self):
  139.         SpecialProgramHandler.__init__(self, "gnome-dictionary.desktop", "gdict")
  140.     
  141.     def create_match(self, desktop, f):
  142.         return GnomeDictMatch(
  143.                     self,
  144.                     name=cgi.escape(desktop.get_localestring(deskbar.gnomedesktop.KEY_NAME)),
  145.                     icon=desktop.get_string(deskbar.gnomedesktop.KEY_ICON),
  146.                     desktop=desktop,
  147.                     desktop_file=f)
  148.  
  149. class GnomeSearchHandler(SpecialProgramHandler):
  150.     def __init__(self):
  151.         SpecialProgramHandler.__init__(self, "gnome-search-tool.desktop", "gnome-searchtool")
  152.     
  153.     def create_match(self, desktop, f):
  154.         return GnomeSearchMatch(
  155.                     self,
  156.                     name=cgi.escape(desktop.get_localestring(deskbar.gnomedesktop.KEY_NAME)),
  157.                     icon=desktop.get_string(deskbar.gnomedesktop.KEY_ICON),
  158.                     desktop=desktop,
  159.                     desktop_file=f)
  160.         
  161. class DevhelpHandler(SpecialProgramHandler):
  162.     def __init__(self):
  163.         SpecialProgramHandler.__init__(self, "devhelp.desktop", "devhelp")
  164.     
  165.     def create_match(self, desktop, f):
  166.         return DevhelpMatch(
  167.                     self,
  168.                     name=cgi.escape(desktop.get_localestring(deskbar.gnomedesktop.KEY_NAME)),
  169.                     icon=desktop.get_string(deskbar.gnomedesktop.KEY_ICON),
  170.                     desktop=desktop,
  171.                     desktop_file=f)
  172.  
  173. class PathProgramMatch(deskbar.Match.Match):
  174.     def __init__(self, backend, name=None, use_terminal=False, priority=0, **args):
  175.         deskbar.Match.Match.__init__(self, backend, name=name, **args)
  176.         self.use_terminal = use_terminal
  177.         self._priority = EXACT_MATCH_PRIO
  178.         
  179.     def set_with_terminal(self, terminal):
  180.         self.use_terminal = terminal
  181.         
  182.     def get_hash(self, text=None):
  183.         if not self.use_terminal:
  184.             return text
  185.         else:
  186.             return (text, True)
  187.         
  188.     def action(self, text=None):
  189.         if self.use_terminal:
  190.             try:
  191.                 prog = subprocess.Popen(
  192.                     text.split(" "),
  193.                     stdout=subprocess.PIPE,
  194.                     stderr=subprocess.STDOUT)
  195.                 
  196.                 zenity = subprocess.Popen(
  197.                     ["zenity", "--title="+text,
  198.                         "--window-icon="+join(deskbar.ART_DATA_DIR, "generic.png"),
  199.                         "--width=700",
  200.                         "--height=500",
  201.                         "--text-info"],
  202.                     stdin=prog.stdout)
  203.     
  204.                 # Reap the processes when they have done
  205.                 gobject.child_watch_add(zenity.pid, lambda pid, code: None)
  206.                 gobject.child_watch_add(prog.pid, lambda pid, code: None)
  207.                 return
  208.             except:
  209.                 #No zenity, get out of the if, and launch without GUI
  210.                 pass
  211.         
  212.         gobject.spawn_async(text.split(" "), flags=gobject.SPAWN_SEARCH_PATH)            
  213.  
  214.     def get_category(self):
  215.         return "actions"
  216.     
  217.     def get_verb(self):
  218.         return _("Execute %s") % "<b>%(text)s</b>"
  219.         
  220. class ProgramsHandler(deskbar.Handler.Handler):
  221.     def __init__(self):
  222.         deskbar.Handler.Handler.__init__(self, gtk.STOCK_EXECUTE)
  223.         self._indexer = deskbar.Indexer.Indexer()
  224.         
  225.     def initialize(self):
  226.         self._scan_desktop_files()
  227.         self._path = [path for path in os.getenv("PATH").split(os.path.pathsep) if path.strip() != "" and exists(path) and isdir(path)]
  228.         
  229.     def query(self, query):
  230.         result = self.query_path_programs(query)
  231.         result += self.query_desktop_programs(query)
  232.         return result
  233.         
  234.     def query_path_programs(self, query):
  235.         args = query.split(" ")
  236.         match = self._check_program(args[0])
  237.  
  238.         if match != None:
  239.             return [match]
  240.         else:
  241.             return []
  242.     
  243.     def query_desktop_programs(self, query):
  244.         result = []
  245.         for match in self._indexer.look_up(query):
  246.             match._priority = get_priority_for_name(query, match._desktop.get_string("Exec"))
  247.             result.append(match)
  248.         return result
  249.             
  250.     
  251.     def on_key_press(self, query, shortcut):
  252.         if shortcut == gtk.keysyms.t:
  253.             match = self._check_program(query.split(" ")[0])
  254.             if match != None:
  255.                 match.set_with_terminal(True)
  256.                 return match
  257.             
  258.         return None
  259.         
  260.     def _check_program(self, program):
  261.         for path in self._path:
  262.             prog_path = join(path, program)
  263.             if exists(prog_path) and isfile(prog_path):
  264.                 return PathProgramMatch(self, program)    
  265.                 
  266.     def _scan_desktop_files(self):
  267.         for dir in get_xdg_data_dirs():
  268.             for f in glob.glob(join(dir, "applications", "*.desktop")):
  269.                 result = parse_desktop_file(f)
  270.                 if result != None:
  271.                     match = GenericProgramMatch(
  272.                                 self,
  273.                                 name=cgi.escape(result.get_localestring(deskbar.gnomedesktop.KEY_NAME)),
  274.                                 icon=result.get_string(deskbar.gnomedesktop.KEY_ICON),
  275.                                 desktop=result,
  276.                                 desktop_file=f)
  277.                     self._indexer.add("%s %s %s %s %s" % (
  278.                                 result.get_string("Exec"),
  279.                                 result.get_localestring(deskbar.gnomedesktop.KEY_NAME),
  280.                                 result.get_localestring(deskbar.gnomedesktop.KEY_COMMENT),
  281.                                 result.get_string(deskbar.gnomedesktop.KEY_NAME),
  282.                                 result.get_string(deskbar.gnomedesktop.KEY_COMMENT),
  283.                             ), match)
  284.  
  285. def get_priority_for_name(query, name):
  286.     if name.split(" ")[0].endswith(query):
  287.         return EXACT_MATCH_PRIO
  288.     else:
  289.         return EXACT_WORD_PRIO
  290.         
  291. def parse_desktop_filename(desktop, only_if_visible=True):
  292.     if desktop[0] == "/" and exists(desktop):
  293.         return parse_desktop_file(desktop, only_if_visible)
  294.             
  295.     for dir in get_xdg_data_dirs():
  296.         f = join(dir, "applications", desktop)
  297.         if exists(f):
  298.             return parse_desktop_file(f, only_if_visible)
  299.     
  300.     return None
  301.  
  302.  
  303. def parse_desktop_file(desktop, only_if_visible=True):
  304.     try:
  305.         desktop = deskbar.gnomedesktop.item_new_from_file(desktop, deskbar.gnomedesktop.LOAD_ONLY_IF_EXISTS)
  306.     except Exception, e:
  307.         print 'Couldn\'t read desktop file:%s:%s' % (desktop, e)
  308.         return None
  309.     
  310.     if desktop == None or desktop.get_entry_type() != deskbar.gnomedesktop.TYPE_APPLICATION:
  311.         return None
  312.     if desktop.get_boolean(deskbar.gnomedesktop.KEY_TERMINAL):
  313.         return None
  314.     if only_if_visible and desktop.get_boolean(deskbar.gnomedesktop.KEY_NO_DISPLAY):
  315.         return None
  316.         
  317.     return desktop
  318.