[libpeas/proxys: 12/25] Introduce PeasExtensionSet.



commit bf2a2622ef34d2140cff7d08e393fbed0154072f
Author: Steve Frécinaux <code istique net>
Date:   Wed May 19 12:22:21 2010 +0200

    Introduce PeasExtensionSet.
    
    This is a way to handle all the plugins at once, for some specialized
    use. Especially, "PeasActivatable" extensions fit fine with this new
    object.
    
    A way to check that called functions don't expect OUT or INOUT args is
    currently missing.

 .gitignore                   |    2 +
 libpeas/Makefile.am          |   22 ++++-
 libpeas/peas-extension-set.c |  258 ++++++++++++++++++++++++++++++++++++++++++
 libpeas/peas-extension-set.h |   83 ++++++++++++++
 libpeas/peas-marshal.list    |    1 +
 5 files changed, 365 insertions(+), 1 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 935da60..dbad570 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,6 +28,8 @@ Makefile.in
 /data/libpeas-2.0.pc
 /data/libpeasui-2.0.pc
 /depcomp
+/libpeas/peas-marshal.h
+/libpeas/peas-marshal.c
 /peas-demo/peas-demo
 /gnome-doc-utils.make
 /gtk-doc.make
diff --git a/libpeas/Makefile.am b/libpeas/Makefile.am
index f0caed9..247d431 100644
--- a/libpeas/Makefile.am
+++ b/libpeas/Makefile.am
@@ -20,6 +20,7 @@ INST_H_FILES =			\
 	peas-plugin.h		\
 	peas-plugin-info.h	\
 	peas-extension.h	\
+	peas-extension-set.h	\
 	peas-activatable.h	\
 	peas-engine.h
 
@@ -40,17 +41,36 @@ C_FILES =			\
 	peas-plugin-info.c	\
 	peas-plugin-loader.c	\
 	peas-extension.c	\
+	peas-extension-set.c	\
 	peas-activatable.c	\
 	peas-engine.c
 
+BUILT_SOURCES = \
+	peas-marshal.c			\
+	peas-marshal.h
+
 libpeas_2_0_la_SOURCES = 	\
 	$(INST_H_FILES)		\
 	$(NOINST_H_FILES)	\
+	$(BUILT_SOURCES)	\
 	$(C_FILES)
 
 headerdir = $(prefix)/include/libpeas-2.0/libpeas
 header_DATA = $(INST_H_FILES)
 
+peas-marshal.c: peas-marshal.list $(GLIB_GENMARSHAL)
+	$(AM_V_GEN) (echo "#include \"peas-marshal.h\"" && $(GLIB_GENMARSHAL) $< --body --prefix=peas_cclosure_marshal) > $@
+
+peas-marshal.h: peas-marshal.list $(GLIB_GENMARSHAL)
+	$(AM_V_GEN) $(GLIB_GENMARSHAL) $< --header --prefix=peas_cclosure_marshal > $@
+
+EXTRA_DIST = peas-marshal.list
+
+CLEANFILES = $(BUILT_SOURCES)
+
+dist-hook:
+	cd $(distdir); rm -f $(BUILT_SOURCES)
+
 if HAVE_INTROSPECTION
   -include $(INTROSPECTION_MAKEFILE)
   INTROSPECTION_GIRS = Peas-2.0.gir
@@ -69,7 +89,7 @@ if HAVE_INTROSPECTION
   typelibdir = $(libdir)/girepository-1.0
   typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
 
-CLEANFILES = \
+  CLEANFILES += \
 	$(dist_gir_DATA)		\
 	$(typelib_DATA)
 
