aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--e-util/ChangeLog10
-rw-r--r--e-util/e-plugin.c138
-rw-r--r--e-util/e-plugin.h11
3 files changed, 148 insertions, 11 deletions
diff --git a/e-util/ChangeLog b/e-util/ChangeLog
index 5b94bb0cd9..9244442c84 100644
--- a/e-util/ChangeLog
+++ b/e-util/ChangeLog
@@ -1,3 +1,13 @@
+2004-11-03 Not Zed <NotZed@Ximian.com>
+
+ * e-plugin.c (e_plugin_list_plugins): added helper api to list all
+ plugins.
+ (ep_construct): load authors into new list for them.
+ (e_plugin_register_type): setup disabled list.
+ (ep_construct): dont load the hooks if we're not enabled.
+ (e_plugin_enable): make this a virutal method.
+ (e_plugin_invoke): if we're disabled, noop.
+
2004-11-01 Not Zed <NotZed@Ximian.com>
** See bug #68787
diff --git a/e-util/e-plugin.c b/e-util/e-plugin.c
index 959d1391a6..0a0688a5cd 100644
--- a/e-util/e-plugin.c
+++ b/e-util/e-plugin.c
@@ -4,6 +4,7 @@
#include <string.h>
#include <glib/gi18n.h>
+#include <gconf/gconf-client.h>
#include "e-plugin.h"
#include "e-msgport.h"
@@ -52,6 +53,10 @@ static GHashTable *ep_plugins;
static GHashTable *ep_plugins_pending;
/* list of all cached xml docs:struct _plugin_doc's */
static EDList ep_plugin_docs = E_DLIST_INITIALISER(ep_plugin_docs);
+/* gconf client */
+static GConfClient *ep_gconf;
+/* the list of disabled plugins from gconf */
+static GSList *ep_disabled;
/* EPluginHook stuff */
static void *eph_parent_class;
@@ -66,6 +71,43 @@ struct _plugin_doc {
GSList *plugins;
};
+static gboolean
+ep_check_enabled(const char *id)
+{
+ GSList *l = ep_disabled;
+
+ for (;l;l = g_slist_next(l))
+ if (!strcmp((char *)l->data, id))
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+ep_set_enabled(const char *id, int state)
+{
+ if ((state == 0) == ep_check_enabled(id) == 0)
+ return;
+
+ if (state) {
+ GSList *l = ep_disabled;
+
+ while (l) {
+ GSList *n = l->next;
+
+ if (!strcmp((char *)l->data, id)) {
+ g_free(l->data);
+ ep_disabled = g_slist_remove_link(ep_disabled, l);
+ }
+ l = n;
+ }
+ } else {
+ ep_disabled = g_slist_prepend(ep_disabled, g_strdup(id));
+ }
+
+ gconf_client_set_list(ep_gconf, "/apps/evolution/eplugin/disabled", GCONF_VALUE_STRING, ep_disabled, NULL);
+}
+
static int
ep_construct(EPlugin *ep, xmlNodePtr root)
{
@@ -89,7 +131,8 @@ ep_construct(EPlugin *ep, xmlNodePtr root)
goto fail;
}
- if (eph_types != NULL
+ if (ep->enabled
+ && eph_types != NULL
&& (type = g_hash_table_lookup(eph_types, class)) != NULL) {
g_free(class);
hook = g_object_new(G_OBJECT_CLASS_TYPE(type), NULL);
@@ -117,6 +160,17 @@ ep_construct(EPlugin *ep, xmlNodePtr root)
}
} else if (strcmp(node->name, "description") == 0) {
ep->description = e_plugin_xml_content_domain(node, ep->domain);
+ } else if (strcmp(node->name, "author") == 0) {
+ char *name = e_plugin_xml_prop(node, "name");
+ char *email = e_plugin_xml_prop(node, "email");
+
+ if (name || email) {
+ EPluginAuthor *epa = g_malloc0(sizeof(*epa));
+
+ epa->name = name;
+ epa->email = email;
+ ep->authors = g_slist_append(ep->authors, epa);
+ }
}
node = node->next;
}
@@ -126,6 +180,18 @@ fail:
}
static void
+ep_enable(EPlugin *ep, int state)
+{
+ GSList *l;
+
+ ep->enabled = state;
+ for (l=ep->hooks;l;l = g_slist_next(l))
+ e_plugin_hook_enable((EPluginHook *)l->data, state);
+
+ ep_set_enabled(ep->id, state);
+}
+
+static void
ep_finalise(GObject *o)
{
EPlugin *ep = (EPlugin *)o;
@@ -155,6 +221,7 @@ ep_class_init(EPluginClass *klass)
{
((GObjectClass *)klass)->finalize = ep_finalise;
klass->construct = ep_construct;
+ klass->enable = ep_enable;
}
/**
@@ -265,6 +332,7 @@ ep_load(const char *filename)
ep = g_object_new(G_TYPE_FROM_CLASS(klass), NULL);
ep->id = id;
ep->path = g_strdup(filename);
+ ep->enabled = ep_check_enabled(id);
if (e_plugin_construct(ep, root) == -1) {
g_object_unref(ep);
} else {
@@ -422,6 +490,9 @@ e_plugin_register_type(GType type)
if (ep_types == NULL) {
ep_types = g_hash_table_new(g_str_hash, g_str_equal);
ep_plugins = g_hash_table_new(g_str_hash, g_str_equal);
+ /* TODO: notify listening */
+ ep_gconf = gconf_client_get_default();
+ ep_disabled = gconf_client_get_list(ep_gconf, "/apps/evolution/eplugin/disabled", GCONF_VALUE_STRING, NULL);
}
klass = g_type_class_ref(type);
@@ -431,6 +502,34 @@ e_plugin_register_type(GType type)
g_hash_table_insert(ep_types, (void *)klass->type, klass);
}
+static void
+ep_list_plugin(void *key, void *val, void *dat)
+{
+ GSList **l = (GSList **)dat;
+
+ *l = g_slist_prepend(*l, g_object_ref(val));
+}
+
+/**
+ * e_plugin_list_plugins: List all plugins.
+ *
+ * Static class method to retrieve a list of all current plugins. They
+ * are listed in no particular order.
+ *
+ * Return value: A GSList of all plugins, they must be
+ * g_object_unref'd and the list freed.
+ **/
+GSList *
+e_plugin_list_plugins(void)
+{
+ GSList *l = NULL;
+
+ if (ep_plugins)
+ g_hash_table_foreach(ep_plugins, ep_list_plugin, &l);
+
+ return l;
+}
+
/**
* e_plugin_construct:
* @ep: An EPlugin derived object.
@@ -463,8 +562,10 @@ e_plugin_construct(EPlugin *ep, xmlNodePtr root)
void *
e_plugin_invoke(EPlugin *ep, const char *name, void *data)
{
- if (!ep->enabled)
- g_warning("Invoking method on disabled plugin");
+ if (!ep->enabled) {
+ g_warning("Invoking method on disabled plugin, ignored");
+ return NULL;
+ }
return ((EPluginClass *)G_OBJECT_GET_CLASS(ep))->invoke(ep, name, data);
}
@@ -481,17 +582,10 @@ e_plugin_invoke(EPlugin *ep, const char *name, void *data)
void
e_plugin_enable(EPlugin *ep, int state)
{
- GSList *l;
-
if ((ep->enabled == 0) == (state == 0))
return;
- ep->enabled = state;
- for (l=ep->hooks;l;l = g_slist_next(l)) {
- EPluginHook *eph = l->data;
-
- e_plugin_hook_enable(eph, state);
- }
+ ((EPluginClass *)G_OBJECT_GET_CLASS(ep))->enable(ep, state);
}
/**
@@ -693,6 +787,27 @@ epl_construct(EPlugin *ep, xmlNodePtr root)
}
static void
+epl_enable(EPlugin *ep, int state)
+{
+ ((EPluginClass *)epl_parent_class)->enable(ep, state);
+
+ /* try and unload the module if the plugin will let us */
+ /* This may cause more problems than its worth ... so actual module removal disabled for now */
+ if (epl->module && !state) {
+ EPluginLibEnableFunc enable;
+
+ if (g_module_symbol(epl->module, "e_plugin_lib_enable", (void *)&enable)) {
+ if (enable(epl, FALSE) != 0)
+ return;
+ }
+#if 0
+ g_module_close(epl->module);
+ epl->module = NULL;
+#endif
+ }
+}
+
+static void
epl_finalise(GObject *o)
{
EPlugin *ep = (EPlugin *)o;
@@ -711,6 +826,7 @@ epl_class_init(EPluginClass *klass)
((GObjectClass *)klass)->finalize = epl_finalise;
klass->construct = epl_construct;
klass->invoke = epl_invoke;
+ klass->enable = epl_enable;
klass->type = "shlib";
}
diff --git a/e-util/e-plugin.h b/e-util/e-plugin.h
index 60635ae2dc..efc53d5108 100644
--- a/e-util/e-plugin.h
+++ b/e-util/e-plugin.h
@@ -13,6 +13,13 @@ typedef struct _EPluginClass EPluginClass;
#define E_PLUGIN_CLASSID "org.gnome.evolution.plugin"
+/* Structure to define the author(s) names and addresses */
+typedef struct _EPluginAuthor EPluginAuthor;
+struct _EPluginAuthor {
+ char *name;
+ char *email;
+};
+
/**
* struct _EPlugin - An EPlugin instance.
*
@@ -43,6 +50,7 @@ struct _EPlugin {
char *name;
char *domain;
GSList *hooks;
+ GSList *authors; /* EPluginAuthor structures */
int enabled:1;
};
@@ -59,6 +67,7 @@ struct _EPlugin {
* @invoke: The invoke virtual method loads the plugin code, resolves
* the function name, and marshals a simple pointer to execute the
* plugin.
+ * @enable: Virtual method to enable/disable the plugin.
*
* The EPluginClass represents each plugin type. The type of each class is
* registered in a global table and is used to instantiate a
@@ -75,6 +84,7 @@ struct _EPluginClass {
int (*construct)(EPlugin *, xmlNodePtr root);
void *(*invoke)(EPlugin *, const char *name, void *data);
+ void (*enable)(EPlugin *, int state);
};
GType e_plugin_get_type(void);
@@ -82,6 +92,7 @@ GType e_plugin_get_type(void);
int e_plugin_construct(EPlugin *ep, xmlNodePtr root);
void e_plugin_add_load_path(const char *);
int e_plugin_load_plugins(void);
+GSList * e_plugin_list_plugins(void);
void e_plugin_register_type(GType type);