thomasvs - in flumotion/trunk: . flumotion/ui

flumotion-commit at lists.fluendo.com flumotion-commit at lists.fluendo.com
Mon Feb 26 22:45:09 CET 2007


Author: thomasvs
Date: Mon Feb 26 22:45:01 2007
New Revision: 4527

Modified:
   flumotion/trunk/ChangeLog
   flumotion/trunk/flumotion/ui/glade.py
Log:
	* flumotion/ui/glade.py:
	  Some easy refactoring.  Create a common GladeBacked class to
	  avoid repeating and diverging code.  Remove an experimental
	  generator method that I can't find any callers of.
	  Document and comment.



Modified: flumotion/trunk/ChangeLog
==============================================================================
--- flumotion/trunk/ChangeLog	(original)
+++ flumotion/trunk/ChangeLog	Mon Feb 26 22:45:01 2007
@@ -1,3 +1,11 @@
+2007-02-26  Thomas Vander Stichele  <thomas at apestaart dot org>
+
+	* flumotion/ui/glade.py:
+	  Some easy refactoring.  Create a common GladeBacked class to
+	  avoid repeating and diverging code.  Remove an experimental
+	  generator method that I can't find any callers of.
+	  Document and comment.
+
 2007-02-23  Thomas Vander Stichele  <thomas at apestaart dot org>
 
 	* data/Makefile.am:

Modified: flumotion/trunk/flumotion/ui/glade.py
==============================================================================
--- flumotion/trunk/flumotion/ui/glade.py	(original)
+++ flumotion/trunk/flumotion/ui/glade.py	Mon Feb 26 22:45:01 2007
@@ -31,6 +31,7 @@
 from flumotion.common import log, pygobject
 
 
+# FIXME: what does this mean ?
 # proc := module1.module2.moduleN.proc1().maybe_another_proc()
 #  -> eval proc1().maybe_another_proc() in module1.module2.moduleN
 def flumotion_glade_custom_handler(xml, proc, name, *args):
@@ -64,30 +65,37 @@
     w.set_name(name)
     w.show()
     return w
+# FIXME: what does this do ?
 gtk.glade.set_custom_handler(flumotion_glade_custom_handler)
 
 
-class GladeWidget(gtk.VBox):
-    '''
-    Base class for composite widgets backed by glade interface definitions.
-
-    Example:
-    class MyWidget(GladeWidget):
-        glade_file = 'my_glade_file.glade'
-        ...
-    gobject.type_register(MyWidget)
+class GladeBacked:
+    """
+    Base class for objects backed by glade interface definitions.
+    The glade file should have exactly one Window.
 
-    Remember to chain up if you customize __init__().
-    '''
-        
+    @ivar glade_dir:      directory where the glade file is stored
+    @type glade_dir:      str
+    @ivar glade_file:     filename of glade file containing the interface
+    @type glade_file:     str
+    @ivar glade_typedict: GTK widget class name -> replacement widget class
+                          see L{flumotion.ui.fgtk.WidgetMapping}
+    @type glade_typedict: dict of str -> class
+    @ivar widgets:        widget name -> Widget
+    @type widgets:        str -> gtk.Widget
+    """
     glade_dir = configure.gladedir
     glade_file = None
     glade_typedict = None
+    widgets = None
+
+    _window = None # the gtk.Window of the glade file
 
     def __init__(self):
-        gtk.VBox.__init__(self)
+        self.widgets = {}
         try:
-            assert self.glade_file
+            assert self.glade_file, "%s.glade_file should be set" % \
+                self.__class__
             file = os.path.join(self.glade_dir, self.glade_file)
             if self.glade_typedict:
                 wtree = gtk.glade.XML(file, typedict=self.glade_typedict)
@@ -99,30 +107,61 @@
             raise RuntimeError('Failed to load file %s from directory %s: %s'
                                % (self.glade_file, self.glade_dir, msg))
 
-        win = None
         for widget in wtree.get_widget_prefix(''):
             wname = widget.get_name()
             if isinstance(widget, gtk.Window):
-                assert win == None
-                win = widget
+                assert self._window == None, \
+                    "glade file %s has more than one Window" % self.glade_file
+                self._window = widget
                 continue
+
+            assert not self.widgets.has_key(wname), \
+                "There is already a widget called %s" % wname
+
+            self.widgets[wname] = widget
             
-            if hasattr(self, wname) and getattr(self, wname):
-                raise AssertionError(
-                    "There is already an attribute called %s in %r" %
-                    (wname, self))
-            setattr(self, wname, widget)
-
-        assert win != None
-        w = win.get_child()
-        win.remove(w)
-        self.add(w)
-        win.destroy()
+        assert self._window != None, \
+            "glade file %s has no Window" % self.glade_file
+
+        # connect all signals
         wtree.signal_autoconnect(self)
-pygobject.type_register(GladeWidget)
 
+class GladeWidget(gtk.VBox, GladeBacked):
+    '''
+    Base class for composite widgets backed by glade interface definitions.
+
+    The Window contents will be reparented to ourselves.
+    All widgets inside the Window will be available as attributes on the
+    object (dashes will be replaced with underscores).
+    
+    Example:
+    class MyWidget(GladeWidget):
+        glade_file = 'my_glade_file.glade'
+        ...
+    gobject.type_register(MyWidget)
+
+    Remember to chain up if you customize __init__().
+
+    '''
+    def __init__(self):
+        GladeBacked.__init__(self)
+        gtk.VBox.__init__(self)
+            
+        for name, widget in self.widgets.items():
+            # translate - to _ so we can access them as attributes
+            if name.find('-') > -1:
+                name = "_".join(name.split('-'))
+            setattr(self, name, widget)
+
+        # we reparent the contents of the window to ourselves
+        w = self._window.get_child()
+        self._window.remove(w)
+        self.add(w)
+        self._window.destroy()
+        self._window = None
+pygobject.type_register(GladeWidget)
 
-class GladeWindow(gobject.GObject):
+class GladeWindow(gobject.GObject, GladeBacked):
     """
     Base class for dialogs or windows backed by glade interface definitions.
 
