Merge branch 'wip/otte/builder' into 'master'

Reorganize various GtkBuilder things

See merge request GNOME/gtk!1204
This commit is contained in:
Benjamin Otte 2019-11-23 17:09:15 +00:00
commit e3c3cbbbcb
26 changed files with 448 additions and 391 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, 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

@ -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, 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

@ -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, 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

@ -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, NULL);
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, NULL);
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, 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

@ -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, NULL);
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, NULL);
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, 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_scale (GtkWidget *do_widget)
GtkBuilder *builder;
builder = gtk_builder_new_from_resource ("/scale/scale.ui");
gtk_builder_connect_signals (builder, 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

@ -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, NULL);
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, NULL);
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, 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

@ -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, NULL);
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

@ -520,7 +520,7 @@ GTK_BUILDABLE_GET_IFACE
<FILE>gtkbuilder</FILE>
<TITLE>GtkBuilder</TITLE>
GtkBuilder
GtkBuilderConnectFunc
GtkBuilderClosureFunc
GtkBuilderError
gtk_builder_new
gtk_builder_new_from_file
@ -529,6 +529,8 @@ gtk_builder_new_from_string
gtk_builder_add_callback_symbol
gtk_builder_add_callback_symbols
gtk_builder_lookup_callback_symbol
gtk_builder_create_closure
gtk_builder_create_cclosure
gtk_builder_add_from_file
gtk_builder_add_from_resource
gtk_builder_add_from_string
@ -539,13 +541,10 @@ 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_set_application
gtk_builder_get_application
gtk_builder_get_type_from_name
gtk_builder_set_closure_func
gtk_builder_value_from_string
gtk_builder_value_from_string_type
GTK_BUILDER_WARN_INVALID_CHILD_TYPE
@ -4667,7 +4666,7 @@ gtk_widget_class_bind_template_child_internal_private
gtk_widget_class_bind_template_child_full
gtk_widget_class_bind_template_callback
gtk_widget_class_bind_template_callback_full
gtk_widget_class_set_connect_func
gtk_widget_class_set_closure_func
<SUBSECTION>
gtk_widget_observe_children

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
*
* |[
@ -216,7 +241,6 @@
#include "gtkicontheme.h"
#include "gtktestutils.h"
static void gtk_builder_finalize (GObject *object);
static void gtk_builder_set_property (GObject *object,
guint prop_id,
@ -226,8 +250,6 @@ static void gtk_builder_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static GType gtk_builder_real_get_type_from_name (GtkBuilder *builder,
const gchar *type_name);
enum {
PROP_0,
@ -237,6 +259,16 @@ enum {
static GParamSpec *builder_props[LAST_PROP];
struct _GtkBuilder
{
GObject parent_instance;
};
struct _GtkBuilderClass
{
GObjectClass parent_class;
};
typedef struct
{
gchar *domain;
@ -245,10 +277,14 @@ typedef struct
GSList *delayed_properties;
GSList *signals;
GSList *bindings;
GModule *module;
gchar *filename;
gchar *resource_prefix;
GType template_type;
GtkApplication *application;
GtkBuilderClosureFunc closure_func;
gpointer closure_data;
GDestroyNotify closure_destroy;
} GtkBuilderPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (GtkBuilder, gtk_builder, G_TYPE_OBJECT)
@ -256,16 +292,12 @@ G_DEFINE_TYPE_WITH_PRIVATE (GtkBuilder, gtk_builder, G_TYPE_OBJECT)
static void
gtk_builder_class_init (GtkBuilderClass *klass)
{
GObjectClass *gobject_class;
gobject_class = G_OBJECT_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = gtk_builder_finalize;
gobject_class->set_property = gtk_builder_set_property;
gobject_class->get_property = gtk_builder_get_property;
klass->get_type_from_name = gtk_builder_real_get_type_from_name;
/**
* GtkBuilder:translation-domain:
*
@ -304,6 +336,11 @@ gtk_builder_finalize (GObject *object)
{
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (GTK_BUILDER (object));
if (priv->closure_destroy)
priv->closure_destroy (priv->closure_data);
g_clear_pointer (&priv->module, g_module_close);
g_free (priv->domain);
g_free (priv->filename);
g_free (priv->resource_prefix);
@ -390,16 +427,34 @@ type_name_mangle (const gchar *name)
return g_string_free (symbol_name, FALSE);
}
static GType
_gtk_builder_resolve_type_lazily (const gchar *name)
GModule *
gtk_builder_get_module (GtkBuilder *builder)
{
static GModule *module = NULL;
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (builder);
if (priv->module == NULL)
{
if (!g_module_supported ())
return NULL;
priv->module = g_module_open (NULL, G_MODULE_BIND_LAZY);
}
return priv->module;
}
static GType
gtk_builder_resolve_type_lazily (GtkBuilder *builder,
const gchar *name)
{
GModule *module;
GTypeGetFunc func;
gchar *symbol;
GType gtype = G_TYPE_INVALID;
module = gtk_builder_get_module (builder);
if (!module)
module = g_module_open (NULL, 0);
return G_TYPE_INVALID;
symbol = type_name_mangle (name);
@ -415,24 +470,6 @@ _gtk_builder_resolve_type_lazily (const gchar *name)
* GtkBuilder virtual methods
*/
static GType
gtk_builder_real_get_type_from_name (GtkBuilder *builder,
const gchar *type_name)
{
GType gtype;
gtype = g_type_from_name (type_name);
if (gtype != G_TYPE_INVALID)
return gtype;
gtype = _gtk_builder_resolve_type_lazily (type_name);
if (gtype != G_TYPE_INVALID)
return gtype;
gtk_test_register_all_types ();
return g_type_from_name (type_name);
}
typedef struct
{
gchar *object;
@ -1027,13 +1064,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:
*
@ -1629,153 +1659,54 @@ gtk_builder_expose_object (GtkBuilder *builder,
g_object_ref (object));
}
typedef struct {
GModule *module;
gpointer data;
} ConnectArgs;
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)
{
GCallback func;
ConnectArgs *args = (ConnectArgs*) user_data;
func = gtk_builder_lookup_callback_symbol (builder, handler_name);
if (!func)
{
/* Only error out for missing GModule support if we've not
* found the symbols explicitly added with gtk_builder_add_callback_symbol()
*/
if (args->module == NULL)
g_error ("gtk_builder_connect_signals() requires working GModule");
if (!g_module_symbol (args->module, handler_name, (gpointer)&func))
{
g_warning ("Could not find signal handler '%s'. Did you compile with -rdynamic?", handler_name);
return;
}
}
if (connect_object)
g_signal_connect_object (object, signal_name, func, connect_object, flags);
else
g_signal_connect_data (object, signal_name, func, args->data, NULL, flags);
}
/**
* gtk_builder_connect_signals:
* GtkBuilderClosureFunc:
* @builder: a #GtkBuilder
* @user_data: user data to pass back with all signals
* @function_name: name of the function to create a closure for
* @swapped: if the closure should swap user data and instance
* @object: (nullable): object to use as user data for the closure
* @user_data: user data passed when setting the function
* @error: location for error when creating the closure fails
*
* 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.
* Prototype of function used to create closures by @builder. It is meant
* for influencing how @function_name is resolved.
*
* 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.
* This function is most useful for bindings and can be used with
* gtk_builder_set_closure_func() or gtk_widget_class_set_closure_func()
* to allow creating closures for functions defined in the binding's
* language.
*
* If you rely on #GModule support to lookup callbacks in the symbol table,
* the following details should be noted:
* If the given @function_name does not match a function name or when the
* arguments cannot be supported by the bindings, bindings should return
* %NULL and set @error. Usually %GTK_BUILDER_ERROR_INVALID_FUNCTION will
* be the right error code to use.
*
* 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,
gpointer user_data)
{
ConnectArgs args;
g_return_if_fail (GTK_IS_BUILDER (builder));
args.data = user_data;
if (g_module_supported ())
args.module = g_module_open (NULL, G_MODULE_BIND_LAZY);
else
args.module = NULL;
gtk_builder_connect_signals_full (builder,
gtk_builder_connect_signals_default,
&args);
if (args.module)
g_module_close (args.module);
}
/**
* 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.
* Returns: (nullable): a new #GClosure or %NULL when no closure could
* be created and @error was set.
*/
/**
* 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 gboolean
gtk_builder_connect_signals (GtkBuilder *builder,
GError **error)
{
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (builder);
GSList *l;
GObject *object;
GObject *connect_object;
GString *detailed_id = NULL;
g_return_if_fail (GTK_IS_BUILDER (builder));
g_return_if_fail (func != NULL);
gboolean result = FALSE;
if (!priv->signals)
return;
return TRUE;
priv->signals = g_slist_reverse (priv->signals);
for (l = priv->signals; l; l = l->next)
{
SignalInfo *signal = (SignalInfo*)l->data;
const gchar *signal_name;
GClosure *closure;
g_assert (signal != NULL);
g_assert (signal->id != 0);
signal_name = g_signal_name (signal->id);
object = g_hash_table_lookup (priv->objects, signal->object_name);
g_assert (object != NULL);
@ -1786,30 +1717,47 @@ gtk_builder_connect_signals_full (GtkBuilder *builder,
connect_object = g_hash_table_lookup (priv->objects,
signal->connect_object_name);
if (!connect_object)
g_warning ("Could not lookup object %s on signal %s of object %s",
signal->connect_object_name, signal_name,
signal->object_name);
{
g_set_error (error,
GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_INVALID_ID,
"Could not lookup object %s on signal %s of object %s",
signal->connect_object_name, g_signal_name (signal->id),
signal->object_name);
break;
}
}
if (signal->detail)
{
if (detailed_id == NULL)
detailed_id = g_string_new ("");
closure = gtk_builder_create_closure (builder,
signal->handler,
signal->flags & G_CONNECT_SWAPPED ? TRUE : FALSE,
connect_object,
error);
g_string_printf (detailed_id, "%s::%s", signal_name,
g_quark_to_string (signal->detail));
signal_name = detailed_id->str;
}
if (closure == NULL)
break;
func (builder, object, signal_name, signal->handler,
connect_object, signal->flags, user_data);
g_signal_connect_closure_by_id (object,
signal->id,
signal->detail,
closure,
signal->flags & G_CONNECT_AFTER ? TRUE : FALSE);
}
if (l == NULL)
result = TRUE;
g_slist_free_full (priv->signals, (GDestroyNotify)_free_signal_info);
priv->signals = NULL;
if (detailed_id)
g_string_free (detailed_id, TRUE);
return result;
}
gboolean
_gtk_builder_finish (GtkBuilder *builder,
GError **error)
{
gtk_builder_apply_delayed_properties (builder);
gtk_builder_create_bindings (builder);
return gtk_builder_connect_signals (builder, error);
}
/**
@ -2493,7 +2441,16 @@ gtk_builder_get_type_from_name (GtkBuilder *builder,
g_return_val_if_fail (GTK_IS_BUILDER (builder), G_TYPE_INVALID);
g_return_val_if_fail (type_name != NULL, G_TYPE_INVALID);
type = GTK_BUILDER_GET_CLASS (builder)->get_type_from_name (builder, type_name);
type = g_type_from_name (type_name);
if (type == G_TYPE_INVALID)
{
type = gtk_builder_resolve_type_lazily (builder, type_name);
if (type == G_TYPE_INVALID)
{
gtk_test_register_all_types ();
type = g_type_from_name (type_name);
}
}
if (G_TYPE_IS_CLASSED (type))
g_type_class_unref (g_type_class_ref (type));
@ -2569,7 +2526,7 @@ _gtk_builder_get_template_type (GtkBuilder *builder)
*
* Adds the @callback_symbol to the scope of @builder under the given @callback_name.
*
* Using this function overrides the behavior of gtk_builder_connect_signals()
* Using this function overrides the behavior of gtk_builder_create_closure()
* for any callback symbols that are added. Using this method allows for better
* encapsulation as it does not require that callback symbols be declared in
* the global namespace.
@ -2645,7 +2602,7 @@ gtk_builder_add_callback_symbols (GtkBuilder *builder,
*
* This function is intended for possible use in language bindings
* or for any case that one might be customizing signal connections
* using gtk_builder_connect_signals_full()
* using gtk_builder_set_closure_func().
*
* Returns: (nullable): The callback symbol in @builder for @callback_name, or %NULL
*/
@ -2664,6 +2621,159 @@ gtk_builder_lookup_callback_symbol (GtkBuilder *builder,
return g_hash_table_lookup (priv->callbacks, callback_name);
}
/**
* gtk_builder_set_closure_func: (skip)
* @builder: a #GtkBuilder
* @closure_func: (allow-none) function to call when creating
* closures or %NULL to use the default
* @user_data: (nullable): user data to pass to @closure_func
* @user_destroy: destroy function for user data
*
* Sets the function to call for creating closures.
* gtk_builder_create_closure() will use this function instead
* of gtk_builder_create_cclosure().
*
* This is useful for bindings.
**/
void
gtk_builder_set_closure_func (GtkBuilder *builder,
GtkBuilderClosureFunc closure_func,
gpointer user_data,
GDestroyNotify user_destroy)
{
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (builder);
g_return_if_fail (GTK_IS_BUILDER (builder));
if (priv->closure_destroy)
priv->closure_destroy (priv->closure_data);
priv->closure_func = closure_func;
priv->closure_data = user_data;
priv->closure_destroy = user_destroy;
}
static GClosure *
gtk_builder_create_closure_for_funcptr (GtkBuilder *builder,
GCallback callback,
gboolean swapped,
GObject *object)
{
GClosure *closure;
if (object)
{
if (swapped)
closure = g_cclosure_new_object_swap (callback, object);
else
closure = g_cclosure_new_object (callback, object);
}
else
{
if (swapped)
closure = g_cclosure_new_swap (callback, NULL, NULL);
else
closure = g_cclosure_new (callback, NULL, NULL);
}
return closure;
}
/**
* gtk_builder_create_closure:
* @builder: a #GtkBuilder
* @function_name: name of the function to look up
* @swapped: %TRUE to create a swapped closure
* @object: (nullable): Object to create the closure with
* @error: (allow-none): return location for an error, or %NULL
*
* Creates a closure to invoke the function called @function_name.
*
* If a closure function was set via gtk_builder_set_closure_func(),
* will be invoked.
* Otherwise, gtk_builder_create_cclosure() will be called.
*
* If no closure could be created, %NULL will be returned and @error will
* be set.
*
* Returns: (nullable): A new closure for invoking @function_name
**/
GClosure *
gtk_builder_create_closure (GtkBuilder *builder,
const char *function_name,
gboolean swapped,
GObject *object,
GError **error)
{
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (builder);
g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
g_return_val_if_fail (function_name, NULL);
g_return_val_if_fail (object == NULL || G_IS_OBJECT (object), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
if (priv->closure_func)
return priv->closure_func (builder, function_name, swapped, object, priv->closure_data, error);
else
return gtk_builder_create_cclosure (builder, function_name, swapped, object, error);
}
/**
* gtk_builder_create_cclosure: (skip)
* @builder: a #GtkBuilder
* @function_name: name of the function to look up
* @swapped: %TRUE to create a swapped closure
* @object: (nullable): Object to create the closure with
* @error: (allow-none): return location for an error, or %NULL
*
* This is the default function used by gtk_builder_set_closure_func(). Some bindings
* with C support may want to call this function as a fallback from their closure
* function.
*
* This function has no purpose otherwise.
*
* This function will prefer callbacks added via gtk_builder_add_callback_symbol()
* to looking up public symbols.
*
* Returns: (nullable): A new closure for invoking @function_name
**/
GClosure *
gtk_builder_create_cclosure (GtkBuilder *builder,
const char *function_name,
gboolean swapped,
GObject *object,
GError **error)
{
GModule *module = gtk_builder_get_module (builder);
GCallback func;
func = gtk_builder_lookup_callback_symbol (builder, function_name);
if (func)
return gtk_builder_create_closure_for_funcptr (builder, func, swapped, object);
if (module == NULL)
{
g_set_error (error,
GTK_BUILDER_ERROR,
GTK_BUILDER_ERROR_INVALID_FUNCTION,
"Could not look up function `%s`: GModule is not supported.",
function_name);
return NULL;
}
if (!g_module_symbol (module, function_name, (gpointer)&func))
{
g_set_error (error,
GTK_BUILDER_ERROR,
GTK_BUILDER_ERROR_INVALID_FUNCTION,
"No function named `%s`.",
function_name);
return NULL;
}
return gtk_builder_create_closure_for_funcptr (builder, func, swapped, object);
}
/**
* gtk_builder_new_from_file:
* @filename: filename of user interface description file
@ -2746,66 +2856,6 @@ gtk_builder_new_from_string (const gchar *string,
return builder;
}
/**
* gtk_builder_set_application:
* @builder: a #GtkBuilder
* @application: a #GtkApplication
*
* Sets the application associated with @builder.
*
* You only need this function if there is more than one #GApplication
* in your process. @application cannot be %NULL.
**/
void
gtk_builder_set_application (GtkBuilder *builder,
GtkApplication *application)
{
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (builder);
g_return_if_fail (GTK_IS_BUILDER (builder));
g_return_if_fail (GTK_IS_APPLICATION (application));
if (priv->application)
g_object_unref (priv->application);
priv->application = g_object_ref (application);
}
/**
* gtk_builder_get_application:
* @builder: a #GtkBuilder
*
* Gets the #GtkApplication associated with the builder.
*
* The #GtkApplication is used for creating action proxies as requested
* from XML that the builder is loading.
*
* By default, the builder uses the default application: the one from
* g_application_get_default(). If you want to use another application
* for constructing proxies, use gtk_builder_set_application().
*
* Returns: (nullable) (transfer none): the application being used by the builder,
* or %NULL
**/
GtkApplication *
gtk_builder_get_application (GtkBuilder *builder)
{
GtkBuilderPrivate *priv = gtk_builder_get_instance_private (builder);
g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
if (!priv->application)
{
GApplication *application;
application = g_application_get_default ();
if (application && GTK_IS_APPLICATION (application))
priv->application = g_object_ref (GTK_APPLICATION (application));
}
return priv->application;
}
/*< private >
* _gtk_builder_prefix_error:
* @builder: a #GtkBuilder

View File

@ -63,7 +63,10 @@ typedef struct _GtkBuilderClass GtkBuilderClass;
* @GTK_BUILDER_ERROR_TEMPLATE_MISMATCH: The wrong type was specified in a composite classs template XML
* @GTK_BUILDER_ERROR_INVALID_PROPERTY: The specified property is unknown for the object class.
* @GTK_BUILDER_ERROR_INVALID_SIGNAL: The specified signal is unknown for the object class.
* @GTK_BUILDER_ERROR_INVALID_ID: An object id is unknown
* @GTK_BUILDER_ERROR_INVALID_ID: An object id is unknown.
* @GTK_BUILDER_ERROR_INVALID_FUNCTION: A function could not be found. This often happens
* when symbols are set to be kept private. Compiling code with -rdynamic or using the
* `gmodule-export-2.0` pkgconfig module can fix this problem.
*
* Error codes that identify various errors that can occur while using
* #GtkBuilder.
@ -83,34 +86,23 @@ typedef enum
GTK_BUILDER_ERROR_TEMPLATE_MISMATCH,
GTK_BUILDER_ERROR_INVALID_PROPERTY,
GTK_BUILDER_ERROR_INVALID_SIGNAL,
GTK_BUILDER_ERROR_INVALID_ID
GTK_BUILDER_ERROR_INVALID_ID,
GTK_BUILDER_ERROR_INVALID_FUNCTION
} GtkBuilderError;
GDK_AVAILABLE_IN_ALL
GQuark gtk_builder_error_quark (void);
struct _GtkBuilder
{
GObject parent_instance;
};
struct _GtkBuilderClass
{
GObjectClass parent_class;
GType (* get_type_from_name) (GtkBuilder *builder,
const char *type_name);
/*< private >*/
gpointer padding[8];
};
GDK_AVAILABLE_IN_ALL
GType gtk_builder_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GtkBuilder* gtk_builder_new (void);
GDK_AVAILABLE_IN_ALL
void gtk_builder_set_closure_func (GtkBuilder *builder,
GtkBuilderClosureFunc closure_func,
gpointer user_data,
GDestroyNotify user_destroy);
GDK_AVAILABLE_IN_ALL
gboolean gtk_builder_add_from_file (GtkBuilder *builder,
const gchar *filename,
@ -150,13 +142,6 @@ void gtk_builder_expose_object (GtkBuilder *builder,
const gchar *name,
GObject *object);
GDK_AVAILABLE_IN_ALL
void gtk_builder_connect_signals (GtkBuilder *builder,
gpointer user_data);
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
@ -197,13 +182,19 @@ void gtk_builder_add_callback_symbols (GtkBuilder *builder,
GDK_AVAILABLE_IN_ALL
GCallback gtk_builder_lookup_callback_symbol (GtkBuilder *builder,
const gchar *callback_name);
GDK_AVAILABLE_IN_ALL
void gtk_builder_set_application (GtkBuilder *builder,
GtkApplication *application);
GClosure * gtk_builder_create_closure (GtkBuilder *builder,
const char *function_name,
gboolean swapped,
GObject *object,
GError **error);
GDK_AVAILABLE_IN_ALL
GtkApplication * gtk_builder_get_application (GtkBuilder *builder);
GClosure * gtk_builder_create_cclosure (GtkBuilder *builder,
const char *function_name,
gboolean swapped,
GObject *object,
GError **error);
/**

View File

@ -1594,7 +1594,9 @@ _gtk_builder_parser_parse_buffer (GtkBuilder *builder,
if (!gtk_buildable_parse_context_parse (&data.ctx, buffer, length, error))
goto out;
_gtk_builder_finish (builder);
if (!_gtk_builder_finish (builder, error))
goto out;
if (_gtk_builder_lookup_failed (builder, error))
goto out;

View File

@ -175,7 +175,8 @@ void _gtk_builder_add (GtkBuilder *builder,
ChildInfo *child_info);
void _gtk_builder_add_signals (GtkBuilder *builder,
GSList *signals);
void _gtk_builder_finish (GtkBuilder *builder);
gboolean _gtk_builder_finish (GtkBuilder *builder,
GError **error);
void _free_signal_info (SignalInfo *info,
gpointer user_data);
@ -227,6 +228,7 @@ GObject *_gtk_builder_lookup_object (GtkBuilder *builder,
gint col);
gboolean _gtk_builder_lookup_failed (GtkBuilder *builder,
GError **error);
GModule *gtk_builder_get_module (GtkBuilder *builder);

View File

@ -51,14 +51,12 @@ typedef struct _GtkWidget GtkWidget;
typedef struct _GtkWidgetPath GtkWidgetPath;
typedef struct _GtkWindow GtkWindow;
typedef void (*GtkBuilderConnectFunc) (GtkBuilder *builder,
GObject *object,
const gchar *signal_name,
const gchar *handler_name,
GObject *connect_object,
GConnectFlags flags,
gpointer user_data);
typedef GClosure* (* GtkBuilderClosureFunc) (GtkBuilder *builder,
const char *function_name,
gboolean swapped,
GObject *object,
gpointer user_data,
GError **error);
G_END_DECLS

View File

@ -490,9 +490,9 @@ typedef struct {
GBytes *data;
GSList *children;
GSList *callbacks;
GtkBuilderConnectFunc connect_func;
gpointer connect_data;
GDestroyNotify destroy_notify;
GtkBuilderClosureFunc closure_func;
gpointer closure_data;
GDestroyNotify closure_destroy;
} GtkWidgetTemplate;
struct _GtkWidgetClassPrivate
@ -12027,9 +12027,9 @@ template_data_free (GtkWidgetTemplate *template_data)
g_slist_free_full (template_data->children, (GDestroyNotify)template_child_class_free);
g_slist_free_full (template_data->callbacks, (GDestroyNotify)callback_symbol_free);
if (template_data->connect_data &&
template_data->destroy_notify)
template_data->destroy_notify (template_data->connect_data);
if (template_data->closure_data &&
template_data->closure_destroy)
template_data->closure_destroy (template_data->closure_data);
g_slice_free (GtkWidgetTemplate, template_data);
}
@ -12113,6 +12113,24 @@ setup_template_child (GtkWidgetTemplate *template_data,
return TRUE;
}
static GClosure *
gtk_widget_template_closure_func (GtkBuilder *builder,
const char *function_name,
gboolean swapped,
GObject *object,
gpointer user_data,
GError **error)
{
if (object == NULL)
object = user_data;
return gtk_builder_create_cclosure (builder,
function_name,
swapped,
object,
error);
}
/**
* gtk_widget_init_template:
* @widget: a #GtkWidget
@ -12154,6 +12172,17 @@ gtk_widget_init_template (GtkWidget *widget)
builder = gtk_builder_new ();
/* Setup closure handling. All signal data from a template receive the
* template instance as user data automatically.
*
* A GtkBuilderClosureFunc can be provided to gtk_widget_class_set_signal_closure_func()
* in order for templates to be usable by bindings.
*/
if (template->closure_func)
gtk_builder_set_closure_func (builder, template->closure_func, template->closure_data, NULL);
else
gtk_builder_set_closure_func (builder, gtk_widget_template_closure_func, widget, NULL);
/* Add any callback symbols declared for this GType to the GtkBuilder namespace */
for (l = template->callbacks; l; l = l->next)
{
@ -12203,17 +12232,6 @@ gtk_widget_init_template (GtkWidget *widget)
}
}
/* Connect signals. All signal data from a template receive the
* template instance as user data automatically.
*
* A GtkBuilderConnectFunc can be provided to gtk_widget_class_set_signal_connect_func()
* in order for templates to be usable by bindings.
*/
if (template->connect_func)
gtk_builder_connect_signals_full (builder, template->connect_func, template->connect_data);
else
gtk_builder_connect_signals (builder, object);
g_object_unref (builder);
}
@ -12332,36 +12350,36 @@ gtk_widget_class_bind_template_callback_full (GtkWidgetClass *widget_class,
}
/**
* gtk_widget_class_set_connect_func:
* gtk_widget_class_set_closure_func:
* @widget_class: A #GtkWidgetClass
* @connect_func: The #GtkBuilderConnectFunc to use when connecting signals in the class template
* @connect_data: The data to pass to @connect_func
* @connect_data_destroy: The #GDestroyNotify to free @connect_data, this will only be used at
* @closure_func: The #GtkBuilderClosureFunc to use when creating closure in the class template
* @closure_data: The data to pass to @closure_func
* @closure_data_destroy: The #GDestroyNotify to free @closure_data, this will only be used at
* class finalization time, when no classes of type @widget_type are in use anymore.
*
* For use in language bindings, this will override the default #GtkBuilderConnectFunc to be
* For use in language bindings, this will override the default #GtkBuilderClosureFunc to be
* used when parsing GtkBuilder XML from this classs template data.
*
* Note that this must be called from a composite widget classes class
* initializer after calling gtk_widget_class_set_template().
*/
void
gtk_widget_class_set_connect_func (GtkWidgetClass *widget_class,
GtkBuilderConnectFunc connect_func,
gpointer connect_data,
GDestroyNotify connect_data_destroy)
gtk_widget_class_set_closure_func (GtkWidgetClass *widget_class,
GtkBuilderClosureFunc closure_func,
gpointer closure_data,
GDestroyNotify closure_data_destroy)
{
g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
g_return_if_fail (widget_class->priv->template != NULL);
/* Defensive, destroy any previously set data */
if (widget_class->priv->template->connect_data &&
widget_class->priv->template->destroy_notify)
widget_class->priv->template->destroy_notify (widget_class->priv->template->connect_data);
if (widget_class->priv->template->closure_data &&
widget_class->priv->template->closure_destroy)
widget_class->priv->template->closure_destroy (widget_class->priv->template->closure_data);
widget_class->priv->template->connect_func = connect_func;
widget_class->priv->template->connect_data = connect_data;
widget_class->priv->template->destroy_notify = connect_data_destroy;
widget_class->priv->template->closure_func = closure_func;
widget_class->priv->template->closure_data = closure_data;
widget_class->priv->template->closure_destroy = closure_data_destroy;
}
/**

View File

@ -956,10 +956,10 @@ void gtk_widget_class_bind_template_callback_full (GtkWidgetClass *
const gchar *callback_name,
GCallback callback_symbol);
GDK_AVAILABLE_IN_ALL
void gtk_widget_class_set_connect_func (GtkWidgetClass *widget_class,
GtkBuilderConnectFunc connect_func,
gpointer connect_data,
GDestroyNotify connect_data_destroy);
void gtk_widget_class_set_closure_func (GtkWidgetClass *widget_class,
GtkBuilderClosureFunc closure_func,
gpointer closure_data,
GDestroyNotify closure_destroy);
GDK_AVAILABLE_IN_ALL
void gtk_widget_class_bind_template_child_full (GtkWidgetClass *widget_class,
const gchar *name,

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, NULL);
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, NULL);
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, NULL);
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, NULL);
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, NULL);
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, NULL);
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, NULL);
g_object_unref (builder);
}

View File

@ -145,14 +145,13 @@ snapshot_widget (GtkWidget *widget)
return surface;
}
static void
connect_signals (GtkBuilder *builder,
GObject *object,
const gchar *signal_name,
const gchar *handler_name,
GObject *connect_object,
GConnectFlags flags,
gpointer user_data)
static GClosure *
create_closure (GtkBuilder *builder,
const char *function_name,
gboolean swapped,
GObject *object,
gpointer user_data,
GError **error)
{
ReftestModule *module;
const char *directory;
@ -161,7 +160,7 @@ connect_signals (GtkBuilder *builder,
char **split;
directory = user_data;
split = g_strsplit (handler_name, ":", -1);
split = g_strsplit (function_name, ":", -1);
switch (g_strv_length (split))
{
@ -177,14 +176,20 @@ connect_signals (GtkBuilder *builder,
module = reftest_module_new_self ();
if (module == NULL)
{
g_error ("glib compiled without module support.");
return;
g_set_error (error,
GTK_BUILDER_ERROR,
GTK_BUILDER_ERROR_INVALID_FUNCTION,
"glib compiled without module support.");
return NULL;
}
func = reftest_module_lookup (module, split[0]);
if (!func)
{
g_error ("failed to lookup handler for name '%s' when connecting signals", split[0]);
return;
g_set_error (error,
GTK_BUILDER_ERROR,
GTK_BUILDER_ERROR_INVALID_FUNCTION,
"failed to lookup function for name '%s'", split[0]);
return NULL;
}
}
break;
@ -194,33 +199,42 @@ connect_signals (GtkBuilder *builder,
module = reftest_module_new (directory, split[0]);
if (module == NULL)
{
g_error ("Could not load module '%s' from '%s' when looking up '%s': %s", split[0], directory, handler_name, g_module_error ());
return;
g_set_error (error,
GTK_BUILDER_ERROR,
GTK_BUILDER_ERROR_INVALID_FUNCTION,
"Could not load module '%s' from '%s' when looking up '%s': %s", split[0], directory, function_name, g_module_error ());
return NULL;
}
func = reftest_module_lookup (module, split[1]);
if (!func)
{
g_error ("failed to lookup handler for name '%s' in module '%s'", split[1], split[0]);
return;
g_set_error (error,
GTK_BUILDER_ERROR,
GTK_BUILDER_ERROR_INVALID_FUNCTION,
"failed to lookup function for name '%s' in module '%s'", split[1], split[0]);
return NULL;
}
break;
default:
g_error ("Could not connect signal handler named '%s'", handler_name);
return;
g_set_error (error,
GTK_BUILDER_ERROR,
GTK_BUILDER_ERROR_INVALID_FUNCTION,
"Could not find function named '%s'", function_name);
return NULL;
}
g_strfreev (split);
if (connect_object)
if (object)
{
if (flags & G_CONNECT_SWAPPED)
closure = g_cclosure_new_object_swap (func, connect_object);
if (swapped)
closure = g_cclosure_new_object_swap (func, object);
else
closure = g_cclosure_new_object (func, connect_object);
closure = g_cclosure_new_object (func, object);
}
else
{
if (flags & G_CONNECT_SWAPPED)
if (swapped)
closure = g_cclosure_new_swap (func, NULL, NULL);
else
closure = g_cclosure_new (func, NULL, NULL);
@ -229,7 +243,7 @@ connect_signals (GtkBuilder *builder,
if (module)
g_closure_add_finalize_notifier (closure, module, (GClosureNotify) reftest_module_unref);
g_signal_connect_closure (object, signal_name, closure, flags & G_CONNECT_AFTER ? TRUE : FALSE);
return closure;
}
cairo_surface_t *
@ -243,12 +257,11 @@ reftest_snapshot_ui_file (const char *ui_file)
directory = g_path_get_dirname (ui_file);
builder = gtk_builder_new ();
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_full (builder, connect_signals, directory);
window = builder_get_toplevel (builder);
g_object_unref (builder);
g_free (directory);
g_assert (window);
gtk_widget_show (window);