[libpeas/thiblahute/with-properties: 1/3] extension-set: adds peas_extension_set_new_with_properties()



commit 936959ba46bd5205d7f439d9168cf8334f9ed2d3
Author: Fabian Orccon <cfoch fabian gmail com>
Date:   Mon Jan 30 12:01:43 2017 -0500

    extension-set: adds peas_extension_set_new_with_properties()
    
    Adds a new introspectable variant of peas_extension_set_new() for
    language bindings.
    
    Fixes #8

 libpeas/peas-extension-set.c  |  66 +++++++++++++++++++++++++++
 libpeas/peas-extension-set.h  |   8 +++-
 libpeas/peas-utils.c          |  54 ++++++++++++++++++++++
 libpeas/peas-utils.h          |   7 +++
 tests/libpeas/extension-set.c | 101 ++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 235 insertions(+), 1 deletion(-)
---
diff --git a/libpeas/peas-extension-set.c b/libpeas/peas-extension-set.c
index 027e9d1..8a8de14 100644
--- a/libpeas/peas-extension-set.c
+++ b/libpeas/peas-extension-set.c
@@ -650,6 +650,72 @@ peas_extension_set_newv (PeasEngine *engine,
                                            NULL));
 }
 
+/**
+ * peas_extension_set_new_with_properties: (rename-to peas_extension_set_new)
+ * @engine: (allow-none): A #PeasEngine, or %NULL.
+ * @exten_type: the extension #GType.
+ * @n_properties: the length of the @prop_names and @prop_values array.
+ * @prop_names: (array length=n_properties): an array of property names.
+ * @prop_values: (array length=n_properties): an array of property values.
+ *
+ * Create a new #PeasExtensionSet for the @exten_type extension type.
+ *
+ * If @engine is %NULL, then the default engine will be used.
+ *
+ * Since libpeas 1.22, @exten_type can be an Abstract #GType
+ * and not just an Interface #GType.
+ *
+ * See peas_extension_set_new() for more information.
+ *
+ * Returns: (transfer full): a new instance of #PeasExtensionSet.
+ *
+ * Since 1.24.0
+ */
+PeasExtensionSet *
+peas_extension_set_new_with_properties (PeasEngine    *engine,
+                                        GType          exten_type,
+                                        guint          n_properties,
+                                        const gchar  **prop_names,
+                                        const GValue  *prop_values)
+{
+  PeasExtensionSet *ret;
+  PeasParameterArray construct_properties;
+  GParameter *parameters = NULL;
+
+  g_return_val_if_fail (engine == NULL || PEAS_IS_ENGINE (engine), NULL);
+  g_return_val_if_fail (G_TYPE_IS_INTERFACE (exten_type) ||
+                        G_TYPE_IS_ABSTRACT (exten_type), NULL);
+  g_return_val_if_fail (n_properties == 0 || prop_names != NULL, NULL);
+  g_return_val_if_fail (n_properties == 0 || prop_values != NULL, NULL);
+
+  if (n_properties > 0)
+    {
+      parameters = g_new0 (GParameter, n_properties);
+      if (!peas_utils_properties_array_to_parameter_list (exten_type,
+                                                          n_properties,
+                                                          prop_names,
+                                                          prop_values,
+                                                          parameters))
+        {
+          /* Already warned */
+          g_free (parameters);
+          return NULL;
+        }
+    }
+
+  construct_properties.n_parameters = n_properties;
+  construct_properties.parameters = parameters;
+
+  ret = g_object_new (PEAS_TYPE_EXTENSION_SET,
+                      "engine", engine,
+                      "extension-type", exten_type,
+                      "construct-properties", &construct_properties,
+                      NULL);
+
+  g_free (parameters);
+  return ret;
+}
+
 /**
  * peas_extension_set_new_valist: (skip)
  * @engine: (allow-none): A #PeasEngine, or %NULL.
diff --git a/libpeas/peas-extension-set.h b/libpeas/peas-extension-set.h
index 4b35e65..cd25382 100644
--- a/libpeas/peas-extension-set.h
+++ b/libpeas/peas-extension-set.h
@@ -147,8 +147,14 @@ PeasExtensionSet  *peas_extension_set_newv        (PeasEngine       *engine,
                                                    GType             exten_type,
                                                    guint             n_parameters,
                                                    GParameter       *parameters);
-G_GNUC_END_IGNORE_DEPRECATIONS
 
+PEAS_AVAILABLE_IN_1_24
+PeasExtensionSet  *peas_extension_set_new_with_properties (PeasEngine    *engine,
+                                                           GType          exten_type,
+                                                           guint          n_properties,
+                                                           const gchar  **prop_names,
+                                                           const GValue  *prop_values);
+G_GNUC_END_IGNORE_DEPRECATIONS
 PEAS_AVAILABLE_IN_ALL
 PeasExtensionSet  *peas_extension_set_new_valist  (PeasEngine       *engine,
                                                    GType             exten_type,
diff --git a/libpeas/peas-utils.c b/libpeas/peas-utils.c
index e0dcf49..31e9a55 100644
--- a/libpeas/peas-utils.c
+++ b/libpeas/peas-utils.c
@@ -181,6 +181,60 @@ find_param_spec_for_prerequisites (const gchar  *name,
 }
 
 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+gboolean
+peas_utils_properties_array_to_parameter_list (GType          exten_type,
+                                               guint          n_properties,
+                                               const gchar  **prop_names,
+                                               const GValue  *prop_values,
+                                               GParameter    *parameters)
+{
+  guint i;
+  gpointer *ifaces;
+  GObjectClass *base_class;
+
+  g_return_val_if_fail (n_properties == 0 || prop_names != NULL, FALSE);
+  g_return_val_if_fail (n_properties == 0 || prop_values != NULL, FALSE);
+  g_return_val_if_fail (n_properties == 0 || parameters != NULL, FALSE);
+
+  ifaces = get_base_class_and_interfaces (exten_type, &base_class);
+  memset (parameters, 0, sizeof (GParameter) * n_properties);
+  for (i = 0; i < n_properties; i++)
+    {
+      GParamSpec *pspec;
+      if (prop_names[i] == NULL)
+        {
+          g_warning ("The property name at index %u should not be NULL.", i);
+          goto error;
+        }
+      if (!G_IS_VALUE (&prop_values[i]))
+        {
+          g_warning ("The property value at index %u should be an initialized GValue.", i);
+          goto error;
+        }
+      pspec = find_param_spec_for_prerequisites (prop_names[i], base_class,
+                                                 ifaces);
+      if (!pspec)
+        {
+          g_warning ("%s: type '%s' has no property named '%s'",
+                     G_STRFUNC, g_type_name (exten_type), prop_names[i]);
+          goto error;
+        }
+
+      parameters[i].name = prop_names[i];
+
+      g_value_init (&parameters[i].value,
+                    G_VALUE_TYPE (&prop_values[i]));
+      g_value_copy (&prop_values[i], &parameters[i].value);
+    }
+  return TRUE;
+
+error:
+  n_properties = i;
+  for (i = 0; i < n_properties; i++)
+    g_value_unset (&parameters[i].value);
+  return FALSE;
+}
+
 gboolean
 peas_utils_valist_to_parameter_list (GType         exten_type,
                                      const gchar  *first_property,
diff --git a/libpeas/peas-utils.h b/libpeas/peas-utils.h
index 52c6875..249ca75 100644
--- a/libpeas/peas-utils.h
+++ b/libpeas/peas-utils.h
@@ -27,6 +27,13 @@
 #define PEAS_UTILS_C_LOADER_ID  0
 #define PEAS_UTILS_N_LOADERS    4
 
+gboolean  peas_utils_properties_array_to_parameter_list
+                                              (GType          exten_type,
+                                               guint          n_properties,
+                                               const gchar  **prop_names,
+                                               const GValue  *prop_values,
+                                               GParameter    *params);
+
 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
 gboolean  peas_utils_valist_to_parameter_list (GType         exten_type,
                                                const gchar  *first_property,
diff --git a/tests/libpeas/extension-set.c b/tests/libpeas/extension-set.c
index c4d4d3c..3264651 100644
--- a/tests/libpeas/extension-set.c
+++ b/tests/libpeas/extension-set.c
@@ -26,6 +26,7 @@
 #include <stdlib.h>
 
 #include <glib.h>
+#include <glib-object.h>
 #include <libpeas/peas.h>
 
 #include "testing/testing.h"
@@ -146,6 +147,48 @@ test_extension_set_create_valid (PeasEngine *engine)
   g_object_unref (extension_set);
 }
 
+static void
+valid_extension_added_cb (PeasExtensionSet *extension_set,
+                          PeasPluginInfo   *info,
+                          PeasExtension    *extension,
+                          GObject          **obj_ptr)
+{
+  g_object_get (PEAS_ACTIVATABLE (extension), "object", obj_ptr, NULL);
+}
+
+static void
+test_extension_set_create_valid_with_properties (PeasEngine *engine)
+{
+  PeasPluginInfo *info;
+  PeasExtensionSet *extension_set;
+  GValue prop_value = G_VALUE_INIT;
+  GObject *obj, *obj_cmp;
+  const gchar *prop_names[1] = { "object" };
+
+  obj = g_object_new (G_TYPE_OBJECT, NULL);
+  g_value_init (&prop_value, G_TYPE_OBJECT);
+  g_value_set_object (&prop_value, obj);
+
+  extension_set = peas_extension_set_new_with_properties (engine,
+                                                          PEAS_TYPE_ACTIVATABLE,
+                                                          G_N_ELEMENTS (prop_names),
+                                                          prop_names,
+                                                          &prop_value);
+  g_signal_connect (extension_set,
+                    "extension-added",
+                    G_CALLBACK (valid_extension_added_cb),
+                    &obj_cmp);
+  info = peas_engine_get_plugin_info (engine, "builtin");
+
+  g_assert (peas_engine_load_plugin (engine, info));
+  g_assert (obj == obj_cmp);
+
+  g_assert (PEAS_IS_EXTENSION_SET (extension_set));
+  g_object_unref (extension_set);
+  g_value_unset (&prop_value);
+}
+
+
 static void
 test_extension_set_create_invalid (PeasEngine *engine)
 {
@@ -172,6 +215,62 @@ test_extension_set_create_invalid (PeasEngine *engine)
   g_assert (!PEAS_IS_EXTENSION_SET (extension_set));
 }
 
+static void
+test_extension_set_create_invalid_with_properties (PeasEngine *engine)
+{
+  PeasExtensionSet *extension_set;
+  GValue prop_values[2] = { G_VALUE_INIT };
+  const gchar *prop_names[2] = { "object", NULL };
+  const gchar *prop_names_not_exist[1] = { "aleb" };
+  guint n_elements;
+
+  testing_util_push_log_hook ("*property name*should not be NULL.");
+  testing_util_push_log_hook ("*assertion*G_TYPE_IS_INTERFACE*failed");
+  testing_util_push_log_hook ("*should be an initialized GValue.");
+  testing_util_push_log_hook ("*has no property named 'aleb'*");
+
+  g_value_init (&prop_values[0], G_TYPE_POINTER);
+  g_value_set_pointer (&prop_values[0], NULL);
+
+  /* Interface has a NULL property name*/
+  n_elements = G_N_ELEMENTS (prop_values);
+  extension_set = peas_extension_set_new_with_properties (engine,
+                                                          PEAS_TYPE_ACTIVATABLE,
+                                                          n_elements,
+                                                          prop_names,
+                                                          prop_values);
+  g_assert (!PEAS_IS_EXTENSION_SET (extension_set));
+  g_value_unset (&prop_values[0]);
+
+  /* Invalid GType */
+  extension_set = peas_extension_set_new_with_properties (engine,
+                                                          G_TYPE_INVALID,
+                                                          0, NULL, NULL);
+  g_assert (!PEAS_IS_EXTENSION_SET (extension_set));
+
+  /* Uninitialized GValue */
+  n_elements = 1;
+  extension_set = peas_extension_set_new_with_properties (engine,
+                                                          PEAS_TYPE_ACTIVATABLE,
+                                                          n_elements,
+                                                          prop_names,
+                                                          prop_values);
+  g_assert (!PEAS_IS_EXTENSION_SET (extension_set));
+
+  /* Uninitialized GValue*/
+  g_value_init (&prop_values[0], G_TYPE_POINTER);
+  g_value_set_pointer (&prop_values[0], NULL);
+  n_elements = G_N_ELEMENTS (prop_names_not_exist);
+  extension_set = peas_extension_set_new_with_properties (engine,
+                                                          PEAS_TYPE_ACTIVATABLE,
+                                                          n_elements,
+                                                          prop_names_not_exist,
+                                                          prop_values);
+  g_assert (!PEAS_IS_EXTENSION_SET (extension_set));
+  g_value_unset (&prop_values[0]);
+}
+
+
 static void
 test_extension_set_extension_added (PeasEngine *engine)
 {
@@ -345,6 +444,8 @@ main (int    argc,
 
   TEST ("create-valid", create_valid);
   TEST ("create-invalid", create_invalid);
+  TEST ("create-valid-with-properties", create_valid_with_properties);
+  TEST ("create-invalid-with-properties", create_invalid_with_properties);
 
   TEST ("extension-added", extension_added);
   TEST ("extension-removed", extension_removed);


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