[libpeas] Add support for construct-properties for extensions.



commit 5c6d89f17bdad86bff6fb8d061eb37603235ae7d
Author: Steve Frécinaux <code istique net>
Date:   Mon Jul 12 00:32:51 2010 +0200

    Add support for construct-properties for extensions.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=620057

 libpeas/Makefile.am                        |    2 +
 libpeas/peas-engine.c                      |   61 +++++++++++++++-
 libpeas/peas-engine.h                      |   17 ++++-
 libpeas/peas-extension-set.c               |  104 ++++++++++++++++++++++++++--
 libpeas/peas-extension-set.h               |   17 ++++-
 libpeas/peas-helpers.c                     |   91 ++++++++++++++++++++++++
 libpeas/peas-helpers.h                     |   17 +++++
 libpeas/peas-plugin-loader.c               |    6 +-
 libpeas/peas-plugin-loader.h               |    8 ++-
 libpeasui/peas-ui-plugin-manager.c         |    2 +-
 loaders/c/peas-plugin-loader-c.c           |   37 +++++++---
 loaders/python/peas-plugin-loader-python.c |    6 +-
 loaders/seed/peas-plugin-loader-seed.c     |   66 ++++++++++++++++--
 peas-demo/peas-demo-window.c               |    2 +-
 14 files changed, 400 insertions(+), 36 deletions(-)
---
diff --git a/libpeas/Makefile.am b/libpeas/Makefile.am
index 24e5f90..885d950 100644
--- a/libpeas/Makefile.am
+++ b/libpeas/Makefile.am
@@ -29,6 +29,7 @@ INST_H_FILES =			\
 NOINST_H_FILES =		\
 	peas-debug.h		\
 	peas-dirs.h		\
+	peas-helpers.h		\
 	peas-i18n.h		\
 	peas-introspection.h	\
 	peas-plugin-info-priv.h	\
@@ -37,6 +38,7 @@ NOINST_H_FILES =		\
 C_FILES =			\
 	peas-debug.c		\
 	peas-dirs.c		\
+	peas-helpers.c		\
 	peas-i18n.c		\
 	peas-object-module.c	\
 	peas-introspection.c	\
diff --git a/libpeas/peas-engine.c b/libpeas/peas-engine.c
index 044c195..ae59116 100644
--- a/libpeas/peas-engine.c
+++ b/libpeas/peas-engine.c
@@ -34,6 +34,7 @@
 #include "peas-extension.h"
 #include "peas-dirs.h"
 #include "peas-debug.h"
