def get_pixbuf(self): """ Returns pixbuf that L{get_icon} points to @return: gtk.gdk.Pixbuf """ if self.get_icon() != None: return load_icon(self.get_icon()) return None
class BeagleHandler(deskbar.interfaces.Module): INFOS = {'icon': load_icon("system-search"), "name": _("Beagle"), "description": _("Search all of your documents (using Beagle)"), 'version': VERSION, } def __init__(self): deskbar.interfaces.Module.__init__(self) def query(self, query): self._emit_query_ready(query, [BeagleMatch(name=query, priority=self.get_priority())] ) @staticmethod def has_requirements(): #FIXME: better way to detect beagle ? for dir in get_xdg_data_dirs(): if glob(join(dir, "applications", "*best.desktop")) or glob(join(dir, "applications", "*beagle-search.desktop")): return True BeagleHandler.INSTRUCTIONS = _("Beagle does not seem to be installed.") return False
class TomboyNotesModule (deskbar.interfaces.Module): INFOS = {'icon': load_icon("tomboy"), 'name': _('Tomboy Notes'), 'description': _('Search your Tomboy notes'), 'version': VERSION, } tomboy = None def __init__(self): deskbar.interfaces.Module.__init__(self) def initialize(self): TomboyNotesModule.tomboy = get_tomboy_connection() def stop(self): TomboyNotesModule.tomboy = None # This is so when Tomboy is disabled, history items won't try to connect # Otherwise, we get big DBus errors def set_enabled(self, val): if val == False: TomboyNotesModule.tomboy = None deskbar.interfaces.Module.set_enabled(self, val) # Handles the return from the Tomboy method SearchNotes # This should be called from the lambda in query so that it will get # the extra information (the query text) def handle_searchnotes( self, text, notes ): for note in notes: try: if tomboy().NoteExists(note): match = TomboyExistingNoteMatch(note) match.set_priority (self.get_priority()) self._emit_query_ready( text, [match] ) except (dbus.DBusException, dbus.exceptions.DBusException), e: LOGGER.exception(e) return
class BeagleLiveHandler(deskbar.interfaces.Module): INFOS = { 'icon': load_icon("system-search"), "name": _("Beagle Live"), "description": _("Search all of your documents (using Beagle), as you type"), 'version': VERSION, } def __init__(self): deskbar.interfaces.Module.__init__(self) self.__counter_lock = threading.Lock() self.__beagle_lock = threading.Lock() self.__snippet_lock = threading.Lock() self.__finished_lock = threading.Lock() self.__snippet_request = {} # Maps beagle.Hit to beagle.SnippetRequest # We have to store instances for each query term self._counter = {} # Count hits for each hit type self._at_max = { } # Whether we have reached the maximum for a particular hit type before self._beagle_query = {} self.__hits_added_id = {} self.__hits_finished_id = {} self.__finished = { } # Whether we got all matches from beagle for query def initialize(self): self.beagle = beagle.Client() def stop(self): self.beagle = None def query(self, qstring): self.__counter_lock.acquire() self._counter[qstring] = {} self._at_max[qstring] = {} self.__counter_lock.release() self.__finished_lock.acquire() self.__finished[qstring] = False self.__finished_lock.release() try: self.__beagle_lock.acquire() beagle_query = beagle.Query() self.__hits_added_id[qstring] = beagle_query.connect( "hits-added", self._on_hits_added, qstring) self.__hits_finished_id[qstring] = beagle_query.connect( "finished", self._on_finished, qstring) beagle_query.add_text(qstring) self._beagle_query[qstring] = beagle_query LOGGER.debug("Sending beagle query (%r) for '%s'", self._beagle_query[qstring], qstring) try: self.beagle.send_request_async(self._beagle_query[qstring]) except GError, e: LOGGER.exception(e) self._cleanup_query(qstring) finally: self.__beagle_lock.release() def _on_hits_added(self, query, response, qstring): for hit in response.get_hits(): if hit.get_type() not in TYPES: LOGGER.info("Beagle live seen an unknown type: %s", str(hit.get_type())) continue beagle_type = self._get_beagle_type(hit) if beagle_type == None: continue if beagle_type.get_has_snippet(): self._get_snippet(query, hit, qstring, beagle_type) else: self._create_match(hit, beagle_type, qstring) def _on_finished(self, query, response, qstring): LOGGER.debug("Beagle query (%r) for '%s' finished with response %r", query, qstring, response) self.__finished_lock.acquire() self.__finished[qstring] = True self.__finished_lock.release() def _on_snippet_received(self, request, response, hit, qstring, beagle_type): snippet = response.get_snippet() if snippet == None: snippet_text = None else: # Remove trailing whitespaces and escape '%' snippet_text = snippet.strip().replace("%", "%%") self._create_match(hit, beagle_type, qstring, snippet_text) def _on_snippet_closed(self, request, hit, qstring): self._cleanup_snippet(hit) self.__snippet_lock.acquire() n_snippets = len(self.__snippet_request) self.__snippet_lock.release() self.__finished_lock.acquire() finished = self.__finished[qstring] self.__finished_lock.release() # FIXME: This only works when at least one # result has a snippet, otherwise we # miss cleaning up if finished and n_snippets == 0: self._cleanup_query(qstring) self._cleanup_counter(qstring) def _cleanup_counter(self, qstring): self.__counter_lock.acquire() if qstring in self._counter: del self._counter[qstring] del self._at_max[qstring] self.__counter_lock.release() def _cleanup_snippet(self, hit): LOGGER.debug("Cleaning up hit %r", hit) self.__snippet_lock.acquire() del self.__snippet_request[hit] self.__snippet_lock.release() hit.unref() def _cleanup_query(self, qstring): LOGGER.debug("Cleaning up query for '%s'", qstring) # Remove counter for query self.__beagle_lock.acquire() # Disconnect signals, otherwise we receive late matches # when beagle found the query term in a newly indexed file beagle_query = self._beagle_query[qstring] beagle_query.disconnect(self.__hits_added_id[qstring]) beagle_query.disconnect(self.__hits_finished_id[qstring]) del self._beagle_query[qstring] del self.__hits_added_id[qstring] del self.__hits_finished_id[qstring] self.__beagle_lock.release() self.__finished_lock.acquire() del self.__finished[qstring] self.__finished_lock.release() def _get_snippet(self, query, hit, qstring, beagle_type): LOGGER.debug("Retrieving snippet for hit %r", hit) snippet_request = beagle.SnippetRequest() snippet_request.set_query(query) snippet_request.set_hit(hit) hit.ref() snippet_request.connect('response', self._on_snippet_received, hit, qstring, beagle_type) snippet_request.connect('closed', self._on_snippet_closed, hit, qstring) self.__snippet_lock.acquire() self.__snippet_request[hit] = snippet_request self.__snippet_lock.release() try: self.__beagle_lock.acquire() try: self.beagle.send_request_async(snippet_request) except GError, e: LOGGER.exception(e) self._cleanup_snippet(hit) finally: self.__beagle_lock.release() def _get_beagle_type(self, hit): """ Returns the appropriate L{BeagleType} for the given hit @type hit: beagle.Hit @return: L{BeagleType} instance """ hit_type = hit.get_type() snippet = None if hit_type in TYPES: beagle_type = TYPES[hit_type] else: LOGGER.warning("Unknown beagle match type found: %s", result["type"]) return None # Directories are Files in beagle context if hit_type == "File": filetype = hit.get_properties("beagle:FileType") if filetype != None \ and filetype[0] in BEAGLE_FILE_TYPE_TO_TYPES_MAP: beagle_type = TYPES[BEAGLE_FILE_TYPE_TO_TYPES_MAP[filetype[0]]] return beagle_type def _create_match(self, hit, beagle_type, qstring, snippet=None): # Get category cat_type = beagle_type.get_category() result = { "uri": hit.get_uri(), "type": beagle_type, "snippet": snippet, } self.__counter_lock.acquire() # Create new counter for query and type if not cat_type in self._counter[qstring]: self._counter[qstring][cat_type] = 0 # Increase counter self._counter[qstring][cat_type] += 1 if self._counter[qstring][cat_type] > MAX_RESULTS: if cat_type in self._at_max[qstring]: # We already reached the maximum before self.__counter_lock.release() return else: # We reach the maximum for the first time self._at_max[qstring][cat_type] = True self._emit_query_ready(qstring, [ BeagleSearchMatch(qstring, cat_type, beagle_type.get_hit_type()) ]) self.__counter_lock.release() return self.__counter_lock.release() self._get_properties(hit, result) self._escape_pango_markup(result, qstring) self._emit_query_ready(qstring, [ BeagleLiveMatch( result, category=cat_type, priority=self.get_priority()) ]) def _get_properties(self, hit, result): beagle_type = result["type"] name = None for prop in beagle_type.get_name_properties(): try: name = hit.get_properties( prop )[0] # get_property_one() would be cleaner, but this works around bug #330053 except: pass if name != None: result["name"] = name break if name == None: #translators: This is used for unknown values returned by beagle #translators: for example unknown email sender, or unknown note title result["name"] = _("?") for prop, keys in beagle_type.get_extra_properties().items(): val = None for key in keys: try: val = hit.get_properties( key )[0] # get_property_one() would be cleaner, but this works around bug #330053 except: pass if val != None: result[prop] = val break if val == None: #translators: This is used for unknown values returned by beagle #translators: for example unknown email sender, or unknown note title result[prop] = _("?") def _escape_pango_markup(self, result, qstring): """ Escape everything for display through pango markup, except filenames. Filenames are escaped in escaped_uri or escaped_identifier """ for key, val in result.items(): if key == "uri" or key == "identifier": result["escaped_" + key] = cgi.escape(val) elif key == "snippet": # Add the snippet, in escaped form if available if result["snippet"] != None and result["snippet"] != "": tmp = re.sub(r"<.*?>", "", result["snippet"]) tmp = re.sub(r"</.*?>", "", tmp) result["snippet"] = cgi.escape(tmp) # FIXME: re.escape too much, we only want to escape special regex chars # we should provide a convenient method for _all_ modules result["snippet"] = re.sub( re.escape(qstring), "<span weight='bold'>" + qstring + "</span>", result["snippet"], re.IGNORECASE) else: result["snippet"] = "" elif isinstance(result[key], str): result[key] = cgi.escape(val) @staticmethod def has_requirements(): # Check if we have python bindings for beagle try: import beagle except Exception, e: BeagleLiveHandler.INSTRUCTIONS = _( "Could not load beagle, libbeagle has been compiled without python bindings." ) return False # Check if beagled is running if not beagle.beagle_util_daemon_is_running(): if is_program_in_path("beagled"): BeagleLiveHandler.INSTRUCTIONS = _( "Beagle daemon is not running.") return False else: BeagleLiveHandler.INSTRUCTIONS = _( "Beagled could not be found in your $PATH.") return False else: return True
from gettext import gettext as _ from deskbar.core.Utils import load_icon CATEGORIES = { # Special categories "default" : { "name": _("Uncategorized"), "icon": load_icon("unknown"), }, "history" : { "name": _("History"), "icon": load_icon("document-open-recent"), }, # Standard handlers "documents" : { "name": _("Documents"), "icon": load_icon("empty"), }, "emails" : { "name": _("Emails"), "icon": load_icon("emblem-mail"), }, "conversations" : { "name": _("Conversations"), "icon": load_icon("system-users"), }, "files" : { "name": _("Files"), "icon": load_icon("empty"), },
class WikipediaSuggestHandler(deskbar.interfaces.Module): INFOS = {'icon': load_icon("wikipedia.png"), 'name': _("Wikipedia Suggest"), 'description': _("As you type, Wikipedia will offer suggestions."), 'version': VERSION} DEFAULT_LANG = "en" def __init__(self): deskbar.interfaces.Module.__init__(self) self._lang = None self._mateconf = GconfStore.get_instance().get_client() self._mateconf.notify_add(MATECONF_KEY, self._on_language_changed) self._set_lang() def _set_lang(self): self._lang = self._mateconf.get_string(MATECONF_KEY) if self._lang == None: localelang = self._guess_lang() self._mateconf.set_string(MATECONF_KEY, localelang) def _guess_lang(self): """ Try to guess lang """ localelang = get_locale_lang() if localelang == None: localelang = self.DEFAULT_LANG else: localelang = localelang.split("_")[0] # Check if the language is supported for name, code in LANGUAGES: if code == localelang: return localelang # Set fallback localelang = self.DEFAULT_LANG return localelang def _on_language_changed(self, client, cnxn_id, entry, data): if entry.value == None: self._set_lang() else: self._lang = entry.value.get_string() def query(self, qstring): args = {'lang': self._lang, 'search': qstring} url = WIKIPEDIA_SUGGEST_URL + '?' + urllib.urlencode(args) try: result = urllib.urlopen(url, proxies=get_proxy()) except (IOError, EOFError), msg: # Print error for debugging purposes and end querying LOGGER.error("Could not open URL %s: %s, %s" % (url, msg[0], msg[1])) return matches = [] for line in result: cols = line.strip().split("\t", 2) if len(cols) == 2: title, lang = cols matches.append( WikipediaSuggestMatch(title, lang) ) self._emit_query_ready( qstring, matches )