GtkBuilder has landed!

Blogroll, GNOME, General, olpc 15 Comments

Today, after more than 2 years and 120 comments I could finally close #172535, adding support for loading interfaces created by UI designers in Gtk+.

GtkBuilder replaces libglade, it uses a similar XML format but also supports the following:

  • GtkTreeViews including columns and cell renderers
  • Menus and toolbars created using GtkUIManager, including actions & actiongroups.
  • TreeModels, it’s possible to define the data used by treemodels. It’s used by treeviews, iconviews, comboboxes, and entries.
  • SizeGroups, align all these widgets without using tables!

I’d like to especially thank Matthias Clasen for reviewing the beast, it was over 6500 lines in the end! Henrique Romano helped me to implement parts of it and Tristan Van Berkom, Tim Janik, Kalle Vahlman, Christian Perch, Dan Winship, Owen Taylor, Behdad Esfahbod and Havoc Pennington also helped out with suggestions and improvements to the patch.There are a couple of things that needs to be done to simplify the transition from libglade to gtkbuilder though:

  • Add support in UI designers. Gazpacho mostly supports it already, it’ll be easy to fix. glade-2 is out of the question and I expect glade-3 to at least partially support GtkBuilder before GNOME 2.20 is released
  • Improve migration from libglade files. There’s a script in bugzilla which converts old libglade files to files which gtkbuilder can load. It needs to be improved and tested, especially menus and toolbars
  • Some libglade features are not supported yet, such as loading only a part of a glade file and pixbuf properties. These will be fixed before the final Gtk+ 2.12 release

Now, time to party!

Converting a Subversion repository to Bazaar

General Comments Off

I recently wanted to test drive Bazaar with a fairly large project.
The first problem is to convert the whole repository which happen to be stored in subversion to a bunch of Bazaar branches.
There’s a tool called svn2bzr written by Gustavo Niemeyer which allows you to easily import a bunch of subversion branches in bzr.

There’s nothing special about my subversion repository, it only contains a couple of modules in the same repository, similar to how KDE has it set up, but different to GNOME.

First you need a dump, that’s easily created using

$ svnadmin dump /path/to/url > stoq-projects.dump

Next step is to convert the four modules called kiwi, stoqlib, stoqdrivers and stoq, to do that, issue this command:

$ python ./svn2bzr.py --scheme=trunk \
--exclude=kiwi(|/tags|/branches)$ \
--exclude=stoq(|/tags|/branches)$ \
--exclude=stoqdrivers(|/tags|/branches)$ \
--exclude=stoqlib(|/tags|/branches)$ ../stoq-projects.svndump stoq-projects

It turned out that the revision timestamp conversion had a couple of bugs, so you’d really need the latest version, incidentally available as a bzr branch from here.

Getting somewhere….

GNOME, PyGTK, Python 2 Comments

I’m very pleased to see that no less than 8 posts on Gnome are about PyGTK or applications using PyGTK. And does not count OLPC, which is also using it.

Very few of the posts are explicitly mentioning Python or PyGTK, it’s such a well accepted platform that there’s really no need to.

This the result of many years of hard work. I’d like to acknowledge the following people who have made it possible:

Gnome hackers, keep on being productive, use high level languages, spread the word and don’t forget to let us know what you’!

Simplified GObject properties

GNOME, PyGTK, Python 4 Comments

Today I spent most of the day to finish off an implementation of bug 338098, adding a property helper to the python gobject bindings.

The support for defining your own GObject properties in PyGObject/PyGTK has always been a nail in my eye:

  • You need to create a dictionary filled with crazy options
  • You need to implement get_property and set_property to store/retrieve the values for each property.
  • There’s very little help if you do a mistake, a cryptic error message will be displayed which gives you insufficient clues to figure out what you’ve done wrong.

A long time ago I solved this in kiwi. But I never quite got around to submit these helpers to pygobject where they belong.

With the new property helper it gets much simpler. Let’s say you want to create a new object called Color which has the three integer properties called red, green and blue:

  class Color(gobject.GObject):
    red = gobject.property(type=int)
    green = gobject.property(type=int)
    blue = gobject.property(type=int)

That’s it!
Easy to read and understand.

If you want to set a property, just modify the properties as if they were a normal python attribute:

  color = Color()
  color.red = 10
  color.green = 20
  color.blue = 300

Same goes for access:

  >>> color.green
  20

