builder: Connect signals automatically

gtk_builder_connect_signals() is no longer necessary, because all the
setup that made it necessary to have this extra step is now done
automatically via the closure functions.
This commit is contained in:
Benjamin Otte 2019-11-22 06:31:33 +01:00
parent 82395a93b0
commit b025ee428c
23 changed files with 77 additions and 168 deletions

View File

@ -59,7 +59,6 @@ do_builder (GtkWidget *do_widget)
builder = gtk_builder_new_from_resource ("/builder/demo.ui");
gtk_builder_connect_signals (builder);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window1"));
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));

View File

@ -24,7 +24,6 @@ do_cursors (GtkWidget *do_widget)
GtkBuilder *builder;
builder = gtk_builder_new_from_resource ("/cursors/cursors.ui");
gtk_builder_connect_signals (builder);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));

View File

@ -122,7 +122,6 @@ do_filtermodel (GtkWidget *do_widget)
GtkBuilder *builder;
builder = gtk_builder_new_from_resource ("/filtermodel/filtermodel.ui");
gtk_builder_connect_signals (builder);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window1"));
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));

View File

@ -287,13 +287,13 @@ do_fishbowl (GtkWidget *do_widget)
g_type_ensure (GTK_TYPE_FISHBOWL);
builder = gtk_builder_new_from_resource ("/fishbowl/fishbowl.ui");
builder = gtk_builder_new ();
gtk_builder_add_callback_symbols (builder,
"next_button_clicked_cb", G_CALLBACK (next_button_clicked_cb),
"prev_button_clicked_cb", G_CALLBACK (prev_button_clicked_cb),
"changes_toggled_cb", G_CALLBACK (changes_toggled_cb),
NULL);
gtk_builder_connect_signals (builder);
gtk_builder_add_from_resource (builder, "/fishbowl/fishbowl.ui", NULL);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);

View File

@ -1213,15 +1213,14 @@ do_font_features (GtkWidget *do_widget)
GtkWidget *feature_list;
GtkEventController *controller;
builder = gtk_builder_new_from_resource ("/font_features/font-features.ui");
builder = gtk_builder_new ();
gtk_builder_add_callback_symbol (builder, "update_display", update_display);
gtk_builder_add_callback_symbol (builder, "font_changed", font_changed);
gtk_builder_add_callback_symbol (builder, "script_changed", script_changed);
gtk_builder_add_callback_symbol (builder, "reset", reset_features);
gtk_builder_add_callback_symbol (builder, "stop_edit", G_CALLBACK (stop_edit));
gtk_builder_add_callback_symbol (builder, "toggle_edit", G_CALLBACK (toggle_edit));
gtk_builder_connect_signals (builder);
gtk_builder_add_from_resource (builder, "/font_features/font-features.ui", NULL);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
feature_list = GTK_WIDGET (gtk_builder_get_object (builder, "feature_list"));

View File

@ -248,7 +248,6 @@ do_fontrendering (GtkWidget *do_widget)
GtkBuilder *builder;
builder = gtk_builder_new_from_resource ("/fontrendering/fontrendering.ui");
gtk_builder_connect_signals (builder);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));

View File

@ -205,12 +205,12 @@ do_iconscroll (GtkWidget *do_widget)
{
GtkBuilder *builder;
builder = gtk_builder_new_from_resource ("/iconscroll/iconscroll.ui");
builder = gtk_builder_new ();
gtk_builder_add_callback_symbols (builder,
"next_clicked_cb", G_CALLBACK (next_clicked_cb),
"prev_clicked_cb", G_CALLBACK (prev_clicked_cb),
NULL);
gtk_builder_connect_signals (builder);
gtk_builder_add_from_resource (builder, "/iconscroll/iconscroll.ui", NULL);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &window);

View File

@ -39,9 +39,9 @@ do_modelbutton (GtkWidget *do_widget)
GtkBuilder *builder;
GActionGroup *actions;
builder = gtk_builder_new_from_resource ("/modelbutton/modelbutton.ui");
builder = gtk_builder_new ();
gtk_builder_add_callback_symbol (builder, "tool_clicked", G_CALLBACK (tool_clicked));
gtk_builder_connect_signals (builder);
gtk_builder_add_from_resource (builder, "/modelbutton/modelbutton.ui", NULL);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window1"));
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));