+#include "peas-helpers.h"
 
 /**
  * SECTION:peas-engine
@@ -883,9 +884,11 @@ peas_engine_provides_extension (PeasEngine     *engine,
 }
 
 PeasExtension *
-peas_engine_get_extension (PeasEngine     *engine,
-                           PeasPluginInfo *info,
-                           GType           extension_type)
+peas_engine_get_extensionv (PeasEngine     *engine,
+                            PeasPluginInfo *info,
+                            GType           extension_type,
+                            guint           n_parameters,
+                            GParameter     *parameters)
 {
   PeasPluginLoader *loader;
 
@@ -893,7 +896,57 @@ peas_engine_get_extension (PeasEngine     *engine,
   g_return_val_if_fail (info != NULL, NULL);
 
   loader = get_plugin_loader (engine, info);
-  return peas_plugin_loader_get_extension (loader, info, extension_type);
+  return peas_plugin_loader_get_extension (loader, info, extension_type,
+                                           n_parameters, parameters);
+}
+
+PeasExtension *
+peas_engine_get_extension_valist (PeasEngine     *engine,
+                                  PeasPluginInfo *info,
+                                  GType           extension_type,
+                                  const gchar    *first_property,
+                                  va_list         var_args)
+{
+  gpointer type_struct;
+  guint n_parameters;
+  GParameter *parameters;
+  PeasExtension *exten;
+
+  type_struct = _g_type_struct_ref (extension_type);
+
+  if (!_valist_to_parameter_list (extension_type, type_struct, first_property,
+                                  var_args, &parameters, &n_parameters))
+    {
+      g_return_val_if_reached (NULL);
+    }
+
+  exten = peas_engine_get_extensionv (engine, info, extension_type,
+                                      n_parameters, parameters);
+
+  while (n_parameters-- > 0)
+    g_value_unset (&parameters[n_parameters].value);
+  g_free (parameters);
+
+  _g_type_struct_unref (extension_type, type_struct);
+
+  return exten;
+}
+
+PeasExtension *
+peas_engine_get_extension (PeasEngine     *engine,
+                           PeasPluginInfo *info,
+                           GType           extension_type,
+                           const gchar    *first_property,
+                           ...)
+{
+  va_list var_args;
+  PeasExtension *exten;
+
+  va_start (var_args, first_property);
+  exten = peas_engine_get_extension_valist (engine, info, extension_type, first_property, var_args);
+  va_end (var_args);
+
+  return exten;
 }
 
 /**
diff --git a/libpeas/peas-engine.h b/libpeas/peas-engine.h
index f1e80f8..d54f497 100644
--- a/libpeas/peas-engine.h
+++ b/libpeas/peas-engine.h
@@ -87,9 +87,24 @@ void              peas_engine_garbage_collect     (PeasEngine      *engine);
 gboolean          peas_engine_provides_extension  (PeasEngine      *engine,
                                                    PeasPluginInfo  *info,
                                                    GType            extension_type);
+
+
+PeasExtension    *peas_engine_get_extensionv      (PeasEngine      *engine,
+                                                   PeasPluginInfo  *info,
+                                                   GType            extension_type,
+                                                   guint            n_parameters,
+                                                   GParameter      *parameters);
+PeasExtension    *peas_engine_get_extension_valist
+                                                  (PeasEngine      *engine,
+                                                   PeasPluginInfo  *info,
+                                                   GType            extension_type,
+                                                   const gchar     *first_property,
+                                                   va_list          var_args);
 PeasExtension    *peas_engine_get_extension       (PeasEngine      *engine,
                                                    PeasPluginInfo  *info,
-                                                   GType            extension_type);
+                                                   GType            extension_type,
+                                                   const gchar     *first_property,
+                                                   ...);
 
 
 G_END_DECLS
diff --git a/libpeas/peas-extension-set.c b/libpeas/peas-extension-set.c
index c8f2cb3..9713ae0 100644
--- a/libpeas/peas-extension-set.c
+++ b/libpeas/peas-extension-set.c
@@ -28,6 +28,7 @@
 #include "peas-extension-set.h"
 #include "peas-plugin-info.h"
 #include "peas-marshal.h"
+#include "peas-helpers.h"
 
 /**
  * SECTION:peas-extension-set
@@ -51,6 +52,9 @@ G_DEFINE_TYPE (PeasExtensionSet, peas_extension_set, G_TYPE_OBJECT);
 struct _PeasExtensionSetPrivate {
   PeasEngine *engine;
   GType exten_type;
+  guint n_parameters;
+  GParameter *parameters;
+
   GList *extensions;
 
   gulong load_handler_id;
@@ -75,10 +79,28 @@ static guint signals[LAST_SIGNAL];
 enum {
   PROP_0,
   PROP_ENGINE,
-  PROP_EXTENSION_TYPE
+  PROP_EXTENSION_TYPE,
+  PROP_CONSTRUCT_PROPERTIES
 };
 
 static void
+set_construct_properties (PeasExtensionSet *set,
+                          PeasParameterArray *array)
+{
+  unsigned i;
+
+  set->priv->n_parameters = array->n_parameters;
+
+  set->priv->parameters = g_new0 (GParameter, array->n_parameters);
+  for (i = 0; i < array->n_parameters; i++)
+    {
+      set->priv->parameters[i].name = g_intern_string (array->parameters[i].name);
+      g_value_init (&set->priv->parameters[i].value, G_VALUE_TYPE (&array->parameters[i].value));
+      g_value_copy (&array->parameters[i].value, &set->priv->parameters[i].value);
+    }
+}
+
+static void
 peas_extension_set_set_property (GObject      *object,
                                  guint         prop_id,
                                  const GValue *value,
@@ -95,6 +117,9 @@ peas_extension_set_set_property (GObject      *object,
     case PROP_EXTENSION_TYPE:
       set->priv->exten_type = g_value_get_gtype (value);
       break;
+    case PROP_CONSTRUCT_PROPERTIES:
+      set_construct_properties (set, g_value_get_pointer (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     }
@@ -132,8 +157,10 @@ add_extension (PeasExtensionSet *set,
   if (!peas_plugin_info_is_loaded (info))
     return;
 
-  exten = peas_engine_get_extension (set->priv->engine, info,
-                                     set->priv->exten_type);
+  exten = peas_engine_get_extensionv (set->priv->engine, info,
+                                      set->priv->exten_type,
+                                      set->priv->n_parameters,
+                                      set->priv->parameters);
   if (!exten)
     return;
 
@@ -221,6 +248,13 @@ peas_extension_set_finalize (GObject *object)
       l = g_list_delete_link (l, l);
     }
 
+  if (set->priv->parameters != NULL)
+    {
+      while (set->priv->n_parameters-- > 0)
+        g_value_unset (&set->priv->parameters[set->priv->n_parameters].value);
+      g_free (set->priv->parameters);
+    }
+
   g_object_unref (set->priv->engine);
 }
 
@@ -297,6 +331,14 @@ peas_extension_set_class_init (PeasExtensionSetClass *klass)
                                                        G_PARAM_CONSTRUCT_ONLY |
                                                        G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (object_class, PROP_CONSTRUCT_PROPERTIES,
+                                   g_param_spec_pointer ("construct-properties",
+                                                         "Construct Properties",
+                                                         "The properties to pass the extensions when creating them",
+                                                         G_PARAM_WRITABLE |
+                                                         G_PARAM_CONSTRUCT_ONLY |
+                                                         G_PARAM_STATIC_STRINGS));
+
   g_type_class_add_private (klass, sizeof (PeasExtensionSetPrivate));
 }
 
@@ -362,11 +404,63 @@ peas_extension_set_call_valist (PeasExtensionSet *set,
  * the plugins loaded in @engine.
  */
 PeasExtensionSet *
