[gnome-builder] libide/tweaks: implement a basic deep copy



commit ebd76705ad53de8e9c24e047460f2f8d4985ba91
Author: Christian Hergert <chergert redhat com>
Date:   Tue Aug 2 23:19:48 2022 -0700

    libide/tweaks: implement a basic deep copy

 src/libide/tweaks/ide-tweaks-factory.c      |  2 +-
 src/libide/tweaks/ide-tweaks-item-private.h |  7 ++-
 src/libide/tweaks/ide-tweaks-item.c         | 73 +++++++++++++++++++++++++++--
 src/libide/tweaks/ide-tweaks-item.h         |  7 ++-
 4 files changed, 79 insertions(+), 10 deletions(-)
---
diff --git a/src/libide/tweaks/ide-tweaks-factory.c b/src/libide/tweaks/ide-tweaks-factory.c
index e35c1bcee..3b116885f 100644
--- a/src/libide/tweaks/ide-tweaks-factory.c
+++ b/src/libide/tweaks/ide-tweaks-factory.c
@@ -212,7 +212,7 @@ _ide_tweaks_factory_inflate (IdeTweaksFactory *self)
         g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ITEM]);
 
       /* Now deep copy child to snapshot state */
-      g_ptr_array_add (ar, _ide_tweaks_item_deep_copy (child));
+      g_ptr_array_add (ar, ide_tweaks_item_copy (child));
     }
 
   if (g_set_object (&self->item, NULL))
diff --git a/src/libide/tweaks/ide-tweaks-item-private.h b/src/libide/tweaks/ide-tweaks-item-private.h
index dcee8c417..4b34f67eb 100644
--- a/src/libide/tweaks/ide-tweaks-item-private.h
+++ b/src/libide/tweaks/ide-tweaks-item-private.h
@@ -24,9 +24,8 @@
 
 G_BEGIN_DECLS
 
-IdeTweaksItem *_ide_tweaks_item_deep_copy (IdeTweaksItem *self);
-void           _ide_tweaks_item_printf    (IdeTweaksItem *self,
-                                           GString       *string,
-                                           guint          level);
+void _ide_tweaks_item_printf (IdeTweaksItem *self,
+                              GString       *string,
+                              guint          level);
 
 G_END_DECLS
diff --git a/src/libide/tweaks/ide-tweaks-item.c b/src/libide/tweaks/ide-tweaks-item.c
index c021fede1..dec339a3b 100644
--- a/src/libide/tweaks/ide-tweaks-item.c
+++ b/src/libide/tweaks/ide-tweaks-item.c
@@ -53,6 +53,63 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (IdeTweaksItem, ide_tweaks_item, G_TYPE_OBJECT,
 
 static GParamSpec *properties [N_PROPS];
 
+static void
+clear_value (gpointer data)
+{
+  GValue *v = data;
+  g_value_unset (v);
+}
+
+static IdeTweaksItem *
+ide_tweaks_item_real_copy (IdeTweaksItem *item)
+{
+  g_autoptr(GPtrArray) names = NULL;
+  g_autoptr(GArray) values = NULL;
+  g_autofree GParamSpec **pspecs = NULL;
+  GObject *copy;
+  GType item_type;
+  guint n_pspecs;
+
+  g_assert (IDE_IS_TWEAKS_ITEM (item));
+
+  item_type = G_OBJECT_TYPE (item);
+  names = g_ptr_array_new ();
+  values = g_array_new (FALSE, FALSE, sizeof (GValue));
+  g_array_set_clear_func (values, clear_value);
+
+  pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (item), &n_pspecs);
+
+  for (guint i = 0; i < n_pspecs; i++)
+    {
+      GParamSpec *pspec = pspecs[i];
+      GValue value = G_VALUE_INIT;
+
+      if ((pspec->flags & G_PARAM_READWRITE) != G_PARAM_READWRITE)
+        continue;
+
+      g_value_init (&value, pspec->value_type);
+      g_object_get_property (G_OBJECT (item), pspec->name, &value);
+
+      g_ptr_array_add (names, (gpointer)pspec->name);
+      g_array_append_val (values, value);
+    }
+
+  copy = g_object_new_with_properties (item_type,
+                                       names->len,
+                                       (const char **)names->pdata,
+                                       (const GValue *)values->data);
+
+  for (IdeTweaksItem *child = ide_tweaks_item_get_first_child (item);
+       child != NULL;
+       child = ide_tweaks_item_get_next_sibling (child))
+    {
+      g_autoptr(IdeTweaksItem) new_child = ide_tweaks_item_copy (child);
+      ide_tweaks_item_insert_after (new_child, IDE_TWEAKS_ITEM (copy), NULL);
+    }
+
+  return IDE_TWEAKS_ITEM (copy);
+}
+
 static void
 ide_tweaks_item_dispose (GObject *object)
 {
@@ -138,6 +195,8 @@ ide_tweaks_item_class_init (IdeTweaksItemClass *klass)
   object_class->get_property = ide_tweaks_item_get_property;
   object_class->set_property = ide_tweaks_item_set_property;
 
+  klass->copy = ide_tweaks_item_real_copy;
+
   properties[PROP_ID] =
     g_param_spec_string ("id", NULL, NULL,
                          NULL,
@@ -607,12 +666,20 @@ _ide_tweaks_item_printf (IdeTweaksItem *self,
   g_string_append_printf (string, "</%s>\n", G_OBJECT_TYPE_NAME (self));
 }
 
+/**
+ * ide_tweaks_item_copy:
+ * @self: a #IdeTweaksItem
+ *
+ * Does a deep copy starting from @self.
+ *
+ * Returns: (transfer full): an #IdeTweaksItem
+ */
 IdeTweaksItem *
-_ide_tweaks_item_deep_copy (IdeTweaksItem *self)
+ide_tweaks_item_copy (IdeTweaksItem *self)
 {
-  /* TODO: actually implement deep copy */
+  g_return_val_if_fail (IDE_IS_TWEAKS_ITEM (self), NULL);
 
-  return g_object_new (G_OBJECT_TYPE (self), NULL);
+  return IDE_TWEAKS_ITEM_GET_CLASS (self)->copy (self);
 }
 
 gboolean
diff --git a/src/libide/tweaks/ide-tweaks-item.h b/src/libide/tweaks/ide-tweaks-item.h
index 2dbb763fe..dea4e1d00 100644
--- a/src/libide/tweaks/ide-tweaks-item.h
+++ b/src/libide/tweaks/ide-tweaks-item.h
@@ -37,13 +37,16 @@ struct _IdeTweaksItemClass
 {
   GObjectClass parent_class;
 
-  gboolean (*accepts) (IdeTweaksItem *self,
-                       IdeTweaksItem *child);
+  gboolean       (*accepts) (IdeTweaksItem *self,
+                             IdeTweaksItem *child);
+  IdeTweaksItem *(*copy)    (IdeTweaksItem *self);
 };
 
 IDE_AVAILABLE_IN_ALL
 const char *        ide_tweaks_item_get_id               (IdeTweaksItem      *self);
 IDE_AVAILABLE_IN_ALL
+IdeTweaksItem      *ide_tweaks_item_copy                 (IdeTweaksItem      *self);
+IDE_AVAILABLE_IN_ALL
 const char * const *ide_tweaks_item_get_keywords         (IdeTweaksItem      *self);
 IDE_AVAILABLE_IN_ALL
 void                ide_tweaks_item_set_keywords         (IdeTweaksItem      *self,


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