A Gtk+ Property Tree View

Recently, I faced the problem to display a tree view of properties. It is trivial to setup a tree view that displays different kind of widgets (or cell renderers in Gtk+ speak) per column. However, to properly interact with different property types, I have to display a suitable cell renderer per row. This cannot be done out-of-the-box, so I consulted the excellent stackoverflow Q&A site. I was pointed to the dconf-editor that does exactly this for the different key entries. Unfortunately, it is written in Vala so I had to port it with my lacking Vala fluency. After some obstacles, I came up with the EggPropertyCellRenderer and EggPropertyTreeView classes that subclass from GtkCellRenderer and GtkTreeView respectively. You can find the sources on GitHub. Here is a screenshot that shows you the tree view applied to the window itself.

2012-07-04/2012-07-04-tree-view-test.png

The cell renderer is actually a royal hack. It subclasses from GtkCellRenderer but does not provide any functionality on its own. Internally it creates spin button, toggle, text and combo cell renderers to which rendering and sizing requests are delegated. This is possible, because whenever a cell renderer is about to be redrawn it is first updated with data using g_object_set(). At this point, we know the property name, query it’s type using g_object_class_find_property() and decide which renderer to use and how to adapt it.

You can use it directly like so:

GtkCellRenderer *renderer;
GtkTreeViewColumn *column;

renderer = egg_property_cell_renderer_new (
    object,     /* a GObject whose properties you want to monitor */
    list_store  /* the model that must contain property names of 'object' in column 0 */
    );

column = gtk_tree_view_column_new_with_attributes(
    "Values", renderer,
    "prop-name", 0,
    NULL);

gtk_tree_view_append_column (tree_view, column);

But you can also use the provided EggPropertyTreeView that encapsulates this setup:

GtkWidget *tree_view;

tree_view = egg_property_tree_view_new (object);

That’s it folks.


Discussion