diff --git a/libpeas/peas-extension-set.c b/libpeas/peas-extension-set.c
new file mode 100644
index 0000000..66e258f
--- /dev/null
+++ b/libpeas/peas-extension-set.c
@@ -0,0 +1,258 @@
+/*
+ * peas-extension-set.c
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 Steve Frécinaux
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include "peas-extension-set.h"
+#include "peas-plugin-info.h"
+#include "peas-marshal.h"
+
+G_DEFINE_TYPE (PeasExtensionSet, peas_extension_set, G_TYPE_OBJECT);
+
+struct _PeasExtensionSetPrivate {
+  PeasEngine *engine;
+  GType exten_type;
+  GList *extensions;
+
+  gulong activate_handler_id;
+  gulong deactivate_handler_id;
+};
+
+typedef struct {
+  PeasPluginInfo *info;
+  PeasExtension *exten;
+} ExtensionItem;
+
+/* Signals */
+enum {
+  EXTENSION_ADDED,
+  EXTENSION_REMOVED,
+  LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+static void
+add_extension (PeasExtensionSet *set,
+               PeasPluginInfo   *info)
+{
+  PeasExtension *exten;
+  ExtensionItem *item;
+
+  /* Let's just ignore inactive plugins... */
+  if (!peas_plugin_info_is_active (info))
+    return;
+
+  exten = peas_engine_get_extension (set->priv->engine, info,
+                                     set->priv->exten_type);
+  if (!exten)
+    return;
+
+/*  peas_plugin_info_ref (info); */
+  g_object_ref (exten);
+
+  item = (ExtensionItem *) g_slice_new (ExtensionItem);
+  item->info = info;
+  item->exten = exten;
+
+  set->priv->extensions = g_list_prepend (set->priv->extensions, item);
+  g_signal_emit (set, signals[EXTENSION_ADDED], 0, info, exten);
+}
+
+static void
+remove_extension_item (PeasExtensionSet *set,
+                       ExtensionItem    *item)
+{
+  g_signal_emit (set, signals[EXTENSION_REMOVED], 0, item->info, item->exten);
+
+/*  peas_plugin_info_unref (item->info); */
+  g_object_unref (item->exten);
+
+  g_slice_free (ExtensionItem, item);
+}
+
+static void
+remove_extension (PeasExtensionSet *set,
+                  PeasPluginInfo   *info)
+{
+  GList *l;
+  ExtensionItem *item;
+
+  for (l = set->priv->extensions; l; l = l->next)
+    {
+      item = (ExtensionItem *) l->data;
+      if (item->info != info)
+        continue;
+
+      remove_extension_item (set, item);
+      set->priv->extensions = g_list_delete_link (set->priv->extensions, l);
+      return;
+    }
+}
+
+static void
+peas_extension_set_init (PeasExtensionSet *set)
+{
+  set->priv = G_TYPE_INSTANCE_GET_PRIVATE (set, PEAS_TYPE_EXTENSION_SET, PeasExtensionSetPrivate);
+}
+
+static void
+peas_extension_set_set_internal_data (PeasExtensionSet *set,
+                                      PeasEngine       *engine,
+                                      GType             exten_type)
+{
+  GList *plugins, *l;
+
+  set->priv->exten_type = exten_type;
+  set->priv->engine = engine;
+  g_object_ref (engine);
+
+  plugins = (GList *) peas_engine_get_plugin_list (engine);
+  for (l = plugins; l; l = l->next)
+    add_extension (set, (PeasPluginInfo *) l->data);
+
+  set->priv->activate_handler_id =
+          g_signal_connect_data (engine, "activate-plugin",
+                                 G_CALLBACK (add_extension), set,
+                                 NULL, G_CONNECT_AFTER | G_CONNECT_SWAPPED);
+  set->priv->deactivate_handler_id =
+          g_signal_connect_data (engine, "deactivate-plugin",
+                                 G_CALLBACK (remove_extension), set,
+                                 NULL, G_CONNECT_SWAPPED);
+}
+
+static void
+peas_extension_set_finalize (GObject *object)
+{
+  PeasExtensionSet *set = PEAS_EXTENSION_SET (object);
+  GList *l;
+
+  g_signal_handler_disconnect (set->priv->engine, set->priv->activate_handler_id);
+  g_signal_handler_disconnect (set->priv->engine, set->priv->deactivate_handler_id);
+
+  for (l = set->priv->extensions; l;)
+    {
+      remove_extension_item (set, (ExtensionItem *) l->data);
+      l = g_list_delete_link (l, l);
+    }
+
+  g_object_unref (set->priv->engine);
+}
+
+static gboolean
+peas_extension_set_call_real (PeasExtensionSet *set,
+                              const gchar      *method,
+                              va_list           args)
+{
+  gboolean ret = TRUE;
+  GList *l;
+  va_list args_copy;
+
+  for (l = set->priv->extensions; l; l = l->next)
+    {
+      G_VA_COPY (args_copy, args);
+      ret = peas_extension_call_valist (((ExtensionItem *) l->data)->exten, method, args_copy) && ret;
+    }
+
+  return ret;
+}
+
+static void
+peas_extension_set_class_init (PeasExtensionSetClass *klass)
+{
+  GType the_type = G_TYPE_FROM_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = peas_extension_set_finalize;
+
+  klass->call = peas_extension_set_call_real;
+
+  signals[EXTENSION_ADDED] =
+    g_signal_new ("extension-added",
+                  the_type,
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (PeasExtensionSetClass, extension_added),
+                  NULL, NULL,
+                  peas_cclosure_marshal_VOID__BOXED_OBJECT,
+                  G_TYPE_NONE,
+                  2,
+                  PEAS_TYPE_PLUGIN_INFO | G_SIGNAL_TYPE_STATIC_SCOPE,
+                  PEAS_TYPE_EXTENSION);
+
+  signals[EXTENSION_REMOVED] =
+    g_signal_new ("extension-removed",
+                  the_type,
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (PeasExtensionSetClass, extension_removed),
+                  NULL, NULL,
+                  peas_cclosure_marshal_VOID__BOXED_OBJECT,
+                  G_TYPE_NONE,
+                  2,
+                  PEAS_TYPE_PLUGIN_INFO | G_SIGNAL_TYPE_STATIC_SCOPE,
+                  PEAS_TYPE_EXTENSION);
+
+  g_type_class_add_private (klass, sizeof (PeasExtensionSetPrivate));
+}
+
+gboolean
+peas_extension_set_call (PeasExtensionSet *set,
+                         const gchar      *method_name,
+                         ...)
+{
+  va_list args;
+  gboolean result;
+
+  va_start (args, method_name);
+  result = peas_extension_set_call_valist (set, method_name, args);
+  va_end (args);
+
+  return result;
+}
+
+gboolean
+peas_extension_set_call_valist (PeasExtensionSet *set,
+                                const gchar      *method_name,
+                                va_list           args)
+{
+  PeasExtensionSetClass *klass;
+
+  g_return_val_if_fail (PEAS_IS_EXTENSION_SET (set), FALSE);
+  g_return_val_if_fail (method_name != NULL, FALSE);
+
+  klass = PEAS_EXTENSION_SET_GET_CLASS (set);
+  return klass->call (set, method_name, args);
+}
+
+PeasExtensionSet *
+peas_extension_set_new (PeasEngine *engine,
+                        GType       exten_type)
+{
+  PeasExtensionSet *set;
+
+  set = PEAS_EXTENSION_SET (g_object_new (PEAS_TYPE_EXTENSION_SET, NULL));
+  peas_extension_set_set_internal_data (set, engine, exten_type);
+
+  return set;
+}
diff --git a/libpeas/peas-extension-set.h b/libpeas/peas-extension-set.h
new file mode 100644
index 0000000..dee226a
--- /dev/null
+++ b/libpeas/peas-extension-set.h
@@ -0,0 +1,83 @@
+/*
+ * peas-extension-set.h
+ * This file is part of libpeas
+ *
+ * Copyright (C) 2010 - Steve Frécinaux
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU Library General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PEAS_EXTENSION_SET_H__
+#define __PEAS_EXTENSION_SET_H__
+
+#include <glib-object.h>
+#include "peas-engine.h"
+
+G_BEGIN_DECLS
+
+/*
+ * Type checking and casting macros
+ */
+#define PEAS_TYPE_EXTENSION_SET            (peas_extension_set_get_type())
+#define PEAS_EXTENSION_SET(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), PEAS_TYPE_EXTENSION_SET, PeasExtensionSet))
+#define PEAS_EXTENSION_SET_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), PEAS_TYPE_EXTENSION_SET, PeasExtensionSetClass))
+#define PEAS_IS_EXTENSION_SET(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), PEAS_TYPE_EXTENSION_SET))
+#define PEAS_IS_EXTENSION_SET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PEAS_TYPE_EXTENSION_SET))
+#define PEAS_EXTENSION_SET_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), PEAS_TYPE_EXTENSION_SET, PeasExtensionSetClass))
+
+typedef struct _PeasExtensionSet        PeasExtensionSet;
+typedef struct _PeasExtensionSetClass   PeasExtensionSetClass;
+typedef struct _PeasExtensionSetPrivate PeasExtensionSetPrivate;
+
+struct _PeasExtensionSet {
+  GObject parent;
+  PeasExtensionSetPrivate *priv;
+};
+
+struct _PeasExtensionSetClass {
+  GObjectClass parent_class;
+
+  /* Virtual public methods */
+  gboolean   (*call)                      (PeasExtensionSet *set,
+                                           const gchar      *method,
+                                           va_list           args);
+
+  /* Signals */
+  void (*extension_added) (PeasExtensionSet *set,
+                           PeasPluginInfo *info,
+                           PeasExtension *exten);
+  void (*extension_removed) (PeasExtensionSet *set,
+                             PeasPluginInfo *info,
+                             PeasExtension *exten);
+};
+
+/*
+ * Public methods
+ */
+GType              peas_extension_set_get_type    (void)  G_GNUC_CONST;
+
+gboolean           peas_extension_set_call        (PeasExtensionSet *set,
+                                                   const gchar      *method_name,
+                                                   ...);
+gboolean           peas_extension_set_call_valist (PeasExtensionSet *set,
+                                                   const gchar      *method_name,
+                                                   va_list           args);
+
+PeasExtensionSet  *peas_extension_set_new         (PeasEngine *engine,
+                                                   GType       exten_type);
+
+G_END_DECLS
+
+#endif /* __PEAS_EXTENSION_SET_H__ */
diff --git a/libpeas/peas-marshal.list b/libpeas/peas-marshal.list
new file mode 100644
index 0000000..82e029e
--- /dev/null
+++ b/libpeas/peas-marshal.list
@@ -0,0 +1 @@
+VOID:BOXED,OBJECT



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