home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / lib / deskbar-applet / handlers / programs.py < prev    next >
Encoding:
Python Source  |  2007-04-09  |  9.6 KB  |  319 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, is_program_in_path, spawn_async
  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 "generic_"+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]
  71.  
  72.             spawn_async(args)
  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.             try:
  77.                 self._desktop.launch([])
  78.             except Exception, e:
  79.                 #FIXME: Proper dialog here. Also see end of Utils.py
  80.                 print 'Warning:Could not launch .desktop file:', e
  81.  
  82.     def get_category(self):
  83.         return "actions"
  84.     
  85.     def get_verb(self):
  86.         #translators: First %s is the programs full name, second is the executable name
  87.         #translators: For example: Launch Text Editor (gedit)
  88.         return _("Launch <b>%(name)s</b> (%(prog)s)")
  89.         
  90.     def get_name(self, text=None):
  91.         return {
  92.             "name": self.name,
  93.             "prog": self._display_prog,
  94.         }
  95.         
  96. class GnomeDictMatch(GenericProgramMatch):
  97.     def __init__(self, backend, use_arg=True, **args):
  98.         GenericProgramMatch.__init__(self, backend, use_arg=use_arg, **args)
  99.         self._args = ["--look-up"]
  100.     
  101.     def get_verb(self):
  102.         return _("Lookup %s in dictionary") % "<b>%(text)s</b>"
  103.  
  104. class GnomeSearchMatch(GenericProgramMatch):
  105.     def __init__(self, backend, use_arg=True, **args):
  106.         GenericProgramMatch.__init__(self, backend, use_arg=use_arg, **args)
  107.         self._args = ["--start", "--path", expanduser("~"), "--named"]
  108.         
  109.     def get_verb(self):
  110.         return _("Search for file names like %s") % "<b>%(text)s</b>"
  111.  
  112. class DevhelpMatch(GenericProgramMatch):
  113.     def __init__(self, backend, use_arg=True, **args):
  114.         GenericProgramMatch.__init__(self, backend, use_arg=use_arg, **args)
  115.         self._args = ["-s"]
  116.         
  117.     def get_verb(self):
  118.         return _("Search in Devhelp for %s") % "<b>%(text)s</b>"
  119.  
  120. class SpecialProgramHandler(deskbar.Handler.Handler):
  121.     def __init__(self, desktop, icon=gtk.STOCK_EXECUTE):
  122.         deskbar.Handler.Handler.__init__(self, icon)
  123.         self._desktop = desktop
  124.         self._match = None
  125.         
  126.     def initialize(self):
  127.         result = parse_desktop_filename(self._desktop, False)
  128.         if result != None:
  129.             self._match = self.create_match(result, self._desktop)
  130.     
  131.     def create_match(self, desktop, f):
  132.         raise NotImplementedError
  133.         
  134.     def query(self, qstring):
  135.         if self._match != None:
  136.             self._match._priority = get_priority_for_name(qstring, self._match._desktop.get_string("Exec"))
  137.             return [self._match]
  138.         else:
  139.             return []
  140.         
  141. class GnomeDictHandler(SpecialProgramHandler):
  142.     def __init__(self):
  143.         SpecialProgramHandler.__init__(self, "gnome-dictionary.desktop", "gdict")
  144.     
  145.     def create_match(self, desktop, f):
  146.         return GnomeDictMatch(
  147.                     self,
  148.                     name=cgi.escape(desktop.get_localestring(deskbar.gnomedesktop.KEY_NAME)),
  149.                     icon=desktop.get_string(deskbar.gnomedesktop.KEY_ICON),
  150.                     desktop=desktop,
  151.                     desktop_file=f)
  152.  
  153. class GnomeSearchHandler(SpecialProgramHandler):
  154.     def __init__(self):
  155.         SpecialProgramHandler.__init__(self, "gnome-search-tool.desktop", "gnome-searchtool")
  156.     
  157.     def create_match(self, desktop, f):
  158.         return GnomeSearchMatch(
  159.                     self,
  160.                     name=cgi.escape(desktop.get_localestring(deskbar.gnomedesktop.KEY_NAME)),
  161.                     icon=desktop.get_string(deskbar.gnomedesktop.KEY_ICON),
  162.                     desktop=desktop,
  163.                     desktop_file=f)
  164.         
  165. class DevhelpHandler(SpecialProgramHandler):
  166.     def __init__(self):
  167.         SpecialProgramHandler.__init__(self, "devhelp.desktop", "devhelp")
  168.     
  169.     def create_match(self, desktop, f):
  170.         return DevhelpMatch(
  171.                     self,
  172.                     name=cgi.escape(desktop.get_localestring(deskbar.gnomedesktop.KEY_NAME)),
  173.                     icon=desktop.get_string(deskbar.gnomedesktop.KEY_ICON),
  174.                     desktop=desktop,
  175.                     desktop_file=f)
  176.  
  177. class PathProgramMatch(deskbar.Match.Match):
  178.     def __init__(self, backend, name=None, use_terminal=False, priority=0, **args):
  179.         deskbar.Match.Match.__init__(self, backend, name=name, **args)
  180.         self.use_terminal = use_terminal
  181.         self._priority = EXACT_MATCH_PRIO
  182.         
  183.     def set_with_terminal(self, terminal):
  184.         self.use_terminal = terminal
  185.         
  186.     def get_hash(self, text=None):
  187.         if not self.use_terminal:
  188.             return text
  189.         else:
  190.             return (text, True)
  191.         
  192.     def action(self, text=None):
  193.         if self.use_terminal:
  194.             try:
  195.                 prog = subprocess.Popen(
  196.                     text.split(" "),
  197.                     stdout=subprocess.PIPE,
  198.                     stderr=subprocess.STDOUT)
  199.                 
  200.                 zenity = subprocess.Popen(
  201.                     ["zenity", "--title="+text,
  202.                         "--window-icon="+join(deskbar.ART_DATA_DIR, "generic.png"),
  203.                         "--width=700",
  204.                         "--height=500",
  205.                         "--text-info"],
  206.                     stdin=prog.stdout)
  207.     
  208.                 # Reap the processes when they have done
  209.                 gobject.child_watch_add(zenity.pid, lambda pid, code: None)
  210.                 gobject.child_watch_add(prog.pid, lambda pid, code: None)
  211.                 return
  212.             except:
  213.                 #No zenity, get out of the if, and launch without GUI
  214.                 pass
  215.         
  216.         spawn_async(text.split(" "))            
  217.  
  218.     def get_category(self):
  219.         return "actions"
  220.     
  221.     def get_verb(self):
  222.         return _("Execute %s") % "<b>%(text)s</b>"
  223.         
  224. class ProgramsHandler(deskbar.Handler.Handler):
  225.     def __init__(self):
  226.         deskbar.Handler.Handler.__init__(self, gtk.STOCK_EXECUTE)
  227.         self._indexer = deskbar.Indexer.Indexer()
  228.         
  229.     def initialize(self):
  230.         self._scan_desktop_files()
  231.         
  232.     def query(self, query):
  233.         result = self.query_path_programs(query)
  234.         result += self.query_desktop_programs(query)
  235.         return result
  236.         
  237.     def query_path_programs(self, query):
  238.         args = query.split(" ")
  239.         match = self._check_program(args[0])
  240.  
  241.         if match != None:
  242.             return [match]
  243.         else:
  244.             return []
  245.     
  246.     def query_desktop_programs(self, query):
  247.         result = []
  248.         for match in self._indexer.look_up(query):
  249.             match._priority = get_priority_for_name(query, match._desktop.get_string("Exec"))
  250.             result.append(match)
  251.         return result
  252.             
  253.     
  254.     def on_key_press(self, query, shortcut):
  255.         if shortcut == gtk.keysyms.t:
  256.             match = self._check_program(query.split(" ")[0])
  257.             if match != None:
  258.                 match.set_with_terminal(True)
  259.                 return match
  260.             
  261.         return None
  262.         
  263.     def _check_program(self, program):
  264.         if is_program_in_path(program):
  265.             return PathProgramMatch(self, program)    
  266.                 
  267.     def _scan_desktop_files(self):
  268.         for dir in get_xdg_data_dirs():
  269.             for f in glob.glob(join(dir, "applications", "*.desktop")):
  270.                 result = parse_desktop_file(f)
  271.                 if result != None:
  272.                     match = GenericProgramMatch(
  273.                                 self,
  274.                                 name=cgi.escape(result.get_localestring(deskbar.gnomedesktop.KEY_NAME)),
  275.                                 icon=result.get_string(deskbar.gnomedesktop.KEY_ICON),
  276.                                 desktop=result,
  277.                                 desktop_file=f)
  278.                     self._indexer.add("%s %s %s %s %s" % (
  279.                                 result.get_string("Exec"),
  280.                                 result.get_localestring(deskbar.gnomedesktop.KEY_NAME),
  281.                                 result.get_localestring(deskbar.gnomedesktop.KEY_COMMENT),
  282.                                 result.get_string(deskbar.gnomedesktop.KEY_NAME),
  283.                                 result.get_string(deskbar.gnomedesktop.KEY_COMMENT),
  284.                             ), match)
  285.  
  286. def get_priority_for_name(query, name):
  287.     if name.split(" ")[0].endswith(query):
  288.         return EXACT_MATCH_PRIO
  289.     else:
  290.         return EXACT_WORD_PRIO
  291.         
  292. def parse_desktop_filename(desktop, only_if_visible=True):
  293.     if desktop[0] == "/" and exists(desktop):
  294.         return parse_desktop_file(desktop, only_if_visible)
  295.             
  296.     for dir in get_xdg_data_dirs():
  297.         f = join(dir, "applications", desktop)
  298.         if exists(f):
  299.             return parse_desktop_file(f, only_if_visible)
  300.     
  301.     return None
  302.  
  303.  
  304. def parse_desktop_file(desktop, only_if_visible=True):
  305.     try:
  306.         desktop = deskbar.gnomedesktop.item_new_from_file(desktop, deskbar.gnomedesktop.LOAD_ONLY_IF_EXISTS)
  307.     except Exception, e:
  308.         print 'Couldn\'t read desktop file:%s:%s' % (desktop, e)
  309.         return None
  310.     
  311.     if desktop == None or desktop.get_entry_type() != deskbar.gnomedesktop.TYPE_APPLICATION:
  312.         return None
  313.     if desktop.get_boolean(deskbar.gnomedesktop.KEY_TERMINAL):
  314.         return None
  315.     if only_if_visible and desktop.get_boolean(deskbar.gnomedesktop.KEY_NO_DISPLAY):
  316.         return None
  317.         
  318.     return desktop
  319.