4702l1 Listing 1. GladeBase #!/usr/bin/env python """GladeBase.py This module provides base classes for Glade-derived UIs and their controllers.""" import os, gtk, gnome.ui, libglade, PathFinder class UI(libglade.GladeXML): """Base class for UIs loaded from glade.""" def __init__(self, filename, rootname, gladeDir="."): """Initialize a new instance. `filename' is the name of the .glade file containing the UI hierarchy. `rootname' is the name of the topmost widget to be loaded. `gladeDir' is the name of the directory, relative to the Python path, in which to search for `filename'.""" if gladeDir: filename = os.path.join(gladeDir, filename) self._gladePathname = PathFinder.find(filename) libglade.GladeXML.__init__(self, self._gladePathname, rootname) self.root = self.get_widget(rootname) def __getattr__(self, name): """Look up an as-yet undefined attribute, assuming it's a widget.""" result = self.get_widget(name) if result is None: raise AttributeError("Can't find widget %s in %s.\n" % (`name`, `self._gladePathname`)) # Cache the widget to speed up future lookups. If multiple # widgets in a hierarchy have the same name, the lookup # behavior is non-deterministic just as for libglade. setattr(self, name, result) return result class Controller: """Base class for all controllers of glade-derived UIs.""" def __init__(self, ui): """Initialize a new instance. `ui' is the user interface to be controlled.""" self.ui = ui self.ui.signal_autoconnect(self._getAllMethods()) def _getAllMethods(self): """Get a dictionary of all methods in self's class hierarchy.""" result = {} # Find all callable instance/class attributes. This will miss # attributes which are "interpreted" via __getattr__. By # convention such attributes should be listed in # self.__methods__. allAttrNames = self.__dict__.keys() + self._getAllClassAttributes() for name in allAttrNames: value = getattr(self, name) if callable(value): result[name] = value return result def _getAllClassAttributes(self): """Get a list of all attribute names in self's class hierarchy.""" nameSet = {} for currClass in self._getAllClasses(): nameSet.update(currClass.__dict__) result = nameSet.keys() return result def _getAllClasses(self): """Get all classes in self's heritage.""" result = [self.__class__] i = 0 while i < len(result): currClass = result[i] result.extend(list(currClass.__bases__)) i = i + 1 return result def main(): """This is a unit test which confirms that all base classes are traversed when looking up attributes.""" class BaseTest(Controller): def __init__(self, gladePath): ui = UI(gladePath, "app") Controller.__init__(self, ui) def on_exit1_activate(self, *args): gtk.mainquit() def on_new_file1_activate(self, *args): return class Test(BaseTest): def on_new_file1_activate(self, *args): return gladePath = "_test/data/ui.glade" c = Test(gladePath) print 72 * "_" print "Controller methods:" methods = c._getAllMethods() names = methods.keys() names.sort() for name in names: value = methods[name] print " %-32.32s %s" % (name, value) print 72 * "_" print "Sample UI instance attributes:" names = ["root", "new_file1", "exit1"] names.sort() for name in names: value = getattr(c.ui, name) print " %-32.32s %s" % (name, value) if __name__ == "__main__": main()