[libpeas] Add basic support for plugin dependencies.
- From: Steve Frécinaux <sfre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libpeas] Add basic support for plugin dependencies.
- Date: Tue, 27 Jul 2010 18:54:14 +0000 (UTC)
commit d230359cd8fb58b6628f4b2faaac515202fd975f
Author: Steve Frécinaux <code istique net>
Date: Sat Jul 24 01:09:07 2010 +0200
Add basic support for plugin dependencies.
https://bugzilla.gnome.org/show_bug.cgi?id=625156
configure.ac | 1 +
docs/reference/libpeas-sections.txt | 2 +
libpeas/peas-engine.c | 47 ++++++-
libpeas/peas-plugin-info.c | 42 ++++++
libpeas/peas-plugin-info.h | 3 +
peas-demo/plugins/Makefile.am | 2 +-
peas-demo/plugins/secondtime/Makefile.am | 19 +++
peas-demo/plugins/secondtime/second-time.c | 145 ++++++++++++++++++++
peas-demo/plugins/secondtime/second-time.h | 35 +++++
.../plugins/secondtime/secondtime.peasdemo-plugin | 9 ++
10 files changed, 299 insertions(+), 6 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 1d5086a..e89f9d0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -298,6 +298,7 @@ peas-demo/Makefile
peas-demo/plugins/Makefile
peas-demo/plugins/helloworld/Makefile
peas-demo/plugins/pythonhello/Makefile
+peas-demo/plugins/secondtime/Makefile
peas-demo/plugins/seedhello/Makefile
po/Makefile.in
])
diff --git a/docs/reference/libpeas-sections.txt b/docs/reference/libpeas-sections.txt
index 62b937e..9196867 100644
--- a/docs/reference/libpeas-sections.txt
+++ b/docs/reference/libpeas-sections.txt
@@ -185,6 +185,8 @@ peas_plugin_info_is_builtin
peas_plugin_info_get_module_name
peas_plugin_info_get_module_dir
peas_plugin_info_get_data_dir
+peas_plugin_info_get_dependencies
+peas_plugin_info_has_dependency
peas_plugin_info_get_name
peas_plugin_info_get_description
peas_plugin_info_get_icon_name
diff --git a/libpeas/peas-engine.c b/libpeas/peas-engine.c
index 8cbab4e..336fad2 100644
--- a/libpeas/peas-engine.c
+++ b/libpeas/peas-engine.c
@@ -754,6 +754,9 @@ static gboolean
load_plugin (PeasEngine *engine,
PeasPluginInfo *info)
{
+ const gchar **dependencies;
+ PeasPluginInfo *dep_info;
+ guint i;
PeasPluginLoader *loader;
if (peas_plugin_info_is_loaded (info))
@@ -762,6 +765,24 @@ load_plugin (PeasEngine *engine,
if (!peas_plugin_info_is_available (info))
return FALSE;
+ /* We set the plugin info as loaded before trying to load the dependencies,
+ * to make sure we won't have an infinite loop. */
+ info->loaded = TRUE;
+
+ dependencies = peas_plugin_info_get_dependencies (info);
+ for (i = 0; dependencies[i] != NULL; i++)
+ {
+ dep_info = peas_engine_get_plugin_info (engine, dependencies[i]);
+ if (!dep_info)
+ {
+ g_warning ("Plugin not found: %s", dependencies[i]);
+ return FALSE;
+ }
+
+ if (!peas_engine_load_plugin (engine, dep_info))
+ return FALSE;
+ }
+
loader = get_plugin_loader (engine, info);
if (loader == NULL)
@@ -772,11 +793,10 @@ load_plugin (PeasEngine *engine,
return FALSE;
}
- info->loaded = peas_plugin_loader_load (loader, info);
-
- if (info->loaded == FALSE)
+ if (!peas_plugin_loader_load (loader, info))
{
g_warning ("Error loading plugin '%s'", info->name);
+ info->loaded = FALSE;
info->available = FALSE;
return FALSE;
}
@@ -824,20 +844,37 @@ static void
peas_engine_unload_plugin_real (PeasEngine *engine,
PeasPluginInfo *info)
{
+ GList *item;
+ const gchar *module_name;
PeasPluginLoader *loader;
if (!peas_plugin_info_is_loaded (info) ||
!peas_plugin_info_is_available (info))
return;
+ /* We set the plugin info as unloaded before trying to unload the
+ * dependants, to make sure we won't have an infinite loop. */
+ info->loaded = FALSE;
+
+ /* First unload all the dependant plugins */
+ module_name = peas_plugin_info_get_module_name (info);
+ for (item = engine->priv->plugin_list; item; item = item->next)
+ {
+ PeasPluginInfo *other_info = PEAS_PLUGIN_INFO (item->data);
+
+ if (!peas_plugin_info_is_loaded (other_info))
+ continue;
+
+ if (peas_plugin_info_has_dependency (other_info, module_name))
+ peas_engine_unload_plugin (engine, other_info);
+ }
+
/* find the loader and tell it to gc and unload the plugin */
loader = get_plugin_loader (engine, info);
peas_plugin_loader_garbage_collect (loader);
peas_plugin_loader_unload (loader, info);
- info->loaded = FALSE;
-
g_object_notify (G_OBJECT (engine), "loaded-plugins");
}
diff --git a/libpeas/peas-plugin-info.c b/libpeas/peas-plugin-info.c
index a3dd0da..68931c7 100644
--- a/libpeas/peas-plugin-info.c
+++ b/libpeas/peas-plugin-info.c
@@ -445,6 +445,48 @@ peas_plugin_info_get_data_dir (const PeasPluginInfo *info)
}
/**
+ * peas_plugin_info_get_dependencies:
+ * @info: A #PeasPluginInfo.
+ *
+ * Gets the dependencies of the plugin.
+ *
+ * Returns: the plugin's dependencies.
+ */
+const gchar **
+peas_plugin_info_get_dependencies (const PeasPluginInfo *info)
+{
+ g_return_val_if_fail (info != NULL, NULL);
+
+ return (const gchar **) info->dependencies;
+}
+
+/**
+ * peas_plugin_info_has_dependency:
+ * @info: A #PeasPluginInfo.
+ * @module_name: The name of the plugin to check.
+ *
+ * Check if the plugin depends on another plugin.
+ *
+ * Returns: whether the plugin depends on the plugin @module_name.
+ */
+gboolean
+peas_plugin_info_has_dependency (const PeasPluginInfo *info,
+ const gchar *module_name)
+{
+ guint i;
+
+ g_return_val_if_fail (info != NULL, FALSE);
+ g_return_val_if_fail (module_name != NULL, FALSE);
+
+ for (i = 0; info->dependencies[i] != NULL; i++)
+ if (g_ascii_strcasecmp (module_name, info->dependencies[i]) == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+
+/**
* peas_plugin_info_get_name:
* @info: A #PeasPluginInfo.
*
diff --git a/libpeas/peas-plugin-info.h b/libpeas/peas-plugin-info.h
index d60deab..10756d1 100644
--- a/libpeas/peas-plugin-info.h
+++ b/libpeas/peas-plugin-info.h
@@ -46,6 +46,9 @@ gboolean peas_plugin_info_is_builtin (const PeasPluginInfo *info);
const gchar *peas_plugin_info_get_module_name (const PeasPluginInfo *info);
const gchar *peas_plugin_info_get_module_dir (const PeasPluginInfo *info);
const gchar *peas_plugin_info_get_data_dir (const PeasPluginInfo *info);
+const gchar **peas_plugin_info_get_dependencies (const PeasPluginInfo *info);
+gboolean peas_plugin_info_has_dependency (const PeasPluginInfo *info,
+ const gchar *name);
const gchar *peas_plugin_info_get_name (const PeasPluginInfo *info);
const gchar *peas_plugin_info_get_description (const PeasPluginInfo *info);
diff --git a/peas-demo/plugins/Makefile.am b/peas-demo/plugins/Makefile.am
index 3ce8c21..d2824e1 100644
--- a/peas-demo/plugins/Makefile.am
+++ b/peas-demo/plugins/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = helloworld
+SUBDIRS = helloworld secondtime
if ENABLE_PYTHON
SUBDIRS += pythonhello
diff --git a/peas-demo/plugins/secondtime/Makefile.am b/peas-demo/plugins/secondtime/Makefile.am
new file mode 100644
index 0000000..3a1c4c5
--- /dev/null
+++ b/peas-demo/plugins/secondtime/Makefile.am
@@ -0,0 +1,19 @@
+plugindir = $(libdir)/peas-demo/plugins/secondtime
+
+INCLUDES = \
+ -I$(top_srcdir) \
+ $(PEAS_CFLAGS) \
+ $(PEASUI_CFLAGS)
+
+plugin_LTLIBRARIES = libsecondtime.la
+
+libsecondtime_la_SOURCES = \
+ second-time.h \
+ second-time.c
+
+libsecondtime_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS)
+libsecondtime_la_LIBADD = $(PEAS_LIBS) $(PEASUI_LIBS)
+
+plugin_DATA = secondtime.peasdemo-plugin
+
+EXTRA_DIST = $(plugin_DATA)
diff --git a/peas-demo/plugins/secondtime/second-time.c b/peas-demo/plugins/secondtime/second-time.c
new file mode 100644
index 0000000..fdb7f95
--- /dev/null
+++ b/peas-demo/plugins/secondtime/second-time.c
@@ -0,0 +1,145 @@
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+#include <gtk/gtk.h>
+
+#include <libpeas/peas.h>
+
+#include "second-time.h"
+
+static void peas_activatable_iface_init (PeasActivatableInterface *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (PeasDemoSecondTime,
+ peasdemo_second_time,
+ PEAS_TYPE_EXTENSION_BASE,
+ 0,
+ G_IMPLEMENT_INTERFACE_DYNAMIC (PEAS_TYPE_ACTIVATABLE,
+ peas_activatable_iface_init))
+
+enum {
+ PROP_0,
+ PROP_OBJECT
+};
+
+static void
+peasdemo_second_time_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PeasDemoSecondTime *plugin = PEASDEMO_SECOND_TIME (object);
+
+ switch (prop_id)
+ {
+ case PROP_OBJECT:
+ plugin->window = GTK_WIDGET (g_value_dup_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+peasdemo_second_time_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ PeasDemoSecondTime *plugin = PEASDEMO_SECOND_TIME (object);
+
+ switch (prop_id)
+ {
+ case PROP_OBJECT:
+ g_value_set_object (value, plugin->window);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+static void
+peasdemo_second_time_init (PeasDemoSecondTime *plugin)
+{
+ g_debug (G_STRFUNC);
+}
+
+static void
+peasdemo_second_time_finalize (GObject *object)
+{
+ PeasDemoSecondTime *plugin = PEASDEMO_SECOND_TIME (object);
+
+ g_debug (G_STRFUNC);
+
+ g_object_unref (plugin->label);
+
+ G_OBJECT_CLASS (peasdemo_second_time_parent_class)->finalize (object);
+}
+
+static GtkBox *
+get_box (GtkWidget *window)
+{
+ return GTK_BOX (gtk_bin_get_child (GTK_BIN (window)));
+}
+
+static void
+peasdemo_second_time_activate (PeasActivatable *activatable)
+{
+ PeasDemoSecondTime *plugin = PEASDEMO_SECOND_TIME (activatable);
+ GtkWidget *label;
+
+ g_debug (G_STRFUNC);
+
+ plugin->label = gtk_label_new ("A second time!");
+ gtk_box_pack_start (get_box (plugin->window), plugin->label, 1, 1, 0);
+ gtk_widget_show (plugin->label);
+ g_object_ref (plugin->label);
+}
+
+static void
+peasdemo_second_time_deactivate (PeasActivatable *activatable)
+{
+ PeasDemoSecondTime *plugin = PEASDEMO_SECOND_TIME (activatable);
+
+ g_debug (G_STRFUNC);
+
+ gtk_container_remove (GTK_CONTAINER (get_box (plugin->window)), plugin->label);
+}
+
+static void
+peasdemo_second_time_class_init (PeasDemoSecondTimeClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = peasdemo_second_time_set_property;
+ object_class->get_property = peasdemo_second_time_get_property;
+ object_class->finalize = peasdemo_second_time_finalize;
+
+ g_object_class_override_property (object_class, PROP_OBJECT, "object");
+}
+
+static void
+peas_activatable_iface_init (PeasActivatableInterface *iface)
+{
+ iface->activate = peasdemo_second_time_activate;
+ iface->deactivate = peasdemo_second_time_deactivate;
+}
+
+static void
+peasdemo_second_time_class_finalize (PeasDemoSecondTimeClass *klass)
+{
+}
+
+G_MODULE_EXPORT void
+peas_register_types (PeasObjectModule *module)
+{
+ peasdemo_second_time_register_type (G_TYPE_MODULE (module));
+
+ peas_object_module_register_extension_type (module,
+ PEAS_TYPE_ACTIVATABLE,
+ PEASDEMO_TYPE_SECOND_TIME);
+}
diff --git a/peas-demo/plugins/secondtime/second-time.h b/peas-demo/plugins/secondtime/second-time.h
new file mode 100644
index 0000000..c0345ae
--- /dev/null
+++ b/peas-demo/plugins/secondtime/second-time.h
@@ -0,0 +1,35 @@
+#ifndef __PEASDEMO_SECOND_TIME_H__
+#define __PEASDEMO_SECOND_TIME_H__
+
+#include <gtk/gtk.h>
+#include <libpeas/peas.h>
+
+G_BEGIN_DECLS
+
+#define PEASDEMO_TYPE_SECOND_TIME (peasdemo_second_time_get_type ())
+#define PEASDEMO_SECOND_TIME(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), PEASDEMO_TYPE_SECOND_TIME, PeasDemoSecondTime))
+#define PEASDEMO_SECOND_TIME_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), PEASDEMO_TYPE_SECOND_TIME, PeasDemoSecondTime))
+#define PEASDEMO_IS_SECOND_TIME(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), PEASDEMO_TYPE_SECOND_TIME))
+#define PEASDEMO_IS_SECOND_TIME_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), PEASDEMO_TYPE_SECOND_TIME))
+#define PEASDEMO_SECOND_TIME_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), PEASDEMO_TYPE_SECOND_TIME, PeasDemoSecondTimeClass))
+
+typedef struct _PeasDemoSecondTime PeasDemoSecondTime;
+typedef struct _PeasDemoSecondTimeClass PeasDemoSecondTimeClass;
+
+struct _PeasDemoSecondTime {
+ PeasExtensionBase parent_instance;
+
+ GtkWidget *window;
+ GtkWidget *label;
+};
+
+struct _PeasDemoSecondTimeClass {
+ PeasExtensionBaseClass parent_class;
+};
+
+GType peasdemo_second_time_get_type (void) G_GNUC_CONST;
+G_MODULE_EXPORT void peas_register_types (PeasObjectModule *module);
+
+G_END_DECLS
+
+#endif /* __PeasDEMO_HELLO_WORLD_PLUGIN_H__ */
diff --git a/peas-demo/plugins/secondtime/secondtime.peasdemo-plugin b/peas-demo/plugins/secondtime/secondtime.peasdemo-plugin
new file mode 100644
index 0000000..22c798e
--- /dev/null
+++ b/peas-demo/plugins/secondtime/secondtime.peasdemo-plugin
@@ -0,0 +1,9 @@
+[PeasDemo Plugin]
+Module=secondtime
+Depends=helloworld
+IAge=2
+Name=A Second Time!
+Description=Inserts a box containing "A second time!" in every windows.
+Authors=Steve Frécinaux <code istique net>
+Copyright=Copyright © 2010 Steve Frécinaux
+Website=http://live.gnome.org/Libpeas
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]