[gom/wip/hadess/fix-pkey-access] gom: Fix primary-key not being monitored



commit 98554102601a6bb3a6680250306568cc7ba5c9e9
Author: Bastien Nocera <hadess hadess net>
Date:   Mon Feb 17 14:01:23 2020 +0100

    gom: Fix primary-key not being monitored
    
    The GomResourceClass associated with an child class (such as
    ItemResourceClass in much of our tests) isn't the same as the one in
    GomResourceClass' class_init().
    
    We have the right GomResourceClass subclass during
    gom_resource_init(), but GType has temporarily changed its g_class
    pointer to point to the GomResourceClass instance for GOM_TYPE_RESOURCE
    while calling gom_resource_init().
    
    It will later change the g_class pointer back to the GomResourceClass
    instance for ITEM_TYPE_RESOURCE (as is used in most of our tests).
    g_class is used by G_OBJECT_GET_CLASS() to get the class struct instance.
    
    See 
https://gitlab.gnome.org/GNOME/glib/blob/341c58b44a698c68ba96639636fd02e54cbaddd7/gobject/gtype.c#L1860
    
    Add a constructed vfunc so that we can get the GomResourceClass
    associated with the child class' instance after the g_class swap, with,
    this time, the primary_key correctly set to a non-empty value.
    
    Closes: #24

 gom/gom-resource.c | 54 +++++++++++++++++++++++++++++++-----------------------
 1 file changed, 31 insertions(+), 23 deletions(-)
---
diff --git a/gom/gom-resource.c b/gom/gom-resource.c
index 2d2b495..f0c5d6a 100644
--- a/gom/gom-resource.c
+++ b/gom/gom-resource.c
@@ -1048,6 +1048,36 @@ gom_resource_set_property (GObject      *object,
    }
 }
 
+static void
+pkey_changed_cb (GObject    *gobject,
+                 GParamSpec *pspec,
+                 gpointer    user_data)
+{
+  GomResource *resource = (GomResource *) gobject;
+
+  /* Did the developer reset the primary key? */
+  if (!has_primary_key(GOM_RESOURCE(resource))) {
+     resource->priv->is_from_table = FALSE;
+  }
+}
+
+static void
+gom_resource_constructed (GObject *object)
+{
+  char *pkey_signal;
+  GomResourceClass *klass;
+
+  /* Monitor the primary key */
+  klass = GOM_RESOURCE_CLASS (G_OBJECT_GET_CLASS(object));
+  g_assert (klass->primary_key[0] != '\0');
+  pkey_signal = g_strdup_printf("notify::%s", klass->primary_key);
+  g_signal_connect (G_OBJECT (object), pkey_signal,
+                    G_CALLBACK (pkey_changed_cb), NULL);
+  g_free(pkey_signal);
+
+  G_OBJECT_CLASS (gom_resource_parent_class)->constructed (object);
+}
+
 /**
  * gom_resource_class_init:
  * @klass: (in): A #GomResourceClass.
@@ -1063,6 +1093,7 @@ gom_resource_class_init (GomResourceClass *klass)
    object_class->finalize = gom_resource_finalize;
    object_class->get_property = gom_resource_get_property;
    object_class->set_property = gom_resource_set_property;
+   object_class->constructed = gom_resource_constructed;
    g_type_class_add_private(object_class, sizeof(GomResourcePrivate));
 
    gParamSpecs[PROP_REPOSITORY] =
@@ -1075,19 +1106,6 @@ gom_resource_class_init (GomResourceClass *klass)
                                    gParamSpecs[PROP_REPOSITORY]);
 }
 
-static void
-pkey_changed_cb (GObject    *gobject,
-                 GParamSpec *pspec,
-                 gpointer    user_data)
-{
-  GomResource *resource = (GomResource *) gobject;
-
-  /* Did the developer reset the primary key? */
-  if (!has_primary_key(GOM_RESOURCE(resource))) {
-     resource->priv->is_from_table = FALSE;
-  }
-}
-
 /**
  * gom_resource_init:
  * @resource: (in): A #GomResource.
@@ -1097,20 +1115,10 @@ pkey_changed_cb (GObject    *gobject,
 static void
 gom_resource_init (GomResource *resource)
 {
-   char *pkey_signal;
-   GomResourceClass *klass;
-
    resource->priv =
       G_TYPE_INSTANCE_GET_PRIVATE(resource,
                                   GOM_TYPE_RESOURCE,
                                   GomResourcePrivate);
-
-   /* Monitor the primary key */
-   klass = GOM_RESOURCE_CLASS (G_OBJECT_GET_CLASS(resource));
-   pkey_signal = g_strdup_printf("notify::%s", klass->primary_key);
-   g_signal_connect (G_OBJECT (resource), pkey_signal,
-                     G_CALLBACK (pkey_changed_cb), NULL);
-   g_free(pkey_signal);
 }
 
 gboolean


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]