-peas_extension_set_new (PeasEngine *engine,
-                        GType       exten_type)
+peas_extension_set_newv (PeasEngine *engine,
+                         GType       exten_type,
+                         guint       n_parameters,
+                         GParameter *parameters)
 {
+  PeasParameterArray construct_properties = { n_parameters, parameters };
+
   return PEAS_EXTENSION_SET (g_object_new (PEAS_TYPE_EXTENSION_SET,
                                            "engine", engine,
                                            "extension-type", exten_type,
+                                           "construct-properties", &construct_properties,
                                            NULL));
 }
+
+PeasExtensionSet *
+peas_extension_set_new_valist (PeasEngine  *engine,
+                               GType        exten_type,
+                               const gchar *first_property,
+                               va_list      var_args)
+{
+  gpointer type_struct;
+  GParameter *parameters;
+  guint n_parameters;
+  PeasExtensionSet *set;
+
+  type_struct = _g_type_struct_ref (exten_type);
+
+  if (!_valist_to_parameter_list (exten_type, type_struct, first_property,
+                                  var_args, &parameters, &n_parameters))
+    {
+      /* WARNING */
+      g_return_val_if_reached (NULL);
+    }
+
+  set = peas_extension_set_newv (engine, exten_type, n_parameters, parameters);
+
+  while (n_parameters-- > 0)
+    g_value_unset (&parameters[n_parameters].value);
+  g_free (parameters);
+
+  _g_type_struct_unref (exten_type, type_struct);
+
+  return set;
+}
+
+PeasExtensionSet *
+peas_extension_set_new (PeasEngine  *engine,
+                        GType        exten_type,
+                        const gchar *first_property,
+                        ...)
+{
+  va_list var_args;
+  PeasExtensionSet *set;
+
+  va_start (var_args, first_property);
+  set = peas_extension_set_new_valist (engine, exten_type, first_property, var_args);
+  va_end (var_args);
+
+  return set;
+}
diff --git a/libpeas/peas-extension-set.h b/libpeas/peas-extension-set.h
index 7925c27..8254ca5 100644
--- a/libpeas/peas-extension-set.h
+++ b/libpeas/peas-extension-set.h
@@ -70,6 +70,11 @@ struct _PeasExtensionSetClass {
                                            PeasExtension    *exten);
 };
 
