This site has been retired. For up to date information, see handbook.gnome.org or gitlab.gnome.org.


[Home] [TitleIndex] [WordIndex

This page outlines what needs to be done to get libglade handling arbitrary GObjects instead of just GtkWidgets. This is still a draft.

-- JamesHenstridge 2005-02-28

Use Cases

There are a number of things that people would like to declare within a glade file that they currently can't due to the libglade's restriction to GtkWidgets:

There are some other things that I don't particularly want to handle, including:

Implementation plan

This is a list of the things that need to happen to get things implemented. It will probably change as things get implemented.

XML Schema Changes

An incompatible schema change is out of the question, for two reasons:

  1. the pain of the 1.x to 2.x migration was huge, and would prefer not to inflict it on developers again.
  2. the main aim of the schema change in 2.x was to create a schema that could easily be extended in a non-ambiguous way (with the 1.x schema, any element name might be refering to a widget property). So if there is any information that needs to be added, it should be able to be done in a backward compatible fashion.

That said, the current schema can probably handle the use cases listed above. For GObjects defined in the .glade file, we want to specify the following:

The current <widget> tag covers this pretty well, so we may as well use it. The main problem with it is that it seems a bit unclean to declare a non-widget using that tag. One solution to this would be to add an <object> tag that is essentially a synonym (and treated as such by the parser).

DanWinship: We should make sure that it's not possible to open a new-style .glade file in an old version of Glade, and then edit it, save it, and end up losing information. If Glade will refuse to open a file with unrecognized "class" attributes or property nodes, or if it will refuse to let the user edit those things, then we're ok. Otherwise, doing something like using <object> instead of <widget> to force Glade to choke seems like a good plan.

The Parser

While the 2.x .glade file format is defined to be extensible, the parser for the format in libglade will spit out warnings if it sees anything that is unexpected.

Ignoring unknown elements or only printing warnings if $LIBGLADE_DEBUG includes some flags would be one way to better allow for future extensions, without making apps unnecessarily verbose. We probably still want a warning if the file isn't valid XML or the toplevel element is wrong, since this indicates a real problem.

The Name -> Object Mapping

Libglade maintains a dictionary mapping from widget names to objects, that is primarily accessed via glade_xml_get_widget().

This is implemented in terms of the self->priv->name_hash hash table. In order to make sure that a valid object or NULL is always returned, a handler is attached to the GtkObject::destroy signal of each constructed object, that removes the corresponding entry from name_hash.

If we are storing arbitrary GObjects, then we can't rely on this signal being available. The equivalent of GtkObject::destroy signal handlers in GObject are weak references. Unfortunately, weak references are run when the object is in an inconsistent state so we can't use object data to find the object name like we do currently. This could probably be handled by maintaining a second hash table mapping objects to object names.

Memory Management

Currently, libglade does not claim ownership of any of the objects it constructs. It keeps track of them in an internal dictionary, but these are weak references that are broken when the constructed object is destroyed. While this sounds like it would leak memory, in practice it works quite well.

Due to the way GtkObject floating references are handled, each object libglade constructs should end up with its one reference being held by its container parent. When the top level GtkWindows get destroyed, all sub-widgets get destroyed too. So as long as all toplevel windows constructed by libglade get destroyed, you won't get any memory leaks.

Now for GObjects without a floating reference that are children of some other object, the above scheme can probably continue to work -- just make the parent's "build_children" handler assume ownership of the reference (which is slightly different semantics than what we currently have, but might be the best solution). For top level GObjects though, there isn't necessarily anything that would cause them to be destroyed.

Do we just say that the application author will need to manage these objects? Or do we need to add something to handle them differently?

DanWinship: I'm not sure this will end up being a problem. Tree stuff will be reffed by its view, size groups will be reffed by the widgets in the group, etc.

API Changes

There are two distinct APIs for libglade:

  1. the public API used by applications
  2. the semi-public API used by libglade extension modules.

The first API can not be broken at all -- only additions can be made. The second API has lower stability guarantees, but it would be nice to keep to additions there too. We currently do a version check when loading modules, so we could increment the module API version to "2", and accept modules of versions 1 and 2.

At the moment, the following libglade extension modules exist:

So breaking this API is manageable, but it would still be nice to avoid it.

Public API

From the public API, we have the following functions that mention GtkWidget or GtkObject:

None of these functions aren't really GtkWidget specific. The quick dirty method would be to keep the existing API but sometimes not return GtkWidgets, or accept objects that aren't GtkWidgets. Alternatively, new "object" versions could be added, and the old versions could be implemented in terms of those.

DanWinship: Assuming this is being combined with the LibgladeInGtk work, we would just have a new API in gtk, and rewrite the glade_* functions as wrappers around that

Module API

The libglade module API is used to tell libglade about widget types, and register various handlers for them:

Rather than requiring these functions be written for every single widget, default implementations are available:

The "new" implementation should work pretty much the same for plain GObjects. The "build_children" implementation won't work for arbitrary GObjects (or arbitrary GtkWidgets for that matter), but then GObjects with children will probably need a custom "build_children" implementation anyway.

Some parts of glade_xml_set_common_params() will probably need to be made conditional on whether the object is a widget or not.

In addition to helper functions registered against types, libglade lets you register custom property handlers against a (widget type, property name) tuple. These would function pretty much the same for arbitrary GObjects as for GtkWidgets.

Lastly, these functions suffer from the type problem of the public API. Ignoring it and making the user insert extra casts may be acceptable here given the low number of users. On the other hand, it would just involve adding alternatives for the following functions:

New Objects

The following snippets show how some GObjects might be represented in a .glade file.

GnomeCanvas Items

Tree View Columns

I'm not too sure about this representation of GtkCellRenderers. There are two things you might want to do with a cell renderer property:

The second case here would require custom property handlers for every single property on the cell renderer, so might not be worth it. This would mean that all the programmer would need to do to hook up the tree view would be:

Size Groups

Here, "sizegroup" is implemented as a custom property on GtkWidget. Is there a better way to do this?

DanWinship: Seems fine to me. It's similar to how tooltips are represented

Reference implementation

I've started to do write an implementation, which can be downloaded via svn:

svn co svn://async.com.br/libglade

-- JohanDahlin

Widget support

Examples of files which can be parsed and constructed:

Note that data for GtkTreeModels are not supported.

DTD Changes

widget becomes object

DTD Additions


UI Manager Representation

I am not convinced that the proposed representation of GtkUIManager in the .glade file makes sense. To explain this, I'll start with a description of Johan's representation (feel free to correct any errors -- this is based on previous comments and IRC discussions):

  1. a GtkUIManager is defined at the toplevel, along with some number of UI definitions (either inline, or referencing an external file). Those UI definitions are not loaded by default, but made available to add at a later stage.

  2. Each UI definition has a unique name (presumably, this namespace is parallel to the object name namespace).
  3. The UI manager will have one or more GtkActionGroups associated with it, each of which contain GtkActions.

  4. If an <object> tag is encountered with a constructor attribute, the named UI file is merged into its associated UI manager. The value of the id attribute of the element is looked up in that UI manager, and the corresponding widget is added, instead of constructing the widget as normal.

The immediate problems I see with this model are:

On top of this, the above doesn't really match how I'd use GtkUIManager. Here's a rough description of what I'd do in a larger application:

  1. For each toplevel window that needs menus and/or toolbars, a GtkUIManager is created to handle them.

  2. Every menu or toolbar created by a UI manager is added to its associated window, and toolbar additions/removals are handled at runtime.
  3. Each window's UI manager has one or more GtkActionGroups added to it. Some of these action groups will be shared between multiple UI managers (eg. for application wide actions, such as quit, new document, open, preferences, help and about). Some might only be added to a single UI manager (eg. actions associated with a particular document/window like save, print, etc).

  4. UI definitions are loaded into the UI managers. Some UI definitions may be shared between windows (eg. a common underlay giving structure to the menus). The application may add and remove other UI definitions as the user switches modes in the application.

Naturally, the above would be simplified greatly with the addition of a window widget that handled menubar and toolbar addition/removal, which is why I suggested it earlier. Even without such a widget, it would be nice if the representation doesn't use something totally different (assuming that there is consensus on how to use GtkUIManager).

API Changes

And mostly a general s/GtkWidget/GObject/

API Additions

These are used from glade-gtk.c, which needs to access internals of the GladeXML object.

Added properties

Deprecated widgets

JonathanBlandford: I don't think we can remove deprecated widgets entirely. There are still quite a few applications that use GtkCList and GtkCombo in it's glade files.


2024-10-23 10:59