diff options
author | Fabian Orccon <cfoch.fabian@gmail.com> | 2017-01-30 12:01:43 -0500 |
---|---|---|
committer | Christian Hergert <chergert@redhat.com> | 2019-10-24 13:57:32 -0700 |
commit | 936959ba46bd5205d7f439d9168cf8334f9ed2d3 (patch) | |
tree | 62329c79230546b28258d8df4866510043069998 | |
parent | f7aae3257e5654a9c3be9bad85dcf5e7a12be6ed (diff) | |
download | libpeas-936959ba46bd5205d7f439d9168cf8334f9ed2d3.tar.gz |
extension-set: adds peas_extension_set_new_with_properties()
Adds a new introspectable variant of peas_extension_set_new() for
language bindings.
Fixes #8
-rw-r--r-- | libpeas/peas-extension-set.c | 66 | ||||
-rw-r--r-- | libpeas/peas-extension-set.h | 8 | ||||
-rw-r--r-- | libpeas/peas-utils.c | 54 | ||||
-rw-r--r-- | libpeas/peas-utils.h | 7 | ||||
-rw-r--r-- | tests/libpeas/extension-set.c | 101 |
5 files changed, 235 insertions, 1 deletions
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 @@ -651,6 +651,72 @@ peas_extension_set_newv (PeasEngine *engine, } /** + * 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. * @exten_type: the extension #GType. 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 @@ -182,6 +182,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 (¶meters[i].value, + G_VALUE_TYPE (&prop_values[i])); + g_value_copy (&prop_values[i], ¶meters[i].value); + } + return TRUE; + +error: + n_properties = i; + for (i = 0; i < n_properties; i++) + g_value_unset (¶meters[i].value); + return FALSE; +} + +gboolean peas_utils_valist_to_parameter_list (GType exten_type, const gchar *first_property, va_list args, 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" @@ -147,6 +148,48 @@ test_extension_set_create_valid (PeasEngine *engine) } 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) { PeasExtensionSet *extension_set; @@ -173,6 +216,62 @@ test_extension_set_create_invalid (PeasEngine *engine) } 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) { gint active; @@ -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); |