[gtk+/composite-templates: 13/18] Fixed property setting and signal connection for parent objects (ie: gtk_builder_add_to_parent_*())
- From: Juan Pablo Ugarte <jpu src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/composite-templates: 13/18] Fixed property setting and signal connection for parent objects (ie: gtk_builder_add_to_parent_*())
- Date: Tue, 31 Jul 2012 12:14:38 +0000 (UTC)
commit 903d5de2c7dd091b5c54541c45d9ab5d35f10482
Author: Juan Pablo Ugarte <juanpablougarte gmail com>
Date: Tue Jul 10 17:40:21 2012 -0300
Fixed property setting and signal connection for parent objects (ie: gtk_builder_add_to_parent_*())
Use intern strings for properties and signal names and a GType instead of a class name in GtkBuilder
Added new private function _gtk_builder_object_get_name()
gtk/gtkbuilder.c | 86 ++++++++++++++++++++++++++++++----------------
gtk/gtkbuilderparser.c | 60 +++++++++++++++++----------------
gtk/gtkbuilderprivate.h | 8 +++--
gtk/gtkcontainer.c | 6 ++--
4 files changed, 95 insertions(+), 65 deletions(-)
---
diff --git a/gtk/gtkbuilder.c b/gtk/gtkbuilder.c
index 002fd59..c59b624 100644
--- a/gtk/gtkbuilder.c
+++ b/gtk/gtkbuilder.c
@@ -324,8 +324,7 @@ gtk_builder_init (GtkBuilder *builder)
builder->priv->domain = NULL;
builder->priv->objects = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_object_unref);
- builder->priv->external_objects = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, g_object_unref);
+ builder->priv->external_objects = NULL;
}
@@ -343,7 +342,8 @@ gtk_builder_finalize (GObject *object)
g_free (priv->resource_prefix);
g_hash_table_destroy (priv->objects);
- g_hash_table_destroy (priv->external_objects);
+ if (priv->external_objects)
+ g_hash_table_destroy (priv->external_objects);
g_slist_foreach (priv->signals, (GFunc) _free_signal_info, NULL);
g_slist_free (priv->signals);
@@ -603,6 +603,33 @@ gtk_builder_get_internal_child (GtkBuilder *builder,
return obj;
}
+static inline void
+object_set_name (GObject *object, const gchar *name)
+{
+ if (GTK_IS_BUILDABLE (object))
+ gtk_buildable_set_name (GTK_BUILDABLE (object), name);
+ else
+ g_object_set_data_full (object, "gtk-builder-name", g_strdup (name), g_free);
+}
+
+void
+_gtk_builder_add_object (GtkBuilder *builder,
+ const gchar *id,
+ GObject *object)
+{
+ object_set_name (object, id);
+ g_hash_table_insert (builder->priv->objects, g_strdup (id), g_object_ref (object));
+}
+
+const gchar *
+_gtk_builder_object_get_name (GObject *object)
+{
+ if (GTK_IS_BUILDABLE (object))
+ return gtk_buildable_get_name (GTK_BUILDABLE (object));
+ else
+ return g_object_get_data (object, "gtk-builder-name");
+}
+
GObject *
_gtk_builder_construct (GtkBuilder *builder,
ObjectInfo *info,
@@ -616,25 +643,27 @@ _gtk_builder_construct (GtkBuilder *builder,
gboolean custom_set_property;
GtkBuildable *buildable;
- g_assert (info->class_name != NULL);
- object_type = gtk_builder_get_type_from_name (builder, info->class_name);
- if (object_type == G_TYPE_INVALID)
+ if ((object_type = info->object_type) == G_TYPE_INVALID)
{
g_set_error (error,
GTK_BUILDER_ERROR,
GTK_BUILDER_ERROR_INVALID_VALUE,
"Invalid object type `%s'",
- info->class_name);
+ g_type_name (object_type));
return NULL;
}
- gtk_builder_get_parameters (builder, object_type,
+ gtk_builder_get_parameters (builder, info->object_type,
info->id,
info->properties,
¶meters,
&construct_parameters);
- if (info->constructor)
+ if (info->object && info->external)
+ {
+ obj = g_object_ref (info->object);
+ }
+ else if (info->constructor)
{
GObject *constructor;
@@ -691,7 +720,7 @@ _gtk_builder_construct (GtkBuilder *builder,
g_object_ref_sink (obj);
GTK_NOTE (BUILDER,
- g_print ("created %s of type %s\n", info->id, info->class_name));
+ g_print ("created %s of type %s\n", info->id, g_type_name (object_type)));
for (i = 0; i < construct_parameters->len; i++)
{
@@ -732,30 +761,17 @@ _gtk_builder_construct (GtkBuilder *builder,
g_value_unset (¶m->value);
}
g_array_free (parameters, TRUE);
-
- if (GTK_IS_BUILDABLE (obj))
- gtk_buildable_set_name (buildable, info->id);
- else
- g_object_set_data_full (obj,
- "gtk-builder-name",
- g_strdup (info->id),
- g_free);
- /* we already own a reference to obj. put it in the hash table. */
- g_hash_table_insert (builder->priv->objects, g_strdup (info->id), obj);
+ /* put it in the hash table. */
+ _gtk_builder_add_object (builder, info->id, obj);
+
+ /* we already own a reference to obj. */
+ g_object_unref (obj);
return obj;
}
void
-_gtk_builder_add_object (GtkBuilder *builder,
- const gchar *id,
- GObject *object)
-{
- g_hash_table_insert (builder->priv->objects, g_strdup (id), g_object_ref (object));
-}
-
-void
_gtk_builder_add (GtkBuilder *builder,
ChildInfo *child_info)
{
@@ -1462,11 +1478,21 @@ gtk_builder_expose_object (GtkBuilder *builder,
const gchar *name,
GObject *object)
{
+ GtkBuilderPrivate *priv;
+
g_return_if_fail (GTK_IS_BUILDER (builder));
g_return_if_fail (name && name[0]);
g_return_if_fail (G_IS_OBJECT (object));
- g_hash_table_insert (builder->priv->external_objects,
+ priv = builder->priv;
+
+ /* We do not create the table in _init() because this is not used very much */
+ if (priv->external_objects == NULL)
+ priv->external_objects = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, g_object_unref);
+
+ object_set_name (object, name);
+ g_hash_table_insert (priv->external_objects,
g_strdup (name), g_object_ref (object));
}
@@ -1493,7 +1519,7 @@ gtk_builder_connect_signals_default (GtkBuilder *builder,
g_warning ("Could not find signal handler '%s'", handler_name);
return;
}
-
+g_message ("%s %s %s", __func__, signal_name, handler_name);
if (connect_object)
g_signal_connect_object (object, signal_name, func, connect_object, flags);
else
diff --git a/gtk/gtkbuilderparser.c b/gtk/gtkbuilderparser.c
index 5e33901..0bdd118 100644
--- a/gtk/gtkbuilderparser.c
+++ b/gtk/gtkbuilderparser.c
@@ -203,24 +203,19 @@ builder_construct (ParserData *data,
return object;
}
-static gchar *
+static GType
_get_type_by_symbol (const gchar* symbol)
{
static GModule *module = NULL;
GTypeGetFunc func;
- GType type;
if (!module)
module = g_module_open (NULL, 0);
if (!g_module_symbol (module, symbol, (gpointer)&func))
- return NULL;
+ return G_TYPE_INVALID;
- type = func ();
- if (type == G_TYPE_INVALID)
- return NULL;
-
- return g_strdup (g_type_name (type));
+ return func ();
}
static void
@@ -303,13 +298,12 @@ parse_object (GMarkupParseContext *context,
const gchar **values,
GError **error)
{
+ GType object_type = G_TYPE_INVALID;
ObjectInfo *object_info;
- ChildInfo* child_info;
- int i;
- gchar *object_class = NULL;
+ ChildInfo *child_info;
gchar *object_id = NULL;
gchar *constructor = NULL;
- gint line, line2;
+ gint i, line, line2;
child_info = state_peek_info (data, ChildInfo);
if (child_info && strcmp (child_info->tag.name, "object") == 0)
@@ -321,7 +315,8 @@ parse_object (GMarkupParseContext *context,
for (i = 0; names[i] != NULL; i++)
{
if (strcmp (names[i], "class") == 0)
- object_class = g_strdup (values[i]);
+ /* Make sure the class is initialized so we have intern string available */
+ object_type = gtk_builder_get_type_from_name (data->builder, values[i]);
else if (strcmp (names[i], "id") == 0)
object_id = g_strdup (values[i]);
else if (strcmp (names[i], "constructor") == 0)
@@ -332,8 +327,8 @@ parse_object (GMarkupParseContext *context,
* it's guaranteed afterwards that g_type_from_name on the name
* will return our GType
*/
- object_class = _get_type_by_symbol (values[i]);
- if (!object_class)
+ object_type = _get_type_by_symbol (values[i]);
+ if (object_type == G_TYPE_INVALID)
{
g_markup_parse_context_get_position (context, &line, NULL);
g_set_error (error, GTK_BUILDER_ERROR,
@@ -350,7 +345,7 @@ parse_object (GMarkupParseContext *context,
}
}
- if (!object_class)
+ if (object_type == G_TYPE_INVALID)
{
error_missing_attribute (data, element_name, "class", error);
return;
@@ -379,7 +374,6 @@ parse_object (GMarkupParseContext *context,
}
else
{
- g_free (object_class);
g_free (object_id);
g_free (constructor);
return;
@@ -387,7 +381,7 @@ parse_object (GMarkupParseContext *context,
}
object_info = g_slice_new0 (ObjectInfo);
- object_info->class_name = object_class;
+ object_info->object_type = object_type;
object_info->id = object_id;
object_info->constructor = constructor;
state_push (data, object_info);
@@ -420,7 +414,6 @@ free_object_info (ObjectInfo *info)
(GFunc)free_property_info, NULL);
g_slist_free (info->properties);
g_free (info->constructor);
- g_free (info->class_name);
g_free (info->id);
g_slice_free (ObjectInfo, info);
}
@@ -543,7 +536,7 @@ parse_property (ParserData *data,
}
info = g_slice_new0 (PropertyInfo);
- info->name = name;
+ info->name = g_intern_string (name);
info->translatable = translatable;
info->context = context;
info->text = g_string_new ("");
@@ -551,13 +544,14 @@ parse_property (ParserData *data,
state_push (data, info);
info->tag.name = element_name;
+
+ g_free (name);
}
static void
free_property_info (PropertyInfo *info)
{
g_free (info->data);
- g_free (info->name);
g_slice_free (PropertyInfo, info);
}
@@ -569,7 +563,7 @@ parse_signal (ParserData *data,
GError **error)
{
SignalInfo *info;
- gchar *name = NULL;
+ const gchar *name = NULL;
gchar *handler = NULL;
gchar *object = NULL;
gboolean after = FALSE;
@@ -589,7 +583,7 @@ parse_signal (ParserData *data,
for (i = 0; names[i] != NULL; i++)
{
if (strcmp (names[i], "name") == 0)
- name = g_strdup (values[i]);
+ name = values[i];
else if (strcmp (names[i], "handler") == 0)
handler = g_strdup (values[i]);
else if (strcmp (names[i], "after") == 0)
@@ -636,7 +630,7 @@ parse_signal (ParserData *data,
swapped = TRUE;
info = g_slice_new0 (SignalInfo);
- info->name = name;
+ info->name = g_intern_string (name);
info->handler = handler;
if (after)
info->flags |= G_CONNECT_AFTER;
@@ -654,7 +648,6 @@ void
_free_signal_info (SignalInfo *info,
gpointer user_data)
{
- g_free (info->name);
g_free (info->handler);
g_free (info->connect_object_name);
g_free (info->object_name);
@@ -807,7 +800,7 @@ parse_custom (GMarkupParseContext *context,
if (strcmp (parent_info->tag.name, "object") == 0)
{
ObjectInfo* object_info = (ObjectInfo*)parent_info;
- if (!object_info->object)
+ if (!object_info->object || (object_info->object && object_info->external))
{
object_info->properties = g_slist_reverse (object_info->properties);
object_info->object = _gtk_builder_construct (data->builder,
@@ -982,6 +975,12 @@ end_element (GMarkupParseContext *context,
}
else if (strcmp (element_name, "interface") == 0)
{
+ ObjectInfo *object_info = state_pop_info (data, ObjectInfo);
+
+ if (object_info->signals && object_info->external)
+ _gtk_builder_add_signals (data->builder, object_info->signals);
+
+ free_object_info (object_info);
}
else if (data->requested_objects && !data->inside_requested_object)
{
@@ -1175,10 +1174,13 @@ _gtk_builder_parser_parse_buffer (GtkBuilder *builder,
{
ObjectInfo *object_info = g_slice_new0 (ObjectInfo);
- GTK_NOTE (BUILDER, g_print ("parsing with contextual parent info ptr %p\n", object_info));
-
object_info->object = parent;
- object_info->id = g_strdup ("__container");
+ object_info->object_type = G_OBJECT_TYPE (parent);
+ object_info->id = g_strdup (_gtk_builder_object_get_name (parent));
+ object_info->external = TRUE;
+
+ GTK_NOTE (BUILDER, g_print ("parsing with contextual parent info ptr %p %s\n", object_info, g_type_name (object_info->object_type)));
+
state_push (data, object_info);
object_info->tag.name = "object";
}
diff --git a/gtk/gtkbuilderprivate.h b/gtk/gtkbuilderprivate.h
index 3677aca..fb61514 100644
--- a/gtk/gtkbuilderprivate.h
+++ b/gtk/gtkbuilderprivate.h
@@ -31,13 +31,14 @@ typedef struct {
typedef struct {
TagInfo tag;
- gchar *class_name;
+ GType object_type;
gchar *id;
gchar *constructor;
GSList *properties;
GSList *signals;
GObject *object;
CommonInfo *parent;
+ gboolean external;
} ObjectInfo;
typedef struct {
@@ -58,7 +59,7 @@ typedef struct {
typedef struct {
TagInfo tag;
- gchar *name;
+ const gchar *name; /* Intern string */
GString *text;
gchar *data;
gchar *context;
@@ -69,7 +70,7 @@ typedef struct {
typedef struct {
TagInfo tag;
gchar *object_name;
- gchar *name;
+ const gchar *name; /* Intern string */
gchar *handler;
gboolean external;
GConnectFlags flags;
@@ -162,5 +163,6 @@ void _gtk_builder_menu_start (ParserData *parser_data,
GError **error);
void _gtk_builder_menu_end (ParserData *parser_data);
+const gchar * _gtk_builder_object_get_name (GObject *object);
#endif /* __GTK_BUILDER_PRIVATE_H__ */
diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c
index 70ed465..5a7d405 100644
--- a/gtk/gtkcontainer.c
+++ b/gtk/gtkcontainer.c
@@ -1386,7 +1386,7 @@ gtk_container_class_list_child_properties (GObjectClass *cclass,
*
* Retrieves a composite child by name by checking composite children created from the template
*
- * Returns: the composite child of @container with the name @composite_name
+ * Returns: (transfer none): the composite child of @container with the name @composite_name
*/
GtkWidget *
gtk_container_get_composite_child (GtkContainer *container,
@@ -1432,7 +1432,7 @@ gtk_container_get_composite_child (GtkContainer *container,
* instead of <object> and will be parsed with a fresh instance
* of the implementing composite widget type in context as the
* parent container. The composite instance itself will be exposed
- * to the GtkBuilder as an external object named "container" and in this way can
+ * to the GtkBuilder as an external object named "this" and in this way can
* be referred to in child signal and property declarations.
*
* Since: 3.0
@@ -1645,7 +1645,7 @@ gtk_container_constructor (GType type,
guint ret = 0;
builder = gtk_builder_new ();
- gtk_builder_expose_object (builder, "container", object);
+ gtk_builder_expose_object (builder, "this", object);
switch (cpriv->tmpl_type)
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]