EggSignalGroup and EggBindingGroup

Have you ever had to deal with lots of GBinding or signal connection (and therefore disconnections) on indirect objects? A classic example for this is the GtkTextView:buffer GObject property.

It’s not uncommon to find vastly broken code when it comes to this. People will g_signal_connect() and never disconnect. Slightly better is to use g_signal_connect_object()[1]. However even that requires that one of the objects be finalized to work properly.

EggSignalGroup allows you to connect to a bunch of signals on a single target object as a group. You can connect and disconnect them simply by setting the EggSignalGroup:target property. I find this convenient because I can setup the EggSignalGroup in my instance init function, and simply set the target when it becomes available. You can even bind it using g_object_bind_property() for even less application code.

EggSignalGroup *group;

group = egg_signal_group_new (GTK_TYPE_TEXT_VIEW);
egg_signal_group_connect_object (group,
                                 "key-press-event",
                                 G_CALLBACK (press_event),
                                 self,
                                 G_CONNECT_SWAPPED);
egg_signal_group_connect_object (group,
                                 "key-release-event",
                                 G_CALLBACK (release_event),
                                 self,
                                 G_CONNECT_SWAPPED);

/* ... later on */
egg_signal_group_set_target (group, text_view);

/* ... and to disconnect */
g_clear_object (&group);
/* or */
egg_signal_group_set_target (group, NULL);

EggBindingGroup is similar in spirit, but for GBinding. You can create a series of delayed bindings and apply them as a set. Simply set the EggBindingGroup:source property to the GObject instance you would like to bind.

EggBindingGroup *group;

group = egg_binding_group_new ();
egg_binding_group_bind (group, "foo",
                        target, "foo",
                        G_BINDING_SYNC_CREATE);
egg_binding_group_bind (group, "bar",
                        target, "bar",
                        G_BINDING_SYNC_CREATE);

/* later on */
egg_binding_group_set_source (group, my_obj);

[1] g_signal_connect_object() used to be broken, but should work as expected.