aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2010-03-22 10:22:57 +0800
committerMichael Meeks <michael.meeks@novell.com>2010-04-07 19:13:36 +0800
commit13fb16f2793ee91099b1f2960c1875896991f1c4 (patch)
tree9d5832e48bd514baeb24e158db0693f5a1202f7f
parent83e36a49baa491609bda692e36006123a7aa079f (diff)
downloadgsoc2013-evolution-13fb16f2793ee91099b1f2960c1875896991f1c4.tar.gz
gsoc2013-evolution-13fb16f2793ee91099b1f2960c1875896991f1c4.tar.zst
gsoc2013-evolution-13fb16f2793ee91099b1f2960c1875896991f1c4.zip
Demonstrate extending the EExtension API.
Introduce e_extensible_list_extensions(), which provides extensible objects access to their own extensions, or a subset of them. Convert EShellBackend to an abstract EExtension subtype. EShell will load its extensions with e_extensible_load_extensions(), and then obtain a list of EShellBackend extensions as follows: shell_backends = e_extensible_list_extensions ( E_EXTENSIBLE (shell), E_TYPE_SHELL_BACKEND); Because EShellBackend is abstract, its GType is skipped while traversing the GType hierarchy to find EShell extensions.
-rw-r--r--doc/reference/shell/eshell-sections.txt1
-rw-r--r--doc/reference/shell/tmpl/e-extensible.sgml10
-rw-r--r--doc/reference/shell/tmpl/e-shell-backend.sgml5
-rw-r--r--doc/reference/shell/tmpl/eshell-unused.sgml6
-rw-r--r--e-util/e-extensible.c46
-rw-r--r--e-util/e-extensible.h2
-rw-r--r--shell/e-shell-backend.c148
-rw-r--r--shell/e-shell-backend.h5
-rw-r--r--shell/e-shell.c34
9 files changed, 115 insertions, 142 deletions
diff --git a/doc/reference/shell/eshell-sections.txt b/doc/reference/shell/eshell-sections.txt
index 776d08d13f..f25d7c7ff3 100644
--- a/doc/reference/shell/eshell-sections.txt
+++ b/doc/reference/shell/eshell-sections.txt
@@ -445,6 +445,7 @@ e_dialog_combo_box_get
<TITLE>Extensible</TITLE>
EExtensible
e_extensible_load_extensions
+e_extensible_list_extensions
<SUBSECTION Standard>
E_EXTENSIBLE
E_IS_EXTENSIBLE
diff --git a/doc/reference/shell/tmpl/e-extensible.sgml b/doc/reference/shell/tmpl/e-extensible.sgml
index de8e8e140c..80bf8f0da4 100644
--- a/doc/reference/shell/tmpl/e-extensible.sgml
+++ b/doc/reference/shell/tmpl/e-extensible.sgml
@@ -31,3 +31,13 @@ Extensible
@extensible:
+<!-- ##### FUNCTION e_extensible_list_extensions ##### -->
+<para>
+
+</para>
+
+@extensible:
+@extension_type:
+@Returns:
+
+
diff --git a/doc/reference/shell/tmpl/e-shell-backend.sgml b/doc/reference/shell/tmpl/e-shell-backend.sgml
index 79456dcfea..76bf06c58e 100644
--- a/doc/reference/shell/tmpl/e-shell-backend.sgml
+++ b/doc/reference/shell/tmpl/e-shell-backend.sgml
@@ -31,11 +31,6 @@ EShellBackend
@eshellbackend: the object which received the signal.
@arg1:
-<!-- ##### ARG EShellBackend:shell ##### -->
-<para>
-
-</para>
-
<!-- ##### FUNCTION e_shell_backend_compare ##### -->
<para>
diff --git a/doc/reference/shell/tmpl/eshell-unused.sgml b/doc/reference/shell/tmpl/eshell-unused.sgml
index 8769407347..ef0cb974c4 100644
--- a/doc/reference/shell/tmpl/eshell-unused.sgml
+++ b/doc/reference/shell/tmpl/eshell-unused.sgml
@@ -509,6 +509,12 @@ intelligent
</para>
+<!-- ##### ARG EShellBackend:shell ##### -->
+<para>
+
+</para>
+
+
<!-- ##### ARG EShellContent:filter-action ##### -->
<para>
diff --git a/e-util/e-extensible.c b/e-util/e-extensible.c
index a5e87c4280..b718fc59bf 100644
--- a/e-util/e-extensible.c
+++ b/e-util/e-extensible.c
@@ -61,6 +61,9 @@
#include <e-util/e-util.h>
#include <e-util/e-extension.h>
+#define IS_AN_EXTENSION_TYPE(type) \
+ (g_type_is_a ((type), E_TYPE_EXTENSION))
+
static GQuark extensible_quark;
static GPtrArray *
@@ -133,7 +136,7 @@ e_extensible_get_type (void)
* e_extensible_load_extensions:
* @extensible: an #EExtensible
*
- * Creates an instance of all registered subtypes of #EExtension which
+ * Creates an instance of all instantiable subtypes of #EExtension which
* target the class of @extensible. The lifetimes of these newly created
* #EExtension objects are bound to @extensible such that they are finalized
* when @extensible is finalized.
@@ -159,3 +162,44 @@ e_extensible_load_extensions (EExtensible *extensible)
E_TYPE_EXTENSION, (ETypeFunc)
extensible_load_extension, extensible);
}
+
+/**
+ * e_extensible_list_extensions:
+ * @extensible: an #EExtensible
+ * @extension_type: the type of extensions to list
+ *
+ * Returns a list of #EExtension objects bound to @extensible whose
+ * types are ancestors of @extension_type. For a complete list of
+ * extension objects bound to @extensible, pass %E_TYPE_EXTENSION.
+ *
+ * The list itself should be freed with g_list_free(). The extension
+ * objects are owned by @extensible and should not be unreferenced.
+ *
+ * Returns: a list of extension objects derived from @extension_type
+ **/
+GList *
+e_extensible_list_extensions (EExtensible *extensible,
+ GType extension_type)
+{
+ GPtrArray *extensions;
+ GList *list = NULL;
+ guint ii;
+
+ g_return_val_if_fail (E_IS_EXTENSIBLE (extensible), NULL);
+ g_return_val_if_fail (IS_AN_EXTENSION_TYPE (extension_type), NULL);
+
+ e_extensible_load_extensions (extensible);
+
+ extensions = extensible_get_extensions (extensible);
+ g_return_val_if_fail (extensions != NULL, NULL);
+
+ for (ii = 0; ii < extensions->len; ii++) {
+ GObject *object;
+
+ object = g_ptr_array_index (extensions, ii);
+ if (g_type_is_a (G_OBJECT_TYPE (object), extension_type))
+ list = g_list_prepend (list, object);
+ }
+
+ return g_list_reverse (list);
+}
diff --git a/e-util/e-extensible.h b/e-util/e-extensible.h
index a72ea71611..6dd6294212 100644
--- a/e-util/e-extensible.h
+++ b/e-util/e-extensible.h
@@ -51,6 +51,8 @@ struct _EExtensibleInterface {
GType e_extensible_get_type (void);
void e_extensible_load_extensions (EExtensible *extensible);
+GList * e_extensible_list_extensions (EExtensible *extensible,
+ GType extension_type);
G_END_DECLS
diff --git a/shell/e-shell-backend.c b/shell/e-shell-backend.c
index ed354712d3..570e58db95 100644
--- a/shell/e-shell-backend.c
+++ b/shell/e-shell-backend.c
@@ -43,8 +43,6 @@
struct _EShellBackendPrivate {
- gpointer shell; /* weak pointer */
-
/* We keep a reference to corresponding EShellView subclass
* since it keeps a reference back to us. This ensures the
* subclass is not finalized before we are, otherwise it
@@ -58,63 +56,38 @@ struct _EShellBackendPrivate {
};
enum {
- PROP_0,
- PROP_SHELL
-};
-
-enum {
ACTIVITY_ADDED,
LAST_SIGNAL
};
-static gpointer parent_class;
static guint signals[LAST_SIGNAL];
-static void
-shell_backend_set_shell (EShellBackend *shell_backend,
- EShell *shell)
-{
- g_return_if_fail (shell_backend->priv->shell == NULL);
-
- shell_backend->priv->shell = shell;
+G_DEFINE_ABSTRACT_TYPE (EShellBackend, e_shell_backend, E_TYPE_EXTENSION)
- g_object_add_weak_pointer (
- G_OBJECT (shell_backend),
- &shell_backend->priv->shell);
-}
-
-static void
-shell_backend_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
+static GObject *
+shell_backend_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
{
- switch (property_id) {
- case PROP_SHELL:
- shell_backend_set_shell (
- E_SHELL_BACKEND (object),
- g_value_get_object (value));
- return;
- }
+ EShellBackendPrivate *priv;
+ EShellBackendClass *class;
+ EShellViewClass *shell_view_class;
+ GObject *object;
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-}
+ /* Chain up to parent's construct() method. */
+ object = G_OBJECT_CLASS (e_shell_backend_parent_class)->constructor (
+ type, n_construct_properties, construct_properties);
-static void
-shell_backend_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id) {
- case PROP_SHELL:
- g_value_set_object (
- value, e_shell_backend_get_shell (
- E_SHELL_BACKEND (object)));
- return;
- }
+ class = E_SHELL_BACKEND_GET_CLASS (object);
+ priv = E_SHELL_BACKEND_GET_PRIVATE (object);
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ /* Install a reference to ourselves in the
+ * corresponding EShellViewClass structure. */
+ shell_view_class = g_type_class_ref (class->shell_view_type);
+ shell_view_class->shell_backend = g_object_ref (object);
+ priv->shell_view_class = shell_view_class;
+
+ return object;
}
static void
@@ -124,19 +97,13 @@ shell_backend_dispose (GObject *object)
priv = E_SHELL_BACKEND_GET_PRIVATE (object);
- if (priv->shell != NULL) {
- g_object_remove_weak_pointer (
- G_OBJECT (priv->shell), &priv->shell);
- priv->shell = NULL;
- }
-
if (priv->shell_view_class != NULL) {
g_type_class_unref (priv->shell_view_class);
priv->shell_view_class = NULL;
}
/* Chain up to parent's dispose() method. */
- G_OBJECT_CLASS (parent_class)->dispose (object);
+ G_OBJECT_CLASS (e_shell_backend_parent_class)->dispose (object);
}
static void
@@ -150,7 +117,7 @@ shell_backend_finalize (GObject *object)
g_free (priv->data_dir);
/* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (parent_class)->finalize (object);
+ G_OBJECT_CLASS (e_shell_backend_parent_class)->finalize (object);
}
static const gchar *
@@ -195,39 +162,25 @@ shell_backend_get_data_dir (EShellBackend *shell_backend)
}
static void
-shell_backend_class_init (EShellBackendClass *class)
+e_shell_backend_class_init (EShellBackendClass *class)
{
GObjectClass *object_class;
+ EExtensionClass *extension_class;
- parent_class = g_type_class_peek_parent (class);
g_type_class_add_private (class, sizeof (EShellBackendPrivate));
object_class = G_OBJECT_CLASS (class);
- object_class->set_property = shell_backend_set_property;
- object_class->get_property = shell_backend_get_property;
+ object_class->constructor = shell_backend_constructor;
object_class->dispose = shell_backend_dispose;
object_class->finalize = shell_backend_finalize;
+ extension_class = E_EXTENSION_CLASS (class);
+ extension_class->extensible_type = E_TYPE_SHELL;
+
class->get_config_dir = shell_backend_get_config_dir;
class->get_data_dir = shell_backend_get_data_dir;
/**
- * EShellBackend:shell
- *
- * The #EShell singleton.
- **/
- g_object_class_install_property (
- object_class,
- PROP_SHELL,
- g_param_spec_object (
- "shell",
- _("Shell"),
- _("The EShell singleton"),
- E_TYPE_SHELL,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY));
-
- /**
* EShellBackend::activity-added
* @shell_backend: the #EShellBackend that emitted the signal
* @activity: an #EActivity
@@ -245,44 +198,9 @@ shell_backend_class_init (EShellBackendClass *class)
}
static void
-shell_backend_init (EShellBackend *shell_backend,
- EShellBackendClass *class)
+e_shell_backend_init (EShellBackend *shell_backend)
{
- EShellViewClass *shell_view_class;
-
shell_backend->priv = E_SHELL_BACKEND_GET_PRIVATE (shell_backend);
-
- /* Install a reference to ourselves in the corresponding
- * EShellViewClass structure, */
- shell_view_class = g_type_class_ref (class->shell_view_type);
- shell_view_class->shell_backend = g_object_ref (shell_backend);
- shell_backend->priv->shell_view_class = shell_view_class;
-}
-
-GType
-e_shell_backend_get_type (void)
-{
- static GType type = 0;
-
- if (G_UNLIKELY (type == 0)) {
- const GTypeInfo type_info = {
- sizeof (EShellBackendClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) shell_backend_class_init,
- (GClassFinalizeFunc) NULL,
- NULL, /* class_data */
- sizeof (EShellBackend),
- 0, /* n_preallocs */
- (GInstanceInitFunc) shell_backend_init,
- NULL /* value_table */
- };
-
- type = g_type_register_static (
- G_TYPE_OBJECT, "EShellBackend", &type_info, 0);
- }
-
- return type;
}
/**
@@ -364,9 +282,13 @@ e_shell_backend_get_data_dir (EShellBackend *shell_backend)
EShell *
e_shell_backend_get_shell (EShellBackend *shell_backend)
{
+ EExtensible *extensible;
+
g_return_val_if_fail (E_IS_SHELL_BACKEND (shell_backend), NULL);
- return E_SHELL (shell_backend->priv->shell);
+ extensible = e_extension_get_extensible (E_EXTENSION (shell_backend));
+
+ return E_SHELL (extensible);
}
/**
diff --git a/shell/e-shell-backend.h b/shell/e-shell-backend.h
index df4abc8104..055a2a3322 100644
--- a/shell/e-shell-backend.h
+++ b/shell/e-shell-backend.h
@@ -24,6 +24,7 @@
#include <shell/e-shell-common.h>
#include <e-util/e-activity.h>
+#include <e-util/e-extension.h>
/* Standard GObject macros */
#define E_TYPE_SHELL_BACKEND \
@@ -60,7 +61,7 @@ typedef struct _EShellBackendPrivate EShellBackendPrivate;
* functions below.
**/
struct _EShellBackend {
- GObject parent;
+ EExtension parent;
EShellBackendPrivate *priv;
};
@@ -94,7 +95,7 @@ struct _EShellBackend {
* #EShellBackendClass contains a number of important settings for subclasses.
**/
struct _EShellBackendClass {
- GObjectClass parent_class;
+ EExtensionClass parent_class;
GType shell_view_type;
diff --git a/shell/e-shell.c b/shell/e-shell.c
index c9dfd156e6..f877bca4ec 100644
--- a/shell/e-shell.c
+++ b/shell/e-shell.c
@@ -52,7 +52,7 @@ struct _EShellPrivate {
GtkWidget *preferences_window;
/* Shell Backends */
- GList *loaded_backends;
+ GList *loaded_backends; /* not referenced */
GHashTable *backends_by_name;
GHashTable *backends_by_scheme;
@@ -407,23 +407,14 @@ shell_split_and_insert_items (GHashTable *hash_table,
}
static void
-shell_add_backend (GType type,
- EShell *shell)
+shell_process_backend (EShellBackend *shell_backend,
+ EShell *shell)
{
EShellBackendClass *class;
- EShellBackend *shell_backend;
GHashTable *backends_by_name;
GHashTable *backends_by_scheme;
const gchar *string;
- shell_backend = g_object_new (type, "shell", shell, NULL);
-
- shell->priv->loaded_backends = g_list_insert_sorted (
- shell->priv->loaded_backends, shell_backend,
- (GCompareFunc) e_shell_backend_compare);
-
- /* Bookkeeping */
-
class = E_SHELL_BACKEND_GET_CLASS (shell_backend);
backends_by_name = shell->priv->backends_by_name;
backends_by_scheme = shell->priv->backends_by_scheme;
@@ -601,10 +592,6 @@ shell_dispose (GObject *object)
priv->preferences_window = NULL;
}
- g_list_foreach (priv->loaded_backends, (GFunc) g_object_unref, NULL);
- g_list_free (priv->loaded_backends);
- priv->loaded_backends = NULL;
-
if (priv->preparing_for_line_change != NULL) {
g_object_remove_weak_pointer (
G_OBJECT (priv->preparing_for_line_change),
@@ -629,6 +616,8 @@ shell_finalize (GObject *object)
if (!unique_app_is_running (UNIQUE_APP (object)))
e_file_lock_destroy ();
+ g_list_free (priv->loaded_backends);
+
g_free (priv->geometry);
g_free (priv->module_directory);
@@ -640,6 +629,7 @@ static void
shell_constructed (GObject *object)
{
EShellPrivate *priv;
+ GList *list;
priv = E_SHELL_GET_PRIVATE (object);
@@ -659,11 +649,13 @@ shell_constructed (GObject *object)
shell_load_modules (E_SHELL (object));
- e_type_traverse (
- E_TYPE_SHELL_BACKEND, (ETypeFunc)
- shell_add_backend, object);
-
- e_extensible_load_extensions (E_EXTENSIBLE (object));
+ /* Process shell backends. */
+ list = g_list_sort (
+ e_extensible_list_extensions (
+ E_EXTENSIBLE (object), E_TYPE_SHELL_BACKEND),
+ (GCompareFunc) e_shell_backend_compare);
+ g_list_foreach (list, (GFunc) shell_process_backend, object);
+ priv->loaded_backends = list;
}
static UniqueResponse