4702l3 Listing 3. GladeProjectSignals.py #!/usr/bin/env python """GladeProjectSignals.py This module helps identify signal handlers referenced in a Glade project file. This module requires Python 2.0, compiled with the Expat extension.""" from xml.dom import minidom def nodeIsElement(node, elName): """Find out whether or not a node is an element of the specified name.""" return ((node.nodeType == minidom.Node.ELEMENT_NODE) and (node.tagName == elName)) class WidgetTreeSignals: """This class represents a set of signal handlers defined in a Glade widget hierarchy.""" def __init__(self, domNode): """Initialize a new instance. `domNode' is a DOM node which describes a widget hierarchy.""" self.domNode = domNode self.name = "" self.handlers = [] self._findName() self._findHandlers() def _findName(self): """Find the name of the topmost widget defined by self's domNode.""" numNames = 0 for child in self.domNode.childNodes: if nodeIsElement(child, "name"): self.name = self._nameValue(child) numNames = numNames + 1 assert(numNames == 1), "Widget has %s names." % numNames def _findHandlers(self): """Find the widget handlers specified in self's DOM subtree.""" self._walk(self.domNode) def _walk(self, startNode): """Walk through a DOM tree. Whenever a 'signal' node is identified, record its handler name.""" if nodeIsElement(startNode, "signal"): self._processSignal(startNode) else: for child in startNode.childNodes: self._walk(child) def _processSignal(self, node): """Process a signal description node.""" for child in node.childNodes: if nodeIsElement(child, "handler"): self._processHandler(child) def _processHandler(self, node): """Process a signal handler node.""" self.handlers.append(self._nameValue(node)) def _isText(self, node): """Find out whether or not a node is a text node.""" return (node.nodeType == minidom.Node.TEXT_NODE) def _nameValue(self, node): """Get the value of a `name' node.""" numNames = 0 result = "" for child in node.childNodes: if self._isText(child): result = child.data numNames = numNames + 1 assert (numNames == 1), "Name node has %s values." % numNames return result class GladeProjectSignals: """This class extracts widget signal-handler info from a Glade design file. Given a Glade project filename, each instance of this class defines a dictionary, `widgets', of the toplevel widgets in the project file. Each dictionary key is the name of a toplevel widget or dialog. Each dictionary value is a WidgetTreeSignals instance""" def __init__(self, filename): """Initialize a new instance.""" self.pathname = filename self.doc = minidom.parse(self.pathname) self.widgets = {} self._extractWidgets() def _extractWidgets(self): """Extract toplevel widget descriptions from a Glade design file.""" design = self.doc.childNodes[0] for node in design.childNodes: if nodeIsElement(node, "widget"): widgetInfo = WidgetTreeSignals(node) self.widgets[widgetInfo.name] = widgetInfo def main(): """Module mainline (for standalone execution)""" project = GladeProjectSignals("test.glade") names = project.widgets.keys() names.sort() for widget in [project.widgets[name] for name in names]: print "Widget tree", widget.name for handler in widget.handlers: print " %s" % handler print if __name__ == "__main__": main()