View File

@ -69,7 +69,6 @@ do_revealer (GtkWidget *do_widget)
GtkBuilder *builder;
builder = gtk_builder_new_from_resource ("/revealer/revealer.ui");
gtk_builder_connect_signals (builder);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));

View File

@ -18,7 +18,6 @@ do_scale (GtkWidget *do_widget)
GtkBuilder *builder;
builder = gtk_builder_new_from_resource ("/scale/scale.ui");
gtk_builder_connect_signals (builder);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window1"));
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));

View File

@ -85,7 +85,7 @@ do_shortcuts (GtkWidget *do_widget)
{
GtkBuilder *builder;
builder = gtk_builder_new_from_resource ("/shortcuts/shortcuts.ui");
builder = gtk_builder_new ();
gtk_builder_add_callback_symbols (builder,
"builder_shortcuts", G_CALLBACK (builder_shortcuts),
"gedit_shortcuts", G_CALLBACK (gedit_shortcuts),
@ -95,7 +95,7 @@ do_shortcuts (GtkWidget *do_widget)
"boxes_shortcuts_wizard", G_CALLBACK (boxes_shortcuts_wizard),
"boxes_shortcuts_display", G_CALLBACK (boxes_shortcuts_display),
NULL);
gtk_builder_connect_signals (builder);
gtk_builder_add_from_resource (builder, "/shortcuts/shortcuts.ui", NULL);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window1"));
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));

View File

@ -190,7 +190,7 @@ do_spinbutton (GtkWidget *do_widget)
GtkAdjustment *adj;
GtkWidget *label;
builder = gtk_builder_new_from_resource ("/spinbutton/spinbutton.ui");
builder = gtk_builder_new ();
gtk_builder_add_callback_symbols (builder,
"hex_spin_input", G_CALLBACK (hex_spin_input),
"hex_spin_output", G_CALLBACK (hex_spin_output),
@ -199,7 +199,7 @@ do_spinbutton (GtkWidget *do_widget)
"month_spin_input", G_CALLBACK (month_spin_input),
"month_spin_output", G_CALLBACK (month_spin_output),
NULL);
gtk_builder_connect_signals (builder);
gtk_builder_add_from_resource (builder, "/spinbutton/spinbutton.ui", NULL);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));

View File

@ -18,7 +18,6 @@ do_stack (GtkWidget *do_widget)
GtkBuilder *builder;
builder = gtk_builder_new_from_resource ("/stack/stack.ui");
gtk_builder_connect_signals (builder);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window1"));
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));

View File

@ -1715,7 +1715,7 @@ activate (GApplication *app)
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
g_object_unref (provider);
builder = gtk_builder_new_from_resource ("/org/gtk/WidgetFactory4/widget-factory.ui");
builder = gtk_builder_new ();
gtk_builder_add_callback_symbol (builder, "on_entry_icon_release", (GCallback)on_entry_icon_release);
gtk_builder_add_callback_symbol (builder, "on_scale_button_value_changed", (GCallback)on_scale_button_value_changed);
gtk_builder_add_callback_symbol (builder, "on_scale_button_query_tooltip", (GCallback)on_scale_button_query_tooltip);
@ -1728,8 +1728,7 @@ activate (GApplication *app)
gtk_builder_add_callback_symbol (builder, "decrease_icon_size", (GCallback)decrease_icon_size);
gtk_builder_add_callback_symbol (builder, "reset_icon_size", (GCallback)reset_icon_size);
gtk_builder_add_callback_symbol (builder, "osd_frame_pressed", (GCallback)osd_frame_pressed);
gtk_builder_connect_signals (builder);
gtk_builder_add_from_resource (builder, "/org/gtk/WidgetFactory4/widget-factory.ui", NULL);
window = (GtkWindow *)gtk_builder_get_object (builder, "window");
gtk_application_add_window (GTK_APPLICATION (app), window);

View File

@ -521,7 +521,6 @@ GTK_BUILDABLE_GET_IFACE
<TITLE>GtkBuilder</TITLE>
GtkBuilder
GtkBuilderClosureFunc
GtkBuilderConnectFunc
GtkBuilderError
gtk_builder_new
gtk_builder_new_from_file
@ -542,8 +541,6 @@ gtk_builder_extend_with_template
gtk_builder_get_object
gtk_builder_get_objects
gtk_builder_expose_object
gtk_builder_connect_signals
gtk_builder_connect_signals_full
gtk_builder_set_translation_domain
gtk_builder_get_translation_domain
gtk_builder_get_type_from_name

