2 Mar 2005 lgs   » (Master)

Problems with gtype

Until recently the way Gazpacho instantiates widgets was using their python class. For example, for a GtkWindow I had the <type 'gtk.Window'> class, that is what you usually get when typing:

import gtk; print gtk.Window

The problem was when loading a .glade file. Then when you have to instantiate a widget you don't usually know the module where this widget has the class in. For example, let's see this (fake) glade file:

<?xml version="1.0" ?>
<glade-interface>
    <widget class="GtkWindow" id="window1">

Now, how do I get the gtk.Window class from the 'GtkWindow' name. Well, if we just work with gtk+ widgets it's easy. All I have to do is to strip the 'Gtk' prefix from the name, and look for 'Window' in the gtk module.

Ok, that's cheating, and certainly doesn't work as soon as you start working with other modules, like kiwi.

So I tried another approach: getting the gtype from the class name and building the widgets with gobject.new:

>>> gobject.type_from_name('GtkWindow')
<GType GtkWindow (136052312)>
>>> gobject.new(_)
<gtk.Window object (GtkWindow) at 0xb72e22ac>

Looks like this works perfectly but actually, it doesn't. The problem now is that when you create your widgets in pure python (as kiwi does) you __init__ method is not called anymore when using gobject.new(). Seems like a bug but it is not, since this is the expected behaviour. Even when it's the behaviour I don't want at all.

Sooo, back to the classes. Let's sumarize: I don't have an easy way to get the class object from the class name and I can't use gobject.new to construct the object. So let's get the class object from the gtype. That's the best solution and it would also be great if pygtk would support this :-(

Here is my workaround function that I hope I can remove as soon as this bug is fixed:

def class_from_gtype(gtype, module_list):
  for module in module_list:
    for name, klass in inspect.getmembers(module, inspect.isclass):
      if gtype == getattr(klass, '__gtype__', None):
        return klass

Note how easy is to get the gtype from a python class: it's on the '__gtype__' attribute.

Update: new version of class_from_gtype function thansk to Johan:

def class_from_gtype(gtype, module_list):
    def is_gobject_subclass(k):
        return isinstance(k, type) and issubclass(k, gobject.GObject)
        
    for module in module_list:
        for klass in filter(is_gobject_subclass,
                            [getattr(module, n) for n in dir(module)]):
            if gtype == klass.__gtype__:
                return klass

Latest blog entries     Older blog entries

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!