diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2010-03-22 10:22:57 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2010-03-22 11:30:44 +0800 |
commit | 906f93a130d8d670c4b5213c2c2bf03c47c02337 (patch) | |
tree | 049d65401eae28e21b98c27bd9e73a8275f94bcb | |
parent | 5368aec9721e9ccd97280d05e6916e1197fa14a1 (diff) | |
download | gsoc2013-evolution-906f93a130d8d670c4b5213c2c2bf03c47c02337.tar gsoc2013-evolution-906f93a130d8d670c4b5213c2c2bf03c47c02337.tar.gz gsoc2013-evolution-906f93a130d8d670c4b5213c2c2bf03c47c02337.tar.bz2 gsoc2013-evolution-906f93a130d8d670c4b5213c2c2bf03c47c02337.tar.lz gsoc2013-evolution-906f93a130d8d670c4b5213c2c2bf03c47c02337.tar.xz gsoc2013-evolution-906f93a130d8d670c4b5213c2c2bf03c47c02337.tar.zst gsoc2013-evolution-906f93a130d8d670c4b5213c2c2bf03c47c02337.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.txt | 1 | ||||
-rw-r--r-- | doc/reference/shell/tmpl/e-extensible.sgml | 10 | ||||
-rw-r--r-- | doc/reference/shell/tmpl/e-shell-backend.sgml | 5 | ||||
-rw-r--r-- | doc/reference/shell/tmpl/eshell-unused.sgml | 6 | ||||
-rw-r--r-- | e-util/e-extensible.c | 46 | ||||
-rw-r--r-- | e-util/e-extensible.h | 2 | ||||
-rw-r--r-- | shell/e-shell-backend.c | 148 | ||||
-rw-r--r-- | shell/e-shell-backend.h | 5 | ||||
-rw-r--r-- | shell/e-shell.c | 34 |
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 |