View File

@ -137,18 +137,6 @@
* Internally builder implements this using GBinding objects.
* For more information see g_object_bind_property()
*
* Signal handlers are set up with the <signal> element. The name
* attribute specifies the name of the signal, and the handler attribute
* specifies the function to connect to the signal. By default, GTK+ tries
* to find the handler using g_module_symbol(), but this can be changed by
* passing a custom #GtkBuilderConnectFunc to
* gtk_builder_connect_signals_full(). The remaining attributes, after,
* swapped and object, have the same meaning as the corresponding
* parameters of the g_signal_connect_object() or
* g_signal_connect_data() functions. A last_modification_time
* attribute is also allowed, but it does not have a meaning to the
* builder.
*
* Sometimes it is necessary to refer to widgets which have implicitly
* been constructed by GTK+ as part of a composite widget, to set
* properties on them or to add further children (e.g. the @vbox of
@ -163,6 +151,43 @@
* The possible values for the type attribute are described in the
* sections describing the widget-specific portions of UI definitions.
*
* # Signal handlers and function pointers
*
* Signal handlers are set up with the <signal> element. The name
* attribute specifies the name of the signal, and the handler attribute
* specifies the function to connect to the signal.
* The remaining attributes, after, swapped and object, have the
* same meaning as the corresponding parameters of the
* g_signal_connect_object() or g_signal_connect_data() functions. A
* last_modification_time attribute is also allowed, but it does not
* have a meaning to the builder.
*
* By default, GTK+ tries to find functions (like the handlers for
* signals) by using g_module_symbol(), but this can be changed by
* passing a custom #GtkBuilderClosureFunc to gtk_builder_set_closure_func().
* Bindings in particular will want to make use of this functionality to
* allow language-specific name mangling and namespacing.
*
* The default closure function uses symbols explicitly added to @builder
* with prior calls to gtk_builder_add_callback_symbol(). In the case that
* symbols are not explicitly added; it uses #GModules introspective
* features (by opening the module %NULL) to look at the applications symbol
* table. From here it tries to match the signal function names given in the
* interface description with symbols in the application.
*
* Note that unless gtk_builder_add_callback_symbol() is called for
* all signal callbacks which are referenced by the loaded XML, this
* functionality will require that #GModule be supported on the platform.
*
* If you rely on #GModule support to lookup callbacks in the symbol table,
* the following details should be noted:
*
* When compiling applications for Windows, you must declare signal callbacks
* with #G_MODULE_EXPORT, or they will not be put in the symbol table.
* On Linux and Unices, this is not necessary; applications should instead
* be compiled with the -Wl,--export-dynamic CFLAGS, and linked against
* gmodule-export-2.0.
*
* # A GtkBuilder UI Definition
*
* |[
@ -1054,13 +1079,6 @@ gtk_builder_create_bindings (GtkBuilder *builder)
priv->bindings = NULL;
}
void
_gtk_builder_finish (GtkBuilder *builder)
{
gtk_builder_apply_delayed_properties (builder);
gtk_builder_create_bindings (builder);
}
/**
* gtk_builder_new:
*
@ -1656,71 +1674,6 @@ gtk_builder_expose_object (GtkBuilder *builder,
g_object_ref (object));
}
static void
gtk_builder_connect_signals_default (GtkBuilder *builder,
GObject *object,
const gchar *signal_name,
const gchar *handler_name,
GObject *connect_object,
GConnectFlags flags,
gpointer user_data)
{
GClosure *closure;
GError *error = NULL;
closure = gtk_builder_create_closure (builder,
handler_name,
flags & G_CONNECT_SWAPPED ? TRUE : FALSE,
connect_object,
&error);
if (closure == NULL)
{
g_warning ("%s", error->message);
g_error_free (error);
return;
}
g_signal_connect_closure (object, signal_name, closure, flags & G_CONNECT_AFTER ? TRUE : FALSE);
}
/**
* gtk_builder_connect_signals:
* @builder: a #GtkBuilder
*
* This method is a simpler variation of gtk_builder_connect_signals_full().
* It uses symbols explicitly added to @builder with prior calls to
* gtk_builder_add_callback_symbol(). In the case that symbols are not
* explicitly added; it uses #GModules introspective features (by opening the module %NULL)
* to look at the applications symbol table. From here it tries to match
* the signal handler names given in the interface description with
* symbols in the application and connects the signals. Note that this
* function can only be called once, subsequent calls will do nothing.
*
* Note that unless gtk_builder_add_callback_symbol() is called for
* all signal callbacks which are referenced by the loaded XML, this
* function will require that #GModule be supported on the platform.
*
* If you rely on #GModule support to lookup callbacks in the symbol table,
* the following details should be noted:
*
* When compiling applications for Windows, you must declare signal callbacks
* with #G_MODULE_EXPORT, or they will not be put in the symbol table.
* On Linux and Unices, this is not necessary; applications should instead
* be compiled with the -Wl,--export-dynamic CFLAGS, and linked against
* gmodule-export-2.0.
**/
void
gtk_builder_connect_signals (GtkBuilder *builder)
{
g_return_if_fail (GTK_IS_BUILDER (builder));
gtk_builder_connect_signals_full (builder,
gtk_builder_connect_signals_default,
NULL);
}
/**
* GtkBuilderClosureFunc:
* @builder: a #GtkBuilder
@ -1747,38 +1700,8 @@ gtk_builder_connect_signals (GtkBuilder *builder)
* be created and @error was set.
*/
/**
* GtkBuilderConnectFunc:
* @builder: a #GtkBuilder
* @object: object to connect a signal to
* @signal_name: name of the signal
* @handler_name: name of the handler
* @connect_object: (nullable): a #GObject, if non-%NULL, use g_signal_connect_object()
* @flags: #GConnectFlags to use
* @user_data: user data
*
* This is the signature of a function used to connect signals. It is used
* by the gtk_builder_connect_signals() and gtk_builder_connect_signals_full()
* methods. It is mainly intended for interpreted language bindings, but
* could be useful where the programmer wants more control over the signal
* connection process. Note that this function can only be called once,
* subsequent calls will do nothing.
*/
/**
* gtk_builder_connect_signals_full:
* @builder: a #GtkBuilder
* @func: (scope call): the function used to connect the signals
* @user_data: arbitrary data that will be passed to the connection function
*
* This function can be thought of the interpreted language binding
* version of gtk_builder_connect_signals(), except that it does not
* require GModule to function correctly.
*/
void
gtk_builder_connect_signals_full (GtkBuilder *builder,
GtkBuilderConnectFunc func,
gpointer user_data)
static void
gtk_builder_connect_signals (GtkBuilder *builder)
{
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (builder);
GSList *l;
@ -1787,7 +1710,6 @@ gtk_builder_connect_signals_full (GtkBuilder *builder,
GString *detailed_id = NULL;
g_return_if_fail (GTK_IS_BUILDER (builder));
g_return_if_fail (func != NULL);
if (!priv->signals)
return;
@ -1797,6 +1719,8 @@ gtk_builder_connect_signals_full (GtkBuilder *builder,
{
SignalInfo *signal = (SignalInfo*)l->data;
const gchar *signal_name;
GClosure *closure;
GError *error = NULL;
g_assert (signal != NULL);
g_assert (signal->id != 0);
@ -1828,8 +1752,20 @@ gtk_builder_connect_signals_full (GtkBuilder *builder,
signal_name = detailed_id->str;
}
func (builder, object, signal_name, signal->handler,
connect_object, signal->flags, user_data);
closure = gtk_builder_create_closure (builder,
signal->handler,
signal->flags & G_CONNECT_SWAPPED ? TRUE : FALSE,
connect_object,
&error);
if (closure == NULL)
{
g_warning ("%s", error->message);
g_error_free (error);
continue;
}
g_signal_connect_closure (object, signal_name, closure, signal->flags & G_CONNECT_AFTER ? TRUE : FALSE);
}
g_slist_free_full (priv->signals, (GDestroyNotify)_free_signal_info);
@ -1839,6 +1775,14 @@ gtk_builder_connect_signals_full (GtkBuilder *builder,
g_string_free (detailed_id, TRUE);
}
void
_gtk_builder_finish (GtkBuilder *builder)
{
gtk_builder_apply_delayed_properties (builder);
gtk_builder_create_bindings (builder);
gtk_builder_connect_signals (builder);
}
/**
* gtk_builder_value_from_string:
* @builder: a #GtkBuilder

View File

@ -159,12 +159,6 @@ void gtk_builder_expose_object (GtkBuilder *builder,
const gchar *name,
GObject *object);
GDK_AVAILABLE_IN_ALL
void gtk_builder_connect_signals (GtkBuilder *builder);
GDK_AVAILABLE_IN_ALL
void gtk_builder_connect_signals_full (GtkBuilder *builder,
GtkBuilderConnectFunc func,
gpointer user_data);
GDK_AVAILABLE_IN_ALL
void gtk_builder_set_translation_domain (GtkBuilder *builder,
const gchar *domain);
GDK_AVAILABLE_IN_ALL

View File

@ -57,13 +57,6 @@ typedef GClosure* (* GtkBuilderClosureFunc) (GtkBuilder
GObject *object,
gpointer user_data,
GError **error);
typedef void (*GtkBuilderConnectFunc) (GtkBuilder *builder,
GObject *object,
const gchar *signal_name,
const gchar *handler_name,
GObject *connect_object,
GConnectFlags flags,
gpointer user_data);
G_END_DECLS

View File

@ -12232,8 +12232,6 @@ gtk_widget_init_template (GtkWidget *widget)
}
}
gtk_builder_connect_signals (builder);
g_object_unref (builder);
}

View File

@ -34,7 +34,6 @@ main (int argc, char *argv[])
gtk_builder_add_callback_symbol (builder, "back_to_main", G_CALLBACK (back_to_main));
gtk_builder_add_callback_symbol (builder, "go_to_secondary", G_CALLBACK (go_to_secondary));
gtk_builder_add_from_file (builder, "teststackedheaders.ui", NULL);
gtk_builder_connect_signals (builder);
win = (GtkWidget *)gtk_builder_get_object (builder, "window");
header_stack = (GtkWidget *)gtk_builder_get_object (builder, "header_stack");

View File

@ -68,7 +68,6 @@ main (int argc, char *argv[])
builder = gtk_builder_new ();
gtk_builder_add_from_file (builder, filename, NULL);
gtk_builder_connect_signals (builder);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window1"));
g_object_unref (G_OBJECT (builder));

View File

@ -244,7 +244,6 @@ test_connect_signals (void)
"</interface>";
builder = builder_new_from_string (buffer, -1, NULL);
gtk_builder_connect_signals (builder);
window = gtk_builder_get_object (builder, "window1");
gtk_window_set_title (GTK_WINDOW (window), "test");
@ -258,7 +257,6 @@ test_connect_signals (void)
g_object_unref (builder);
builder = builder_new_from_string (buffer_order, -1, NULL);
gtk_builder_connect_signals (builder);
window = gtk_builder_get_object (builder, "window1");
normal = 0;
gtk_window_set_title (GTK_WINDOW (window), "test");
@ -270,7 +268,6 @@ test_connect_signals (void)
strlen (buffer_extra), NULL);
gtk_builder_add_from_string (builder, buffer_extra2,
strlen (buffer_extra2), NULL);
gtk_builder_connect_signals (builder);
window = gtk_builder_get_object (builder, "window2");
gtk_window_set_title (GTK_WINDOW (window), "test");
g_assert (normal == 30);
@ -289,7 +286,6 @@ test_connect_signals (void)
builder = builder_new_from_string (buffer_after_child, -1, NULL);
window = gtk_builder_get_object (builder, "window1");
gtk_builder_connect_signals (builder);
gtk_window_set_title (GTK_WINDOW (window), "test");
g_assert (normal == 1);
@ -2601,7 +2597,6 @@ test_anaconda_signal (void)
"</interface>";
builder = builder_new_from_string (buffer, -1, NULL);
gtk_builder_connect_signals (builder);
g_object_unref (builder);
}

View File

@ -260,7 +260,6 @@ reftest_snapshot_ui_file (const char *ui_file)
gtk_builder_set_closure_func (builder, create_closure, directory, g_free);
gtk_builder_add_from_file (builder, ui_file, &error);
g_assert_no_error (error);
gtk_builder_connect_signals (builder);
window = builder_get_toplevel (builder);
g_object_unref (builder);
g_assert (window);