On Tue, 2005-10-11 at 10:04 +0200, Mikkel Kamstrup Erlandsen wrote: > > > > The concerning fact was that the window was slow to come up. Digging > > through the code I tracked this down to the signals emitted from the > > ModuleLoader. I gave them the same priority as default GTK events. > > Seemingly this was way to aggressive. Changing this to > > gobject.PRIORITY_DEFAULT_IDLE did the trick. > > > > > > Raphael: > > You modifications to my initial patch are most welcome. They work out > > fine for me... I didn't know that python had a thread safe Queue ready > > to plug in. That is a valuable trick! > > Hi ! Ok, i'm ready to put this in CVS, the idle_priority makes indeed the UI appear smoothly, all handlers are ported, i cleaned some debug messages, and added the blocking module in CVS, but it will of course not be installed (only EXTRA_DIST'ed). I also set the priority to 0 so it does not clutter testing. Now the question is: Should we release something before we integrate this and the async handler patches ? Mikkel and me thought it was a good idea, so we release often, release early. We will then merge the async module patch and async handler patch and make release again. Nigel, Mikkel is that ok ? Do we have critical things to fix before making a new release ? Raf PS. Attached is the new patch for async module, to be applied to clean CVS
Index: deskbar/applet.py =================================================================== RCS file: /cvs/gnome/deskbar-applet/deskbar/applet.py,v retrieving revision 1.13 diff -u -p -r1.13 applet.py --- deskbar/applet.py 10 Oct 2005 17:53:21 -0000 1.13 +++ deskbar/applet.py 11 Oct 2005 16:48:53 -0000 @@ -1,14 +1,21 @@ import os, time import deskbar, deskbar.deskbarentry, deskbar.about, deskbar.preferences, deskbar.applet_keybinder +from deskbar.module_list import ModuleLoader # WARNING: Load gnome.ui before gnomeapplet or we have a nasty warning. import gnome.ui import gnomeapplet, gtk, gtk.gdk, gconf +module_dirs = [deskbar.HANDLERS_DIR, "~/.gnome2/deskbar-applet"] + class DeskbarApplet: def __init__(self, applet): self.applet = applet - - self.entry = deskbar.deskbarentry.DeskbarEntry() + + self.loader = ModuleLoader (module_dirs) + self.loader.connect ("module-loaded", lambda l, mod: self.loader.initialize_module_async(mod)) + self.loader.load_all_async () + + self.entry = deskbar.deskbarentry.DeskbarEntry(self.loader) self.entry.get_evbox().connect("button-press-event", self.on_icon_button_press) self.entry.get_entry().connect("button-press-event", self.on_entry_button_press) Index: deskbar/deskbar-applet =================================================================== RCS file: /cvs/gnome/deskbar-applet/deskbar/deskbar-applet,v retrieving revision 1.6 diff -u -p -r1.6 deskbar-applet --- deskbar/deskbar-applet 6 Oct 2005 16:36:17 -0000 1.6 +++ deskbar/deskbar-applet 11 Oct 2005 16:48:53 -0000 @@ -3,7 +3,11 @@ # (C) 2005 Nigel Tao. # Licensed under the GNU GPL. -import gtk, gnomeapplet +import gtk +gtk.threads_init() + +import gnomeapplet + import getopt, sys from os.path import * @@ -18,15 +22,6 @@ if _check(name): else: print "Running installed deskbar, using normal PYTHONPATH" -# Init twisted -#from twisted.python import threadable -#threadable.init() - -#from twisted.internet import gtk2reactor -#gtk2reactor.install() - -#from twisted.internet import reactor - # Now the path is set, import our applet import deskbar.applet @@ -36,18 +31,17 @@ def applet_factory(applet, iid): # Return a standalone window that holds the applet def build_window(): - win = gtk.Window(gtk.WINDOW_TOPLEVEL) - win.set_title("Deskbar Applet") - #win.connect("destroy", lambda x: reactor.stop()) - win.connect("destroy", gtk.main_quit) + app = gtk.Window(gtk.WINDOW_TOPLEVEL) + app.set_title("Deskbar Applet") + app.connect("destroy", gtk.main_quit) applet = gnomeapplet.Applet() applet_factory(applet, None) - applet.reparent(win) + applet.reparent(app) - win.show_all() + app.show_all() - return win + return app def usage(): @@ -61,7 +55,7 @@ OPTIONS: """ sys.exit() -if __name__ == "__main__": +if __name__ == "__main__": standalone = False try: @@ -81,8 +75,10 @@ if __name__ == "__main__": standalone = True if standalone: + gtk.threads_enter() build_window() gtk.main() + gtk.threads_leave() else: gnomeapplet.bonobo_factory( "OAFIID:Deskbar_Applet_Factory", @@ -90,6 +86,3 @@ if __name__ == "__main__": "deskbar-applet", "0", applet_factory) - - #reactor.suggestThreadPoolSize(3) - #reactor.run() Index: deskbar/deskbarentry.py =================================================================== RCS file: /cvs/gnome/deskbar-applet/deskbar/deskbarentry.py,v retrieving revision 1.11 diff -u -p -r1.11 deskbarentry.py --- deskbar/deskbarentry.py 10 Oct 2005 17:53:21 -0000 1.11 +++ deskbar/deskbarentry.py 11 Oct 2005 16:48:53 -0000 @@ -3,14 +3,10 @@ import cgi import deskbar import deskbar.iconentry +from deskbar.module_list import ModuleList import gtk, gobject -from module_list import ModuleList -from module_list import ModuleLoader -module_dirs = [deskbar.HANDLERS_DIR, "~/.gnome2/deskbar-applet"] - - # The liststore columns HANDLER_PRIO_COL = 0 MATCH_PRIO_COL = 1 @@ -31,12 +27,13 @@ MOVE_UP = -1 MOVE_DOWN = +1 class DeskbarEntry(deskbar.iconentry.IconEntry): - def __init__(self): + def __init__(self, loader): deskbar.iconentry.IconEntry.__init__(self) # Set up the Handlers self._handlers = ModuleList () - self._load_handlers() + loader.connect ("module-loaded", self._handlers.update_row_cb) + loader.connect ("module-initialized", self._handlers.module_toggled_cb) self._completion_model = None self._selected_match_index = -1 @@ -103,12 +100,7 @@ class DeskbarEntry(deskbar.iconentry.Ico def get_history(self): return self._history - - def _load_handlers(self): - loader = ModuleLoader (self._handlers, module_dirs, ".py") - loader.load_all () - return - + def _on_sort_matches(self, treemodel, iter1, iter2): # First compare global handler priority diff = treemodel[iter1][HANDLER_PRIO_COL] - treemodel[iter2][HANDLER_PRIO_COL] Index: deskbar/handler.py =================================================================== RCS file: /cvs/gnome/deskbar-applet/deskbar/handler.py,v retrieving revision 1.1 diff -u -p -r1.1 handler.py --- deskbar/handler.py 6 Oct 2005 14:01:06 -0000 1.1 +++ deskbar/handler.py 11 Oct 2005 16:48:53 -0000 @@ -73,10 +73,14 @@ class Match: class Handler: def __init__(self, iconfile): + """ + The constructor of the Handler should generally not block. + Heavy duty tasks such as indexing should be done in the initialize() method. + """ # We load the icon file, and if it fails load an empty one try: - self._icon = gtk.gdk.pixbuf_new_from_file_at_size(join(deskbar.ART_DATA_DIR, iconfile), -1, deskbar.ICON_SIZE) - except gobject.GError: + self._icon = gtk.gdk.pixbuf_new_from_file_at_size(join(deskbar.ART_DATA_DIR, iconfile), deskbar.ICON_SIZE, deskbar.ICON_SIZE) + except Exception: self._icon = None def get_priority(self): @@ -91,6 +95,25 @@ class Handler: Returns None if there is no associated icon. """ return self._icon + + def initialize(self): + """ + The constructor of the Handler should generally not block. + Heavy duty tasks such as indexing should be done in this method. + + Handler.initialize() is guarantied to be called before the handler + is queried. + """ + pass + + def stop(self): + """ + If the handler needs any cleaning up before it is unloaded, do it here. + + Handler.stop() is guarantied to be called before the handler is + unloaded. + """ + pass def query(self, query, max=5): """ Index: deskbar/module_list.py =================================================================== RCS file: /cvs/gnome/deskbar-applet/deskbar/module_list.py,v retrieving revision 1.3 diff -u -p -r1.3 module_list.py --- deskbar/module_list.py 9 Oct 2005 20:58:36 -0000 1.3 +++ deskbar/module_list.py 11 Oct 2005 16:48:53 -0000 @@ -5,23 +5,27 @@ import sys import pydoc from os.path import join, basename, normpath, abspath from os.path import split, expanduser, exists, isfile, dirname +from threading import Thread +import Queue class ModuleContext: """A generic wrapper for any object stored in a ModuleList. settings is unused at the moment. - """ - def __init__ (self, icon, enabled, name, module, settings, filename): + """ + + def __init__ (self, icon, enabled, module, settings, filename, name, exported_class): """The icon should be a gtk.gdk.Pixbuf""" self.icon = icon self.enabled = enabled - self.name = name self.module = module self.settings = settings self.filename = filename + self.name = name + self.exported_class = exported_class class ModuleListIter : - """An iter type to iterate over the modules contexts in a ModuleList object. + """An iter type to iterate over the of *enabled* module contexts in a ModuleList object. This object is (typically) not used directly. See the documentation for ModuleList. For documentation on iters see: http://docs.python.org/lib/typeiter.html @@ -37,15 +41,12 @@ class ModuleListIter : return self def next (self): - """Return the next module in the ModuleList.""" + """Return the next *enabled* module in the ModuleList.""" try: - mod = ModuleContext ( self.owner.get_value (self.owner_iter, self.owner.ICON_COL), - self.owner.get_value (self.owner_iter, self.owner.ENABLED_COL), - self.owner.get_value (self.owner_iter, self.owner.NAME_COL), - self.owner.get_value (self.owner_iter, self.owner.MODULE_COL), - self.owner.get_value (self.owner_iter, self.owner.SETTINGS_COL), - self.owner.get_value (self.owner_iter, self.owner.FILENAME_COL)) + mod = self.owner.get_context_from_iter (self.owner_iter) self.owner_iter = self.owner.iter_next (self.owner_iter) + if not mod.enabled: + return self.next() except TypeError: raise StopIteration return mod @@ -58,7 +59,7 @@ class ModuleList (gtk.ListStore): for modctx in modlist: do_something (modctx) - From this perspective the ModuleList stores ModuleContext (it actually doesnt), + From this perspective the ModuleList stores ModuleContexts (it actually doesnt), so to utilize the modules you'll have to acces modctx.module. Note that the gtk.ListView extends the following classes: @@ -68,32 +69,93 @@ class ModuleList (gtk.ListStore): http://www.pygtk.org/pygtk2reference/class-gtkliststore.html Note that """ + ICON_COL = 0 ENABLED_COL = 1 - NAME_COL = 2 - MODULE_COL = 3 - SETTINGS_COL = 4 - FILENAME_COL = 5 + MODULE_COL = 2 + SETTINGS_COL = 3 + FILENAME_COL = 4 + NAME_COL = 5 + EXP_CLASS_COL = 6 def __init__ (self): gtk.ListStore.__init__ (self, gtk.gdk.Pixbuf, bool, - gobject.TYPE_STRING, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, + gobject.TYPE_STRING, + gobject.TYPE_STRING, gobject.TYPE_STRING) def __iter__ (self): return ModuleListIter (self) - def add (self, mod_context): - it = self.append () - self.set (it, self.ICON_COL, mod_context.icon) - self.set (it, self.ENABLED_COL, mod_context.enabled) - self.set (it, self.NAME_COL, mod_context.name) - self.set (it, self.MODULE_COL, mod_context.module) - self.set (it, self.SETTINGS_COL, mod_context.settings) - self.set (it, self.FILENAME_COL, mod_context.filename) + def add (self, context): + """Appends the module context to the list.""" + self.update_row (context, iter) + + + def get_iter_from_context (self, modctx): + """Returns a gtk.TreeIter pointing to the row containing the filename + modctx.filename. This should be uniqualy determined by the context. + + If the filename is not found return None. + + INVARIANT: ModuleContexts are uniquely determined by their .filename + """ + + iter = self.get_iter_first () + while (iter is not None): + if self.get_value (iter, self.FILENAME_COL) == modctx.filename: + break + iter = self.iter_next (iter) + return iter + + def get_context_from_iter (self, iter): + """Return a ModuleContext representing the row pointed to by iter.""" + modctx = ModuleContext ( self.get_value (iter, self.ICON_COL), + self.get_value (iter, self.ENABLED_COL), + self.get_value (iter, self.MODULE_COL), + self.get_value (iter, self.SETTINGS_COL), + self.get_value (iter, self.FILENAME_COL), + self.get_value (iter, self.NAME_COL), + self.get_value (iter, self.EXP_CLASS_COL)) + return modctx + + def update_row (self, context, iter=None): + """If iter is set this method updates the row pointed to by iter with the + values of context. + + If iter is not set it will try to obtain an iter pointing + to the row containg context.filename. If there's no such row, it will append it. + """ + + if (iter is None): + iter = self.get_iter_from_context (context) + if (iter is None): + iter = self.append () + + self.set_value(iter, self.ICON_COL, context.icon) + self.set_value(iter, self.ENABLED_COL, context.enabled) + self.set_value(iter, self.MODULE_COL, context.module) + self.set_value(iter, self.SETTINGS_COL, context.settings) + self.set_value(iter, self.FILENAME_COL, context.filename) + self.set_value(iter, self.NAME_COL, context.name) + self.set_value(iter, self.EXP_CLASS_COL, context.exported_class) + + def update_row_cb (self, sender, context, iter=None): + """ + Callback for updating the row containing context. + If iter is set the row to which it points to will be + updated with the context. + """ + self.update_row (context, iter) + + def module_toggled_cb (self, sender, context): + """ + Callback to toggle the enabled state of the context. + """ + self.set_value(self.get_iter_from_context (context), self.ENABLED_COL, context.enabled) class ModuleListView (gtk.TreeView): """A versatile list widget that displays the contents of a ModuleList. @@ -107,6 +169,11 @@ class ModuleListView (gtk.TreeView): This will construct a list showing the module names and a checkbox on whether or not they are enabled. """ + + __gsignals__ = { + "row-toggled" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, [gobject.TYPE_PYOBJECT]) + } + def __init__ (self, model, columns): gtk.TreeView.__init__ (self, model) @@ -119,7 +186,7 @@ class ModuleListView (gtk.TreeView): if (model.ENABLED_COL in columns): cell_enabled = gtk.CellRendererToggle () cell_enabled.set_property ("activatable", True) - cell_enabled.connect('toggled', self.toggle_enable, model) + cell_enabled.connect('toggled', self.emit_row_toggled, model) self.column_enabled = gtk.TreeViewColumn ("Enabled", cell_enabled, active=model.ENABLED_COL) if (model.NAME_COL in columns): @@ -139,30 +206,64 @@ class ModuleListView (gtk.TreeView): self.set_headers_visible(True) - def toggle_enable (self, cell, path, model): - iter = model.get_iter(path) - model.set_value(iter, model.ENABLED_COL, not cell.get_active()) - for mod in model: - print mod.name +" is enabled: " + str(mod.enabled) - -class ModuleLoader: + def emit_row_toggled (self, cell, path, model): + """Callback for the toggle buttons in the ModuleList.ENABLED_COL. + Emits a 'row-toggled' signal passing the context in the row as argument.""" + self.emit ("row-toggled", model.get_context_from_iter (model.get_iter(path))) + +class ModuleLoader (gobject.GObject): """An auxilary class to ModuleList. Create an instance of ModuleLoader by specifying the which directories to search and what extension to accept. The load_all() method will load all qualified modules into the ModuleList specified in the constructor. + + Most methods have a _async variant. These methods emits signals that is handled + by the *main* thread. This ensures that locking mechanisms are unlikely to be + needed. + + Hint: If you pass None as the dirs argument the ModuleLoader will not search + for modules at all. This is useful if you want to reload a single module for + which you know the path. + + Important: Remember to do gtk.gdk.threads_init() or gobject.threads_init() before + using any of the _async methods or else it WON'T WORK. Caveat emptor! """ - def __init__ (self, modlist, dirs, extension=".py"): - """modlist: The ModuleList to store all succesfully loaded modules + + __gsignals__ = { + "module-loaded" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, [gobject.TYPE_PYOBJECT]), + "module-initialized" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, [gobject.TYPE_PYOBJECT]), + "module-stopped" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, [gobject.TYPE_PYOBJECT]) + } + + def __init__ (self, dirs, extension=".py"): + """ dirs: A list of directories to search. Relative pathnames and paths - containing ~ will be expanded. + containing ~ will be expanded. If dirs is None the + ModuleLoader will not search for modules. extension: What extension should this ModuleLoader accept (string). """ - self.modlist = modlist - self.dirs = map (lambda s: abspath(expanduser(s)), dirs) + gobject.GObject.__init__ (self) self.ext = extension - self.filelist = self.build_filelist () - - + if (dirs): + self.dirs = map (lambda s: abspath(expanduser(s)), dirs) + self.filelist = self.build_filelist () + else: + self.dirs = None + self.filelist = [] + + self.task_queue = Queue.Queue(0) + thread = Thread(None, self.consume_queue) + # WE don't want the queue thread to prevent us from exiting + thread.setDaemon(True) + thread.start() + + def consume_queue(self): + while True: + try: + self.task_queue.get() () + except Exception, msg: + print 'Error:consume_queue:Got an error while processing item:', msg + def build_filelist (self): """Returns a list containing the filenames of all qualified modules. This method is automatically invoked by the constructor. @@ -179,21 +280,12 @@ class ModuleLoader: def is_module (self, filename): """Tests whether the filename has the appropriate extension.""" - if (filename[-len(self.ext):] == self.ext): - return True - return False - - def load_all (self): - """Tries to load all qualified modules detected by the ModuleLoader. - All succesfully loaded modules are stored in the ModuleList. - """ - for f in self.filelist: - self.load (f) - - def load (self, filename): - """Tries to load the specified file as a module and stores it in the ModuleList.""" + return (filename[-len(self.ext):] == self.ext) + + def import_module (self, filename): + """Tries to import the specified file. Returns the python module on succes. + Primarily for internal use.""" try: - print "Importing %s" % filename mod = pydoc.importfile (filename) except IOError, err: print >> sys.stderr, "Error loading the file: %s\nThe file probably doesn't exist." % filename @@ -203,7 +295,7 @@ class ModuleLoader: print >> sys.stderr, "Unknown error loading the file: %s." % filename print >> sys.stderr, str(err) return - + try: if (mod.EXPORTED_CLASS): pass if (mod.NAME): pass @@ -213,46 +305,139 @@ class ModuleLoader: return if mod.EXPORTED_CLASS == None: - print >> sys.stderr, "The file %s decided to not load itself: %s" % (mod.NAME, filename) + print >> sys.stderr, "***" + print >> sys.stderr, "*** The file %s decided to not load itself: %s" % (mod.NAME, filename) + print >> sys.stderr, "***" return - + try: - mod_init = getattr (mod, mod.EXPORTED_CLASS) + if (getattr(mod, mod.EXPORTED_CLASS).initialize) : pass except AttributeError: - print >> sys.stderr, "Class %s not found in file %s. Skipping." % (mod.EXPORTED_CLASS, filename) + print >> sys.stderr, "Class %s in file %s does not have an initialize(self) method. Skipping." % (mod.EXPORTED_CLASS, filename) return - - try: - mod_instance = mod_init() - except Exception, err: - print >> sys.stderr, "Error in file: %s" % filename - print >> sys.stderr, "There was an error initializing the class: %s" % str(mod_init) - print >> sys.stderr, str(err) + + return mod + + def load_all (self): + """Tries to load all qualified modules detected by the ModuleLoader. + Each time a module is loaded it will emit a 'module-loaded' signal + passing a corresponding module context. + """ + if self.dirs is None: + print >> sys.stderr, "The ModuleLoader at %s has no filelist!" % str(id(self)) + print >> sys.stderr, "It was probably initialized with dirs=None." return - - context = ModuleContext (None, True, mod.NAME, mod_instance, None, filename) - self.modlist.add(context) + for f in self.filelist: + self.load (f) + + def load (self, filename): + """Loads the given file as a module and emits a 'module-loaded' signal + passing a corresponding ModuleContext as argument. + + Returns the context as added to the list. + """ + mod = self.import_module (filename) + if mod is None: + return + + print "Loading module '%s' from file %s." % (mod.NAME, filename) + mod_instance = getattr (mod, mod.EXPORTED_CLASS) () + context = ModuleContext (mod_instance.get_icon(), False, mod_instance, + None, filename, mod.NAME, mod.EXPORTED_CLASS) + + gobject.idle_add (self.emit, "module-loaded", context) + + return context + + def initialize_module (self, context): + """ + Initializes the module in the given context. Emits a 'module-initialized' signal + when done, passing the (now enabled) contextas argument. + """ + + print "Initializing '%s'" % context.name + context.module.initialize () + + context.enabled = True + gobject.idle_add (self.emit, "module-initialized", context) + + def stop_module (self, context): + """ + Stops the module an sets context.enabled = False. Furthermore the context.module + instance is also set to None. Emits a 'context-stopped' signal when done passing + the stopped context as argument. + """ + + print "Stopping '%s'" % context.name + context.module.stop () + + context.enabled = False + context.module = None + gobject.idle_add (self.emit, "module-stopped", context) + + def load_all_async (self): + """ + Same as load_all() except the loading is done in a separate thread. + """ + self.task_queue.put(self.load_all) + + def load_async (self, filename): + """ + Invokes load() in a new thread. + """ + self.task_queue.put( lambda: self.load(filename) ) + + def initialize_module_async (self, context): + """ + Invokes initialize_module in a new thread. + """ + self.task_queue.put( lambda: self.initialize_module(context) ) + + def stop_module_async (self, context): + """ + Invokes stop_module in a new thread. + """ + self.task_queue.put( lambda: self.stop_module(context) ) + +def toggle_module (sender, context, ml): + """Test function""" + if (context.enabled): + ml.stop_module_async (context) + else: + ml.initialize_module_async (context) + if __name__ == "__main__": - """A test suite for the Module* classes. Run from top level dir, + + """A test suite for the Module* classes. Run from top level dir, ie. from deskbar-applet/ run 'python deskbar/module_list.py'.""" + gtk.threads_init() + name = join(dirname(__file__), '..') print 'Changing PYTHONPATH' sys.path.insert(0, abspath(name)) l = ModuleList () - ml = ModuleLoader (l, ["deskbar/handlers"], ".py") + ml = ModuleLoader (["deskbar/handlers"], ".py") + ml.connect ("module-loaded", l.update_row_cb) + ml.connect ("module-initialized", l.module_toggled_cb) + ml.connect ("module-stopped", l.module_toggled_cb) # Load all or just the directories handler. Uncomment to your liking - #ml.load_all () - ml.load (abspath(expanduser("deskbar/handlers/directories.py"))) + ml.load_all_async () + #ml.load_async (abspath(expanduser("deskbar/testmod.py"))) + lw = ModuleListView (l, [ModuleList.FILENAME_COL, ModuleList.NAME_COL, ModuleList.ENABLED_COL]) + lw.connect ("row-toggled", toggle_module, ml) + win = gtk.Window () win.connect ("destroy", gtk.main_quit) win.add (lw) win.show () lw.show () - + + gtk.threads_enter() gtk.main () + gtk.threads_leave() Index: deskbar/handlers/Makefile.am =================================================================== RCS file: /cvs/gnome/deskbar-applet/deskbar/handlers/Makefile.am,v retrieving revision 1.4 diff -u -p -r1.4 Makefile.am --- deskbar/handlers/Makefile.am 7 Oct 2005 19:21:53 -0000 1.4 +++ deskbar/handlers/Makefile.am 11 Oct 2005 16:48:53 -0000 @@ -11,3 +11,6 @@ deskbar_handlers_PYTHON = \ programs.py \ pathprograms.py \ web_address.py + +EXTRA_DIST = \ + debug-blockinginit.py Index: deskbar/handlers/debug-blockinginit.py =================================================================== RCS file: deskbar/handlers/debug-blockinginit.py diff -N deskbar/handlers/debug-blockinginit.py --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ deskbar/handlers/debug-blockinginit.py 11 Oct 2005 16:48:53 -0000 @@ -0,0 +1,38 @@ +from time import sleep +from handler import Handler +from handler import Match + +NAME = "Debug: Blocking Init Module" +EXPORTED_CLASS = "DebugBlockingInitModule" + +INIT_TIME = 5 + +class DebugBlockingInitMatch(Match): + def __init__(self, handler, name, icon=None): + Match.__init__ (self, handler, name) + + def get_verb(self): + return "%(name)s - %(text)s" + + def action(self, text=None): + pass + +class DebugBlockingInitModule(Handler): + def __init__ (self): + Handler.__init__ (self, None) + + def initialize (self): + print NAME + " initializing ... This will block for %s seconds." % INIT_TIME + for i in range(INIT_TIME): + print (i+1)*"." + sleep (1) + + def query (self, qstring, max): + if max > 0: + return [DebugBlockingInitMatch(self, "TestMatch")] + else: + return [] + + def get_priority(self): + return 0 + Index: deskbar/handlers/epiphany.py =================================================================== RCS file: /cvs/gnome/deskbar-applet/deskbar/handlers/epiphany.py,v retrieving revision 1.13 diff -u -p -r1.13 epiphany.py --- deskbar/handlers/epiphany.py 10 Oct 2005 18:15:18 -0000 1.13 +++ deskbar/handlers/epiphany.py 11 Oct 2005 16:48:53 -0000 @@ -50,7 +50,8 @@ class EpiphanySmartMatch(EpiphanyMatch): class EpiphanyHandler(deskbar.handler.Handler): def __init__(self): deskbar.handler.Handler.__init__(self, "web-bookmark.png") - + + def initialize(self): parser = EpiphanyBookmarksParser(self) self._indexer = parser.get_indexer() self._smart_bookmarks = parser.get_smart_bookmarks() Index: deskbar/handlers/galago.py =================================================================== RCS file: /cvs/gnome/deskbar-applet/deskbar/handlers/galago.py,v retrieving revision 1.2 diff -u -p -r1.2 galago.py --- deskbar/handlers/galago.py 6 Oct 2005 14:01:06 -0000 1.2 +++ deskbar/handlers/galago.py 11 Oct 2005 16:48:53 -0000 @@ -4,8 +4,12 @@ import gnomevfs import deskbar, deskbar.indexer import deskbar.handler -EXPORTED_CLASS = "GalagoHandler" -NAME = _("Email and Address Book") +#EXPORTED_CLASS = "GalagoHandler" +#NAME = _("Email and Address Book") + +# FIXME: Waiting for python bindings of galago. +EXPORTED_CLASS = None +NAME = "Waiting for python bindings of galago. Should allow to send IM by typing name." PRIORITY = 150 @@ -22,18 +26,17 @@ class GalagoMatch(deskbar.handler.Match) def get_verb(self): return _("Send Email to <b>%(name)s</b>") - - class GalagoHandler(deskbar.handler.Handler): def __init__(self): - deskbar.handler.Handler.__init__(self, "mail.png") - + deskbar.handler.Handler.__init__(self, "mail.png") self._indexer = deskbar.indexer.Index() - + + def initialize(self): # FIXME: Dummy entries - self._indexer.add("William Gates III <billg microsoft com>", GalagoMatch(self, "William Gates III", "billg microsoft com")) - self._indexer.add("Steve Ballmer <steve microsoft com>", GalagoMatch(self, "Steve Ballmer", "steve microsoft com")) - self._indexer.add("Bill Joy <bjoy sun com>", GalagoMatch(self, "Bill Joy", "bjoy sun com")) + #self._indexer.add("William Gates III <billg microsoft com>", GalagoMatch(self, "William Gates III", "billg microsoft com")) + #self._indexer.add("Steve Ballmer <steve microsoft com>", GalagoMatch(self, "Steve Ballmer", "steve microsoft com")) + #self._indexer.add("Bill Joy <bjoy sun com>", GalagoMatch(self, "Bill Joy", "bjoy sun com")) + pass def get_priority(self): return PRIORITY Index: deskbar/handlers/gtkbookmarks.py =================================================================== RCS file: /cvs/gnome/deskbar-applet/deskbar/handlers/gtkbookmarks.py,v retrieving revision 1.4 diff -u -p -r1.4 gtkbookmarks.py --- deskbar/handlers/gtkbookmarks.py 6 Oct 2005 14:01:06 -0000 1.4 +++ deskbar/handlers/gtkbookmarks.py 11 Oct 2005 16:48:53 -0000 @@ -27,10 +27,10 @@ class GtkBookmarkHandler(deskbar.handler def __init__(self): deskbar.handler.Handler.__init__(self, "folder-bookmark.png") - print 'Starting .gtkbookmarks file indexation' self._locations = {} + + def initialize(self): self._scan_bookmarks_files() - print '\tDone !' def get_priority(self): return PRIORITY Index: deskbar/handlers/mozilla.py =================================================================== RCS file: /cvs/gnome/deskbar-applet/deskbar/handlers/mozilla.py,v retrieving revision 1.13 diff -u -p -r1.13 mozilla.py --- deskbar/handlers/mozilla.py 10 Oct 2005 18:15:18 -0000 1.13 +++ deskbar/handlers/mozilla.py 11 Oct 2005 16:48:53 -0000 @@ -66,6 +66,10 @@ class MozillaHandler(deskbar.handler.Han def __init__(self): deskbar.handler.Handler.__init__(self, "web-bookmark.png") + self._indexer = None + self._smart_bookmarks = None + + def initialize(self): parser = MozillaBookmarksParser(self) self._indexer = parser.get_indexer() @@ -108,13 +112,11 @@ class MozillaBookmarksParser(HTMLParser. self._indexer = deskbar.indexer.Index() - print 'Starting mozilla/ff bookmarks indexation' if USING_FIREFOX: self._index_firefox() else: self._index_mozilla() self.close() - print '\tDone !' def get_indexer(self): """ Index: deskbar/handlers/networkplaces.py =================================================================== RCS file: /cvs/gnome/deskbar-applet/deskbar/handlers/networkplaces.py,v retrieving revision 1.1 diff -u -p -r1.1 networkplaces.py --- deskbar/handlers/networkplaces.py 7 Oct 2005 19:54:45 -0000 1.1 +++ deskbar/handlers/networkplaces.py 11 Oct 2005 16:48:53 -0000 @@ -8,7 +8,6 @@ NAME = _("Network Places") PRIORITY = 150 -GCONF_CLIENT = gconf.client_get_default() NETWORK_PLACES_GCONF = '/desktop/gnome/connected_servers' icon_theme = gtk.icon_theme_get_default() @@ -30,10 +29,10 @@ class NetworkPlacesHandler(deskbar.handl def __init__(self): deskbar.handler.Handler.__init__(self, "folder-bookmark.png") - print 'Starting Network places file indexation' self._indexer = deskbar.indexer.Index() + + def initialize(self): self._scan_network_places() - print '\tDone !' def get_priority(self): return PRIORITY @@ -42,18 +41,19 @@ class NetworkPlacesHandler(deskbar.handl return self._indexer.look_up(query)[:max] def _scan_network_places(self): - if not GCONF_CLIENT.dir_exists(NETWORK_PLACES_GCONF): + client = gconf.client_get_default() + if not client.dir_exists(NETWORK_PLACES_GCONF): return - - dirs = GCONF_CLIENT.all_dirs(NETWORK_PLACES_GCONF) + + dirs = client.all_dirs(NETWORK_PLACES_GCONF) for place in dirs: try: - name = GCONF_CLIENT.get_string(place+"/display_name") - uri = GCONF_CLIENT.get_string(place+"/uri") + name = client.get_string(place+"/display_name") + uri = client.get_string(place+"/uri") pixbuf = None try: - icon = GCONF_CLIENT.get_string(place+"/icon") + icon = client.get_string(place+"/icon") pixbuf = icon_theme.load_icon(icon, deskbar.ICON_SIZE, gtk.ICON_LOOKUP_USE_BUILTIN) except Exception, msg: print 'Error:_scan_network_places:Cannot retreive icon:', msg Index: deskbar/handlers/pathprograms.py =================================================================== RCS file: /cvs/gnome/deskbar-applet/deskbar/handlers/pathprograms.py,v retrieving revision 1.2 diff -u -p -r1.2 pathprograms.py --- deskbar/handlers/pathprograms.py 9 Oct 2005 20:14:21 -0000 1.2 +++ deskbar/handlers/pathprograms.py 11 Oct 2005 16:48:53 -0000 @@ -37,10 +37,10 @@ class PathProgramsHandler(deskbar.handle deskbar.handler.Handler.__init__(self, "generic.png") self._programs = {} - print 'Starting PATH programs indexation' + + def initialize(self): self._desktop_programs = self._scan_desktop_files() self._scan_path() - print '\tDone !' def get_priority(self): return PRIORITY Index: deskbar/handlers/programs.py =================================================================== RCS file: /cvs/gnome/deskbar-applet/deskbar/handlers/programs.py,v retrieving revision 1.13 diff -u -p -r1.13 programs.py --- deskbar/handlers/programs.py 9 Oct 2005 23:38:46 -0000 1.13 +++ deskbar/handlers/programs.py 11 Oct 2005 16:48:53 -0000 @@ -76,9 +76,9 @@ class ProgramsHandler(deskbar.handler.Ha deskbar.handler.Handler.__init__(self, "generic.png") self._indexer = deskbar.indexer.Index() - print 'Starting .desktop file indexation' + + def initialize(self): self._scan_desktop_files() - print '\tDone !' def get_priority(self): return PRIORITY
Attachment:
signature.asc
Description: This is a digitally signed message part