Re: GtkBuilder and widget names



On Mon, Dec 26, 2011 at 9:36 AM, George Brink <siberianowl yahoo com> wrote:
> On Sun, 25 Dec 2011 16:21:40 +0900, Tristan Van Berkom wrote:
>
>> For what it's worth, I see your point, and I don't consider your code to
>> be messy or obfuscated in any way for that, however it's a sort of API
>> abuse.
> Well, may be it is, but if we would have an "official" ability to read
> widget names/ids as they defined in the glade file - then there wont be a
> need for abuse, would it?
>

It is the official way, gtk_buildable_get_name() is the way to obtain the
name of a widget as it was assigned in Glade.

>
>> You will have the limitation that your settings keys must not conflict
>> in name with any other widget names in your project, which is probably
>> not an issue for you in any case.
> It is not issue at all. You cannot have two widgets with the same name in
> a glade file. And the set of functions which deals with that glade file
> is an encapsulated object by itself. So if we want to serialize the data
> from the widgets of some glade file - we just put all the data in one
> segment of key file.
>
>> On the other hand, an elegant and more extendable solution would be to:
> Sorry, I do not think so.
> This additional wrapping looks nice on paper, but I believe it would be
> too much and too one-sided.
> I use the approach I showed not just for saving the data from checkboxes,
> it is also how I save visibility of toolbars, position and visibility of
> docked windows, the active page in notebooks... Everything which needs to
> be saved between restarts is saved-restored by using the
> gtk_buildable_get_name() function.
> It is a global approach - whatever is defined in glade file as the
> object's ID - this string is used as identifier during any kind of
> serialization of that widget and/or data associated with it.

I see now that this is not about storing settings which are relevant
to your program but more about storing your user session in a
generic way (I did not catch this detail from your previous mails).

I can understand that it's useful for your case, there are some other
tools which accomplish this (i.e. libgdl / gnome docking library, user
configurable user interface layouting and session storing capabilities
mainly useful for IDE like programs, main user being anjuta)... but sure,
I can see this as a practical use case of pulling out the builder assigned
name from a built widget... which is the main reason I posed the
first question, I am interested to know if there really are any valid use
cases for this api.

A bit of history is in order now, for you to understand my disgust with
this api and the programming style which it tends to encourage.

Historically Glade (original version by Damon Chaplin) was written with
an internal xml format only used to save the project state, and
code generators were available, and were the only way to
use Glade before the libglade library was developed by James
Henstridge.

Very quickly libglade became the preferred way to use Glade
output files and another version of Glade was released with a
much more friendly xml format (not sure exactly when, but
probably around the time Glade-2 was released for the initial
releases of GTK+2).

Of course libglade was preferred because structuring your
project around some C files generated by Glade was not
maintainable in the long term, much of the time generated files
needed to be hand edited and so regenerating the code always
causes difficult merge situations (worse yet, newcomer programmers
would read generated source code and base their code off of that
instead of following better tutorials, reading documentation and
communicating with us on the lists).

Now, the artifact that was passed down to us from those ancient
times (ever since code-generation addicts had the code-generation
feature pulled out from under their seats, since Glade 3.0) was the
need to lookup widgets by their names.

Many projects, when converting to libglade at that point, ended up
with this really ugly code (actually you can find examples still, google
shows me this very old tutorial for instance:
http://wingtk.sourceforge.net/exampl2.htm)

I don't have the function on hand but it looks sort of like this:

typedef struct {
    gchar *name;
    GtkWidget *match;
} SearchData;

static void
lookup_widget_foreach (GtkWidget *widget,
                                       SearchData *data)
{
   if (data->match)
      return;
   else if (!strcmp (data->name, gtk_widget_get_name (widget)))
     data->match = widget;
   else if (GTK_IS_CONTAINER (widget))
     gtk_container_foreach (GTK_CONTAINER (widget),
lookup_widget_foreach, data);
}

GtkWidget *
lookup_widget (GtkWidget *toplevel, const gchar *name)
{
   SearchData data = { name, NULL };

   gtk_container_foreach (GTK_CONTAINER (toplevel),
lookup_widget_foreach, &data);

   return data.match;
}

Actually, this above code is the extreme case which I want to avoid, and
it's really the only use case that I'm aware of for exposing
gtk_buildable_get_name()
for.

What you are doing is not accessing a widget by name, it's getting the name
for a widget for which you already have access to, which is totally ok (however
I still kind of wish that it could be done differently, like with a
thin layer of
session aware derived widgets such as libgdl where one could assign specific
keys for the widgets which they want session information stored for... it seems
to me to that it would be worth the slight pain, if only to discourage
the old-school
programming techniques mentioned above).

When David made his reply he mentioned that the alternative to using
gtk_buildable_get_name() was to "pass around structures in your callbacks",
this was the old non-object-oriented way of doing things which was still
far superior to recursively comparing name strings at any time one wants
to access a widget, but really... if your going to use C and GObject, I don't
see why you would chose to create structures... you really should be
just passing the handle to your composite object class to the callbacks.

Well, that's my explanation of why I am a hater of the _get_name() api
and wish it had not been exposed in the first place, hopefully in 2012 we
are all a bit better educated than we were in 2005, and this will not be
an issue anymore.

Cheers,
      -Tristan


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]