@@ -135,47 +174,23 @@
     does *not* descend from GtkWindow, so you can't treat the resulting object
     as a GtkWindow. The show, hide, destroy, and present methods are provided as
     convenience wrappers.
-    """
 
-    glade_dir = configure.gladedir
-    glade_file = None
-    glade_typedict = None
+    @ivar window: the gtk Window
+    @type window: gtk.Window
+    """
     interesting_signals = ()
-
     window = None
 
     def __init__(self, parent=None):
         gobject.GObject.__init__(self)
-        try:
-            assert self.glade_file
-            file = os.path.join(self.glade_dir, self.glade_file)
-            if self.glade_typedict:
-                wtree = gtk.glade.XML(file, typedict=self.glade_typedict)
-            else:
-                # pygtk 2.4 doesn't like typedict={} ?
-                wtree = gtk.glade.XML(file)
-        except RuntimeError, e:
-            msg = log.getExceptionMessage(e)
-            raise RuntimeError('Failed to load file %s from directory %s: %s'
-                               % (self.glade_file, self.glade_dir, msg))
+        GladeBacked.__init__(self)
 
-        self.widgets = {}
-        for widget in wtree.get_widget_prefix(''):
-            wname = widget.get_name()
-            if isinstance(widget, gtk.Window):
-                assert self.window == None
-                self.window = widget
-            
-            if wname in self.widgets:
-                raise AssertionError("Two objects with same name (%s): %r %r"
-                                     % (wname, self.widgets[wname], widget))
-            self.widgets[wname] = widget
+        # make public
+        self.window = self._window
 
         if parent:
             self.window.set_transient_for(parent)
 
-        wtree.signal_autoconnect(self)
-
         self.__signals = {}
         for name, widget in self.widgets.iteritems():
             for prefix, signal in self.interesting_signals:
@@ -183,12 +198,18 @@
                     hid = self.connect_signal(name, signal)
                     self.__signals[(name, signal)] = hid
 
+        # have convenience methods acting on our window
         self.show = self.window.show
         self.hide = self.window.hide
         self.present = self.window.present
 
+    def destroy(self):
+        self.window.destroy()
+        del self.window
+
     def connect_signal(self, widget_name, signal):
-        """Connect a conventionally-named signal handler.
+        """
+        Connect a conventionally-named signal handler.
 
         For example:
           connect_signal('window-foo', 'delete-event')
@@ -207,23 +228,4 @@
         proc = lambda *x: getattr(self, attr)()
         return self.widgets[widget_name].connect(signal, proc)
         
-    # somewhat experimental decorator
-    def with_blocked_signal(self, widget_name, signal):
-        w = self.widgets[widget_name]
-        hid = self.__signals[(widget_name, signal)]
-        def blocker(proc):
-            def blocked(*args, **kwargs):
-                w.handler_block(hid)
-                try:
-                    ret = proc(*args, **kwargs)
-                finally:
-                    w.handler_unblock(hid)
-                return ret
-            return blocked
-        return blocker
-
-    def destroy(self):
-        self.window.destroy()
-        del self.window
-
 pygobject.type_register(GladeWindow)


More information about the flumotion-commit mailing list