[gtk+/composite-templates: 13/18] Fixed property setting and signal connection for parent objects (ie: gtk_builder_add_to_parent_*())



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,
                               &parameters,
                               &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 (&param->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]