+typedef struct _PeasParameterArray {
+  guint n_parameters;
+  GParameter *parameters;
+} PeasParameterArray;
+
 /*
  * Public methods
  */
@@ -82,8 +87,18 @@ gboolean           peas_extension_set_call_valist (PeasExtensionSet *set,
                                                    const gchar      *method_name,
                                                    va_list           args);
 
+PeasExtensionSet  *peas_extension_set_newv        (PeasEngine       *engine,
+                                                   GType             exten_type,
+                                                   guint             n_parameters,
+                                                   GParameter       *parameter);
+PeasExtensionSet  *peas_extension_set_new_valist  (PeasEngine       *engine,
+                                                   GType             exten_type,
+                                                   const gchar      *first_property,
+                                                   va_list           var_args);
 PeasExtensionSet  *peas_extension_set_new         (PeasEngine       *engine,
-                                                   GType             exten_type);
+                                                   GType             exten_type,
+                                                   const gchar      *first_property,
+                                                   ...);
 
 G_END_DECLS
 
diff --git a/libpeas/peas-helpers.c b/libpeas/peas-helpers.c
new file mode 100644
index 0000000..97cd748
--- /dev/null
+++ b/libpeas/peas-helpers.c
@@ -0,0 +1,91 @@
+#include <gobject/gvaluecollector.h>
+#include "peas-helpers.h"
+
+gpointer
+_g_type_struct_ref (GType the_type)
+{
+  if (G_TYPE_IS_INTERFACE (the_type))
+    return g_type_default_interface_ref (the_type);
+  else if (G_TYPE_IS_OBJECT (the_type))
+    return g_type_class_ref (the_type);
+  else
+    g_return_val_if_reached (NULL);
+}
+
+void
+_g_type_struct_unref (GType    the_type,
+                      gpointer type_struct)
+{
+  if (G_TYPE_IS_INTERFACE (the_type))
+    g_type_default_interface_unref (type_struct);
+  else if (G_TYPE_IS_OBJECT (the_type))
+    g_type_class_unref (type_struct);
+  else
+    g_return_if_reached ();
+}
+
+static GParamSpec *
+_g_type_struct_find_property (GType        the_type,
+                              gpointer     type_struct,
+                              const gchar *property_name)
+{
+  if (G_TYPE_IS_INTERFACE (the_type))
+    return g_object_interface_find_property (type_struct, property_name);
+  else if (G_TYPE_IS_OBJECT (the_type))
+    return g_object_class_find_property (type_struct, property_name);
+  else
+    g_return_val_if_reached (NULL);
+}
+
+gboolean
+_valist_to_parameter_list (GType         the_type,
+                           gpointer      type_struct,
+                           const gchar  *first_property_name,
+                           va_list       args,
+                           GParameter  **params,
+                           guint        *n_params)
+{
+  const gchar *name;
+  guint n_allocated_params;
+
+  g_return_val_if_fail (type_struct != NULL, FALSE);
+
+  *n_params = 0;
+  n_allocated_params = 16;
+  *params = g_new0 (GParameter, n_allocated_params);
+
+  name = first_property_name;
+  while (name)
+    {
+      gchar *error = NULL;
+      GParamSpec *pspec = _g_type_struct_find_property (the_type, type_struct, name);
+
+      if (!pspec)
+        {
+          g_warning ("%s: type '%s' has no property named '%s'",
+                     G_STRFUNC, g_type_name (the_type), name);
+          return FALSE;
+        }
+
+      if (*n_params >= n_allocated_params)
+        {
+          n_allocated_params += 16;
+          *params = g_renew (GParameter, *params, n_allocated_params);
+        }
+
+      (*params)[*n_params].name = name;
+      G_VALUE_COLLECT_INIT (&(*params)[*n_params].value, pspec->value_type,
+                            args, 0, &error);
+      if (error)
+        {
+          g_warning ("%s: %s", G_STRFUNC, error);
+          g_free (error);
+          g_value_unset (&(*params)[*n_params].value);
+          return FALSE;
+        }
+      (*n_params)++;
+      name = va_arg (args, gchar*);
+    }
+
+  return TRUE;
+}
diff --git a/libpeas/peas-helpers.h b/libpeas/peas-helpers.h
new file mode 100644
index 0000000..3bfce28
--- /dev/null
+++ b/libpeas/peas-helpers.h
@@ -0,0 +1,17 @@
+#ifndef __PEAS_HELPERS_H__
+#define __PEAS_HELPERS_H__
+
+#include <glib-object.h>
+
+gpointer  _g_type_struct_ref        (GType         the_type);
+void      _g_type_struct_unref      (GType         the_type,
+                                     gpointer      type_struct);
+
+gboolean  _valist_to_parameter_list (GType         the_type,
+                                     gpointer      type_struct,
+                                     const gchar  *first_property_name,
+                                     va_list       var_args,
+                                     GParameter  **params,
+                                     guint        *n_params);
+
+#endif /* __PEAS_HELPERS_H__ */
diff --git a/libpeas/peas-plugin-loader.c b/libpeas/peas-plugin-loader.c
index 3d080eb..2399da9 100644
--- a/libpeas/peas-plugin-loader.c
+++ b/libpeas/peas-plugin-loader.c
@@ -97,7 +97,9 @@ peas_plugin_loader_provides_extension (PeasPluginLoader *loader,
 PeasExtension *
 peas_plugin_loader_get_extension (PeasPluginLoader *loader,
                                   PeasPluginInfo   *info,
-                                  GType             ext_type)
+                                  GType             ext_type,
+                                  guint             n_parameters,
+                                  GParameter       *parameters)
 {
   PeasPluginLoaderClass *klass;
 
@@ -106,7 +108,7 @@ peas_plugin_loader_get_extension (PeasPluginLoader *loader,
   klass = PEAS_PLUGIN_LOADER_GET_CLASS (loader);
   g_return_val_if_fail (klass->get_extension != NULL, NULL);
 
-  return klass->get_extension (loader, info, ext_type);
+  return klass->get_extension (loader, info, ext_type, n_parameters, parameters);
 }
 
 void
diff --git a/libpeas/peas-plugin-loader.h b/libpeas/peas-plugin-loader.h
index acabfd4..cf78d86 100644
--- a/libpeas/peas-plugin-loader.h
+++ b/libpeas/peas-plugin-loader.h
@@ -58,7 +58,9 @@ struct _PeasPluginLoaderClass {
                                            GType             ext_type);
   PeasExtension *(*get_extension)         (PeasPluginLoader *loader,
                                            PeasPluginInfo   *info,
-                                           GType             ext_type);
+                                           GType             ext_type,
+                                           guint             n_parameters,
+                                           GParameter       *parameters);
 
   void          (*garbage_collect)        (PeasPluginLoader *loader);
 };
