aboutsummaryrefslogtreecommitdiffstats
path: root/e-util
diff options
context:
space:
mode:
Diffstat (limited to 'e-util')
-rw-r--r--e-util/e-marshal.list2
-rw-r--r--e-util/e-plugin.c112
-rw-r--r--e-util/e-util.c41
-rw-r--r--e-util/e-util.h5
4 files changed, 93 insertions, 67 deletions
diff --git a/e-util/e-marshal.list b/e-util/e-marshal.list
index d6a3f0cb55..c4426d46d7 100644
--- a/e-util/e-marshal.list
+++ b/e-util/e-marshal.list
@@ -1,4 +1,4 @@
-BOOLEAN:BOXED,POINTER,POINTER
+BOOLEAN:BOXED,STRING
BOOLEAN:INT,INT,OBJECT,INT,INT,UINT
BOOLEAN:INT,POINTER,INT,OBJECT,INT,INT,UINT
BOOLEAN:NONE
diff --git a/e-util/e-plugin.c b/e-util/e-plugin.c
index 5d77decfd9..49a15da651 100644
--- a/e-util/e-plugin.c
+++ b/e-util/e-plugin.c
@@ -31,6 +31,7 @@
#include "e-plugin.h"
#include "e-util-private.h"
+#include "e-util.h"
/* plugin debug */
#define pd(x)
@@ -487,79 +488,50 @@ e_plugin_add_load_path(const gchar *path)
}
static void
-plugin_load_subclasses (void)
+plugin_load_subclass (GType type,
+ GHashTable *hash_table)
{
- GType *children;
- guint n_children, ii;
-
- ep_types = g_hash_table_new (g_str_hash, g_str_equal);
- eph_types = g_hash_table_new (g_str_hash, g_str_equal);
- ep_plugins = g_hash_table_new (g_str_hash, g_str_equal);
-
- /* Load EPlugin subclasses. */
-
- children = g_type_children (E_TYPE_PLUGIN, &n_children);
-
- for (ii = 0; ii < n_children; ii++) {
- EPluginClass *class;
-
- class = g_type_class_ref (children[ii]);
- g_hash_table_insert (ep_types, (gpointer) class->type, class);
- }
+ EPluginClass *class;
- g_free (children);
+ class = g_type_class_ref (type);
+ g_hash_table_insert (hash_table, (gpointer) class->type, class);
}
static void
-plugin_load_hook_subclasses (GType parent_type)
+plugin_hook_load_subclass (GType type,
+ GHashTable *hash_table)
{
- GType *children;
- guint n_children, ii;
-
- children = g_type_children (parent_type, &n_children);
-
- for (ii = 0; ii < n_children; ii++) {
- EPluginHookClass *hook_class;
- EPluginHookClass *dupe_class;
- gpointer key;
-
- /* First load the child's children. */
- plugin_load_hook_subclasses (children[ii]);
-
- /* Skip abstract types. */
- if (G_TYPE_IS_ABSTRACT (children[ii]))
- continue;
-
- hook_class = g_type_class_ref (children[ii]);
-
- /* Sanity check the hook class. */
- if (hook_class->id == NULL || *hook_class->id == '\0') {
- g_warning (
- "%s has no hook ID, so skipping",
- G_OBJECT_CLASS_NAME (hook_class));
- g_type_class_unref (hook_class);
- continue;
- }
-
- /* Check for class ID collisions. */
- dupe_class = g_hash_table_lookup (eph_types, hook_class->id);
- if (dupe_class != NULL) {
- g_warning (
- "%s and %s have the same hook "
- "ID ('%s'), so skipping %s",
- G_OBJECT_CLASS_NAME (dupe_class),
- G_OBJECT_CLASS_NAME (hook_class),
- hook_class->id,
- G_OBJECT_CLASS_NAME (hook_class));
- g_type_class_unref (hook_class);
- continue;
- }
+ EPluginHookClass *hook_class;
+ EPluginHookClass *dupe_class;
+ gpointer key;
+
+ hook_class = g_type_class_ref (type);
+
+ /* Sanity check the hook class. */
+ if (hook_class->id == NULL || *hook_class->id == '\0') {
+ g_warning (
+ "%s has no hook ID, so skipping",
+ G_OBJECT_CLASS_NAME (hook_class));
+ g_type_class_unref (hook_class);
+ return;
+ }
- key = (gpointer) hook_class->id;
- g_hash_table_insert (eph_types, key, hook_class);
+ /* Check for class ID collisions. */
+ dupe_class = g_hash_table_lookup (hash_table, hook_class->id);
+ if (dupe_class != NULL) {
+ g_warning (
+ "%s and %s have the same hook "
+ "ID ('%s'), so skipping %s",
+ G_OBJECT_CLASS_NAME (dupe_class),
+ G_OBJECT_CLASS_NAME (hook_class),
+ hook_class->id,
+ G_OBJECT_CLASS_NAME (hook_class));
+ g_type_class_unref (hook_class);
+ return;
}
- g_free (children);
+ key = (gpointer) hook_class->id;
+ g_hash_table_insert (hash_table, key, hook_class);
}
/**
@@ -580,11 +552,19 @@ e_plugin_load_plugins(void)
if (eph_types != NULL)
return 0;
+ ep_types = g_hash_table_new (g_str_hash, g_str_equal);
+ eph_types = g_hash_table_new (g_str_hash, g_str_equal);
+ ep_plugins = g_hash_table_new (g_str_hash, g_str_equal);
+
/* We require that all GTypes for EPlugin and EPluginHook
* subclasses be registered prior to loading any plugins.
* It greatly simplifies the loading process. */
- plugin_load_subclasses ();
- plugin_load_hook_subclasses (E_TYPE_PLUGIN_HOOK);
+ e_type_traverse (
+ E_TYPE_PLUGIN, (ETypeFunc)
+ plugin_load_subclass, ep_types);
+ e_type_traverse (
+ E_TYPE_PLUGIN_HOOK, (ETypeFunc)
+ plugin_hook_load_subclass, eph_types);
client = gconf_client_get_default ();
ep_disabled = gconf_client_get_list (
diff --git a/e-util/e-util.c b/e-util/e-util.c
index 57ec251c55..3c004e57cb 100644
--- a/e-util/e-util.c
+++ b/e-util/e-util.c
@@ -407,6 +407,47 @@ e_radio_action_get_current_action (GtkRadioAction *radio_action)
}
/**
+ * e_type_traverse:
+ * @parent_type: the root #GType to traverse from
+ * @func: the function to call for each visited #GType
+ * @user_data: user data to pass to the function
+ *
+ * Calls @func for all instantiable subtypes of @parent_type.
+ *
+ * This is often useful for extending functionality by way of #EModule.
+ * A module may register a subtype of @parent_type in its e_module_load()
+ * function. Then later on the application will call e_type_traverse()
+ * to instantiate all registered subtypes of @parent_type.
+ **/
+void
+e_type_traverse (GType parent_type,
+ ETypeFunc func,
+ gpointer user_data)
+{
+ GType *children;
+ guint n_children, ii;
+
+ g_return_if_fail (func != NULL);
+
+ children = g_type_children (parent_type, &n_children);
+
+ for (ii = 0; ii < n_children; ii++) {
+ GType type = children[ii];
+
+ /* Recurse over the child's children. */
+ e_type_traverse (type, func, user_data);
+
+ /* Skip abstract types. */
+ if (G_TYPE_IS_ABSTRACT (type))
+ continue;
+
+ func (type, user_data);
+ }
+
+ g_free (children);
+}
+
+/**
* e_str_without_underscores:
* @s: the string to strip underscores from.
*
diff --git a/e-util/e-util.h b/e-util/e-util.h
index 33bc940df7..1e2320914e 100644
--- a/e-util/e-util.h
+++ b/e-util/e-util.h
@@ -41,6 +41,8 @@ typedef enum {
E_FOCUS_END
} EFocus;
+typedef void (*ETypeFunc) (GType type, gpointer user_data);
+
const gchar * e_get_user_data_dir (void);
const gchar * e_get_accels_filename (void);
void e_show_uri (GtkWindow *parent,
@@ -59,6 +61,9 @@ void e_action_group_remove_all_actions
(GtkActionGroup *action_group);
GtkRadioAction *e_radio_action_get_current_action
(GtkRadioAction *radio_action);
+void e_type_traverse (GType parent_type,
+ ETypeFunc func,
+ gpointer user_data);
gchar * e_str_without_underscores (const gchar *s);
gint e_str_compare (gconstpointer x,