After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 727919 - user data objects from GtkBuilder not passed to signal handlers
user data objects from GtkBuilder not passed to signal handlers
Status: RESOLVED OBSOLETE
Product: pygobject
Classification: Bindings
Component: general
3.12.x
Other Linux
: Normal normal
: ---
Assigned To: Nobody's working on this now (help wanted and appreciated)
Python bindings maintainers
Depends on: 701843
Blocks:
 
 
Reported: 2014-04-09 20:16 UTC by David Shea
Modified: 2018-01-10 20:42 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
user_data.glade (1.62 KB, application/x-glade)
2014-04-09 20:16 UTC, David Shea
Details
test.py (447 bytes, text/plain)
2014-04-09 20:17 UTC, David Shea
Details
test.c (737 bytes, text/plain)
2014-04-09 20:18 UTC, David Shea
Details
test.c (1.31 KB, text/plain)
2014-04-10 18:46 UTC, David Shea
Details

Description David Shea 2014-04-09 20:16:23 UTC
Created attachment 273934 [details]
user_data.glade

I am attempting to use the object property of the signal interface element to pass user data to signal handlers defined in python. The object property contains the id of another object defined in the interface file. The signal handler is not being called with the user_data parameter.

Attaching the interface file I am using.
Comment 1 David Shea 2014-04-09 20:17:33 UTC
Created attachment 273936 [details]
test.py

Running the attached Python code, clicking the button prints: TypeError: on_button_clicked() takes exactly 2 arguments (1 given)
Comment 2 David Shea 2014-04-09 20:18:39 UTC
Created attachment 273937 [details]
test.c

Equivalent code in C, which correctly prints "Label text: Label"
Comment 3 Simon Feltman 2014-04-10 18:14:02 UTC
It looks like the user_data is passed as the first argument. connect_signals calls GObject.connect_object which exhibits the same behavior. This can be observed by removing the signal connection from the map and manually calling connect_object:

def on_button_clicked(label):
    print(label.get_text())

button.connect_object('clicked', on_button_clicked, label)
button = builder.get_object("button")
label = builder.get_object("label")

See:
https://git.gnome.org/browse/pygobject/tree/gi/overrides/Gtk.py?id=3.12.0#n390

The connect_object behavior has been around since PyGTK, not sure about connect_signals with a glade file binding user_data though. But based on the connect_object behavior we can assume the entirety of PyGObject3:
http://www.pygtk.org/docs/pygobject/class-gobject.html#method-gobject--connect-object

Unfortunately this is most likely "won't fix" if a different behavior is desired because it would be an API break.
Comment 4 David Shea 2014-04-10 18:46:37 UTC
Created attachment 274031 [details]
test.c

So the problem is with connect_object? Using g_signal_connect_object still passes the object the signal is connected to as the first argument to the handler. Replacing test.c with a version that uses gtk_builder_connect_signals_full and g_signal_connect_object, and that still works as expected.

I appreciate that existing code depends on the existing API, but would you consider providing a different method that provides the expected behavior when using builder signal handlers with user_data?
Comment 5 Simon Feltman 2014-04-10 19:38:33 UTC
(In reply to comment #4)
> So the problem is with connect_object? Using g_signal_connect_object still
> passes the object the signal is connected to as the first argument to the
> handler.

Yep, the connect_object Python binding seems to work differently than the C API. I'm not sure of the historical reasoning. Also note bug 688064 shows other problems with connect_object.

> I appreciate that existing code depends on the existing API, but would you
> consider providing a different method that provides the expected behavior when
> using builder signal handlers with user_data?

New API for GObject.connect_object and Builder.connect_signals that more closely matches the C API sounds reasonable. I don't have any naming ideas beyond a '2' suffix like connect_object2... naming suggestions (and patches) welcome. Another idea would an enablement API which allows for an explicit API break, like in bug 723736.

A short term workaround could be to pass the label as user_data in the signal map and remove it from user_data in the ui file:

handlers = {"on_button_clicked": (on_button_clicked,
                                  builder.get_object("label")),
            "on_delete_event": Gtk.main_quit }
Comment 6 Simon Feltman 2014-05-28 06:24:50 UTC
(In reply to comment #5)
> New API for GObject.connect_object and Builder.connect_signals that more
> closely matches the C API sounds reasonable. I don't have any naming ideas
> beyond a '2' suffix like connect_object2...

I hit this same issue when working out the details for GTK+ Composite Template support in bug 701843. The good news is I was able to work around it by adding a new template connection mechanism. This new mechanism could be used wholesale to fix the problem described here by explicitly a different connection scheme to Builder.connect_signals_full. The new connection mechanism is not public and named "_template_connect_callback" but this could be exposed and named more generically to something like:

    builder.connect_signals_full(Gtk.py_builder_connect_callbacks, self)

or even:

    builder.connect_signals_with_ui_objects(self)

I think either of the above should work out nicely, but better naming suggestions are welcome.

This also brings up the point that an alternative workaround right now is to implement your own connection callback and use "connect_signals_full". Basically I think it would be as simple as (untested):

def connect(builder, gobj, signal_name, handler_name, connect_obj, flags, obj):
    user_data = [connect_obj] if connect_obj else []
    gobj.connect(signal_name, getattr(obj, handler_name), *user_data)

builder.connect_signals_full(connect, self)

See patches in bug 701843 for handling swap and after flags.
Comment 7 Simon Feltman 2014-05-28 06:30:53 UTC
Adding bug 701843 as a dependency. While full template support is not required to fix this bug, at least half the patches over there are needed to fix this.
Comment 8 GNOME Infrastructure Team 2018-01-10 20:42:37 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to GNOME's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/pygobject/issues/70.