@@ -78,7 +80,9 @@ gboolean      peas_plugin_loader_provides_extension   (PeasPluginLoader *loader,
                                                        GType             ext_type);
 PeasExtension *peas_plugin_loader_get_extension       (PeasPluginLoader *loader,
                                                        PeasPluginInfo   *info,
-                                                       GType             ext_type);
+                                                       GType             ext_type,
+                                                       guint             n_parameters,
+                                                       GParameter       *parameters);
 void          peas_plugin_loader_garbage_collect      (PeasPluginLoader *loader);
 
 G_END_DECLS
diff --git a/libpeasui/peas-ui-plugin-manager.c b/libpeasui/peas-ui-plugin-manager.c
index 96c90c6..c7ff538 100644
--- a/libpeasui/peas-ui-plugin-manager.c
+++ b/libpeasui/peas-ui-plugin-manager.c
@@ -218,7 +218,7 @@ show_configure_cb (GtkWidget           *widget,
   info = peas_ui_plugin_manager_view_get_selected_plugin (view);
   g_return_if_fail (info != NULL);
 
-  exten = peas_engine_get_extension (pm->priv->engine, info, PEAS_UI_TYPE_CONFIGURABLE);
+  exten = peas_engine_get_extension (pm->priv->engine, info, PEAS_UI_TYPE_CONFIGURABLE, NULL);
   g_return_if_fail (PEAS_IS_EXTENSION (exten));
 
   peas_extension_call (exten, "create_configure_widget", &conf_widget);
diff --git a/loaders/c/peas-plugin-loader-c.c b/loaders/c/peas-plugin-loader-c.c
index 827b845..40d334d 100644
--- a/loaders/c/peas-plugin-loader-c.c
+++ b/loaders/c/peas-plugin-loader-c.c
@@ -23,11 +23,13 @@
 #include <config.h>
 #endif
 
+#include <string.h>
+#include <gmodule.h>
+
 #include "peas-plugin-loader-c.h"
 #include "peas-extension-c.h"
 #include <libpeas/peas-object-module.h>
 #include <libpeas/peas-extension-base.h>
-#include <gmodule.h>
 
 struct _PeasPluginLoaderCPrivate
 {
@@ -109,24 +111,39 @@ peas_plugin_loader_c_provides_extension  (PeasPluginLoader *loader,
 static PeasExtension *
 peas_plugin_loader_c_get_extension (PeasPluginLoader *loader,
                                     PeasPluginInfo   *info,
-                                    GType             exten_type)
+                                    GType             exten_type,
+                                    guint             n_parameters,
+                                    GParameter       *parameters)
 {
   PeasPluginLoaderC *cloader = PEAS_PLUGIN_LOADER_C (loader);
   PeasObjectModule *module;
-  GParameter info_param = { 0 };
+  GParameter *exten_parameters;
   gpointer instance;
 
   module = (PeasObjectModule *) g_hash_table_lookup (cloader->priv->loaded_plugins,
                                                      info);
   g_return_val_if_fail (module != NULL, NULL);
 
-  info_param.name = "plugin-info";
-  g_value_init (&info_param.value, PEAS_TYPE_PLUGIN_INFO);
-  g_value_set_boxed (&info_param.value, info);
-
-  instance = peas_object_module_create_object (module, exten_type, 1, &info_param);
-
-  g_value_unset (&info_param.value);
+  /* We want to add a "plugin-info" property so we can pass it to the extension
+   * if it inherits from PeasExtensionBase. No need to actually "duplicate" the
+   * GValues, a memcpy is sufficient as the source GValues are longer lived
+   * than our local copy. */
+  exten_parameters = g_new (GParameter, n_parameters + 1);
+  memcpy (exten_parameters, parameters, sizeof (GParameter) * n_parameters);
+
+  /* Initialize our additional property */
+  exten_parameters[n_parameters].name = g_intern_static_string ("plugin-info");
+  memset (&exten_parameters[n_parameters].value, 0, sizeof (GValue));
+  g_value_init (&exten_parameters[n_parameters].value, PEAS_TYPE_PLUGIN_INFO);
+  g_value_set_boxed (&exten_parameters[n_parameters].value, info);
+
+  instance = peas_object_module_create_object (module,
+                                               exten_type,
+                                               n_parameters + 1,
+                                               exten_parameters);
+
+  g_value_unset (&exten_parameters[n_parameters].value);
+  g_free (exten_parameters);
 
   if (instance == NULL)
     {
diff --git a/loaders/python/peas-plugin-loader-python.c b/loaders/python/peas-plugin-loader-python.c
index cf3aba0..4198a56 100644
--- a/loaders/python/peas-plugin-loader-python.c
+++ b/loaders/python/peas-plugin-loader-python.c
@@ -138,7 +138,9 @@ peas_plugin_loader_python_provides_extension (PeasPluginLoader *loader,
 static PeasExtension *
 peas_plugin_loader_python_get_extension (PeasPluginLoader *loader,
                                          PeasPluginInfo   *info,
-                                         GType             exten_type)
+                                         GType             exten_type,
+                                         guint             n_parameters,
+                                         GParameter       *parameters)
 {
   PeasPluginLoaderPython *pyloader = PEAS_PLUGIN_LOADER_PYTHON (loader);
   PythonInfo *pyinfo;
@@ -190,7 +192,7 @@ peas_plugin_loader_python_get_extension (PeasPluginLoader *loader,
       return NULL;
     }
 
-  pygobject_construct (pygobject, NULL);
+  pygobject_constructv (pygobject, n_parameters, parameters);
 
   if (pygobject->obj == NULL)
     {
diff --git a/loaders/seed/peas-plugin-loader-seed.c b/loaders/seed/peas-plugin-loader-seed.c
index 5b4e78e..5fc1e25 100644
--- a/loaders/seed/peas-plugin-loader-seed.c
+++ b/loaders/seed/peas-plugin-loader-seed.c
@@ -24,6 +24,10 @@
 #endif
 
 #include <seed.h>
+/* FIXME: Seed Bug 624560 */
+SeedValue seed_value_from_gvalue (SeedContext    ctx,
+                                  GValue        *gval,
+                                  SeedException *exception);
 
 #include "peas-plugin-loader-seed.h"
 #include "peas-extension-seed.h"
@@ -151,29 +155,77 @@ peas_plugin_loader_seed_provides_extension  (PeasPluginLoader *loader,
 static PeasExtension *
 peas_plugin_loader_seed_get_extension (PeasPluginLoader *loader,
                                        PeasPluginInfo   *info,
-                                       GType             exten_type)
+                                       GType             exten_type,
+                                       guint             n_parameters,
+                                       GParameter       *parameters)
 {
   PeasPluginLoaderSeed *sloader = PEAS_PLUGIN_LOADER_SEED (loader);
   SeedInfo *sinfo;
-  SeedValue extension;
+  SeedValue extension_methods, extension;
+  gchar **property_names;
+  guint i, j;
 
   sinfo = (SeedInfo *) g_hash_table_lookup (sloader->loaded_plugins, info);
   if (!sinfo)
     return NULL;
 
-  extension = seed_object_get_property (sinfo->context,
-                                        sinfo->extensions,
-                                        g_type_name (exten_type));
-  if (!extension)
+  /* FIXME: instantiate new object and pass the parameters */
+  extension_methods = seed_object_get_property (sinfo->context,
+                                                sinfo->extensions,
+                                                g_type_name (exten_type));
+  if (!extension_methods)
     return NULL;
 
-  if (!seed_value_is_object (sinfo->context, extension))
+  if (!seed_value_is_object (sinfo->context, extension_methods))
     {
       g_warning ("Extension '%s' in plugin '%s' is not a Seed object",
                  g_type_name (exten_type), peas_plugin_info_get_module_name (info));
       return NULL;
     }
 
+  /* Copy the original extension_methods object to a new specific object. */
+  extension = seed_make_object (sinfo->context, NULL, NULL);
+  property_names = seed_object_copy_property_names (sinfo->context,
+                                                    extension_methods);
+  for (i = 0; property_names[i] != NULL; i++)
+    {
+      SeedValue value;
+
+      value = seed_object_get_property (sinfo->context,
+                                        extension_methods,
+                                        property_names[i]);
+      seed_object_set_property (sinfo->context,
+                                extension,
+                                property_names[i],
+                                value);
+    }
+
+  /* Set the properties as well */
+  for (i = 0; i < n_parameters; i++)
+    {
+      gchar *key;
+      SeedValue value;
+
+      /* We want to normalize the property names to have a '_' instead of the
+       * conventional '-', to make them accessible through this.property_name */
+      key = g_strdup (parameters[i].name);
+      for (j = 0; key[j] != '\0'; j++)
+        if (key[j] == '-')
+          key[j] = '_';
+
+      value = seed_value_from_gvalue (sinfo->context,
+                                      &parameters[i].value,
+                                      NULL);
+      seed_object_set_property (sinfo->context,
+                                extension,
+                                key,
+                                value);
+
+      g_free (key);
+    }
+
+  g_strfreev (property_names);
+
   return peas_extension_seed_new (exten_type, sinfo->context, extension);
 }
 
diff --git a/peas-demo/peas-demo-window.c b/peas-demo/peas-demo-window.c
index 5147456..f61debe 100644
--- a/peas-demo/peas-demo-window.c
+++ b/peas-demo/peas-demo-window.c
@@ -77,7 +77,7 @@ demo_window_set_data (DemoWindow *dw,
   dw->engine = engine;
   g_object_ref (dw->engine);
 
-  dw->exten_set = peas_extension_set_new (engine, PEAS_TYPE_ACTIVATABLE);
+  dw->exten_set = peas_extension_set_new (engine, PEAS_TYPE_ACTIVATABLE, NULL);
 
   peas_extension_set_call (dw->exten_set, "activate", dw);
 



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