Now, suppose you want a read-only property, then you can use the “new” python 2.4 decorator syntax:

  @gobject.property
  def fnorb(self):
     return 'fnuffra'

Which will add a fnorb property which will always return the string ‘fnuffra’ and raise an exception if your try to modify it.

The patch has not yet landed in pygobject’s SVN repository, but it’ll probably go in shortly, assuming nobody have any objections.

Once this is done I intend to work on a similar solution for signals.

Metaclasses & PyGObject

GNOME, PyGTK, Python Comments Off

I recently ran into a long-standing bug in the Kiwi plugin for Gazpacho.

I have this class in Kiwi: (simplified for explanation purposes)

class KiwiEntry(gtk.Entry):
  gproperty('data_type', object)
  def __init__(self, data_type):
     gtk.Entry.__init__(self)
     self.set_property('data_type', data_type)

This worked absolutely fine when you construct the object by calling the constructor from your python code.
However, Gazpacho and also Glade-3 uses gobject.new() to construct objects, which uses an alternative construction path.

When using gobject.new() to construct the KiwiEntry, an exception would be raised that said that data_type was not a property of the object!

After a few hours of digging in Gazpacho and Kiwi I found out that the underlying bug was actually in PyGObject, the python bindings for GObject. It turned out that the GObject subclasses constructed using gobject.new was not properly created during the constructor phase.

Changing the code to set the property immediately after the constructor would magically solve the bug.

First I tried to solve the bug by using gobject.idle_add. It would actually work but it did not really satisfy me since it depends on the mainloop running. Not too much of a deal actually, since you need a mainloop to use the entry subclass anyway. However, I knew that this would cause hard to debug problems in the future.

The solution of course is to use a metaclass!
A metaclass is a class of a class, which allows you to modify how a class behaves. For instance, you can add a piece of code which is ran when the class is constructed if you like. Or in my case, add a hook which is called after the normal construct has been called.

class MyMeta(gobject.GObjectMeta):
    def __call__(self, *args, **kwargs):
        instance = super(MyMeta, self).__call__(*args, **kwargs)
        instance.__post_init__()
        return instance

This metaclass overrides the __call__ method which is the code being run when you put two parenthesis after the class:

  class()

To use this metaclass for an object, just define the __metaclass__ class attribute in the subclass(es) you wish to use it in:

class KiwiEntry(gtk.Entry):
  __metaclass__ = MyMeta

  def __init__(self, data_type=None):
     gtk.Entry.__init__(self)
     self._data_type = data_type

  def __post_init__(self):
     self.set_property('data-type', self._data_type)

A Metaclass is a very powerful concept, it should be used with caution. It’s very easy to abuse them and make code not only hard to understand, but almost impossible to debug.

For more information about metaclasses, refer to the Unifying types and classes in Python 2.2 which contains a quite technical explanation.

Introducing python-launcher

PyGTK, Python, olpc 7 Comments

There have been a few complaints that it takes too long time to start up python programs, especially the ones which has been written to use GTK and other GNOME libraries.
Yesterday I wrote a program called python-launcher, inspired by maemo-launcher which is a way to reduce start up time and memory usage used by python processes.

The trick works in the following way:
When the system is started, a daemon is run which imports all the modules which we want to cache. The normal launcher (/usr/bin/python) is replaced by a small client which communicates with the header and tells it to fork a new process and then execute the python script.
The gtk module is already imported in the parent process so there’s no need to re-import it for each client (eg, application) that is going to use it.

The “import gtk” statement is now instantaneous, but there’s a small hidden cost of creating a new GdkDisplay and associating a cached GdkSettings inside the deamon itself before the application is executed.

Especially the OLPC suffers due to excessive start-up costs.
I got the following numbers:

importing gtk normally: 1000ms
importing gtk with help if the launcher: less than 1 ms
hidden cost in the daemon for each child: around ~60ms

I looked quickly at the smap script written by Ben Maurer and it appears that the added memory cost of using a deamon is already saved when launching the second process using gtk.

Update: Hi Planet OLPC! Thanks Ivan.

HumanKitty

General 4 Comments

Kiko, Matsubara and I just fell in love with the horribly cute Christian’s Hello Kitty Ubuntu Edition.
Knowing that everybody in office will do the same we wrote a gdm theme and installed on all stations here in the office.

You can find the gdm theme here. Enjoy.

Next Entries »