[evolution/account-mgmt: 49/50] Add ESourceCamelProvider.
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution/account-mgmt: 49/50] Add ESourceCamelProvider.
- Date: Sat, 1 Oct 2011 15:51:34 +0000 (UTC)
commit 0d50f712665b2b5af1e83c0ce5ac0ae60c890e30
Author: Matthew Barnes <mbarnes redhat com>
Date: Tue Aug 30 10:47:58 2011 -0400
Add ESourceCamelProvider.
mail/Makefile.am | 2 +
mail/e-mail-backend.c | 3 +-
mail/e-source-camel-provider.c | 427 ++++++++++++++++++++++++++++++++++++++++
mail/e-source-camel-provider.h | 78 ++++++++
4 files changed, 509 insertions(+), 1 deletions(-)
---
diff --git a/mail/Makefile.am b/mail/Makefile.am
index 5371a9f..ac1dbee 100644
--- a/mail/Makefile.am
+++ b/mail/Makefile.am
@@ -74,6 +74,7 @@ mailinclude_HEADERS = \
e-mail-store.h \
e-mail-store-utils.h \
e-mail-tag-editor.h \
+ e-source-camel-provider.h \
em-account-editor.h \
em-composer-utils.h \
em-config.h \
@@ -147,6 +148,7 @@ libevolution_mail_la_SOURCES = \
e-mail-store.c \
e-mail-store-utils.c \
e-mail-tag-editor.c \
+ e-source-camel-provider.c \
em-account-editor.c \
em-composer-utils.c \
em-config.c \
diff --git a/mail/e-mail-backend.c b/mail/e-mail-backend.c
index 3f888b3..cbd4727 100644
--- a/mail/e-mail-backend.c
+++ b/mail/e-mail-backend.c
@@ -45,6 +45,7 @@
#include "mail/e-mail-session.h"
#include "mail/e-mail-store.h"
#include "mail/e-mail-store-utils.h"
+#include "mail/e-source-camel-provider.h"
#include "mail/em-event.h"
#include "mail/em-folder-tree-model.h"
#include "mail/em-utils.h"
@@ -792,7 +793,7 @@ mail_backend_constructed (GObject *object)
if (camel_init (e_get_user_data_dir (), TRUE) != 0)
exit (0);
- camel_provider_init ();
+ e_source_camel_provider_register_types ();
priv->session = e_mail_session_new ();
folder_cache = e_mail_session_get_folder_cache (priv->session);
diff --git a/mail/e-source-camel-provider.c b/mail/e-source-camel-provider.c
new file mode 100644
index 0000000..7e2a1e5
--- /dev/null
+++ b/mail/e-source-camel-provider.c
@@ -0,0 +1,427 @@
+/*
+ * e-source-camel-provider.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+/**
+ * SECTION: e-source-camel-provider
+ * @include: mail/e-source-camel-provider.h
+ * @short_description: #ESource extension for #CamelSettings
+ *
+ * #ESourceCamelProvider itself is abstract. Its sole function is to
+ * bridge #GObject properties from the #CamelSettings framework to the
+ * #ESource framework. It does this by procedurally registering an
+ * #ESourceCamelProvider subtype for each available #CamelService subtype,
+ * and then registering #GObject properties to proxy the properties in the
+ * corresponding #CamelSettings subtype. The #ESourceCamelProvider owns an
+ * instance of the appropriate #CamelSettings subtype, and redirects all
+ * get/set operations on its own #GObject properties to its #CamelSettings
+ * instance. The #CamelSettings instance, now fully initialized from a key
+ * file, can then be inserted into a new #CamelService instance using
+ * camel_service_set_settings().
+ *
+ * Ultimately, this is all just implementation detail for glueing two
+ * unrelated class hierarchies together. If you need to access provider
+ * specific settings, use the #CamelSettings API, not this.
+ **/
+
+/* XXX This class MIGHT make sense in libedataserver with the other
+ * ESourceExtensions were it not for the fact that Camel links
+ * to libedataserver, so we'd have a circular dependency. */
+
+#include "e-source-camel-provider.h"
+
+#include <e-util/e-util.h>
+#include <libedataserver/e-source-offline.h>
+#include <libedataserver/e-source-security.h>
+
+#define E_SOURCE_CAMEL_PROVIDER_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_SOURCE_CAMEL_PROVIDER, ESourceCamelProviderPrivate))
+
+struct _ESourceCamelProviderPrivate {
+ CamelSettings *settings;
+};
+
+enum {
+ PROP_0,
+ PROP_SETTINGS
+};
+
+static struct {
+ const gchar *extension_name;
+ const gchar *extension_property_name;
+ const gchar *settings_property_name;
+ GBindingTransformFunc extension_to_settings;
+ GBindingTransformFunc settings_to_extension;
+} bindings[] = {
+
+ { E_SOURCE_EXTENSION_OFFLINE,
+ "stay-synchronized", "stay-synchronized" },
+
+ { E_SOURCE_EXTENSION_SECURITY,
+ "method", "security-method",
+ e_binding_transform_enum_nick_to_value,
+ e_binding_transform_enum_value_to_nick }
+};
+
+G_DEFINE_ABSTRACT_TYPE (
+ ESourceCamelProvider,
+ e_source_camel_provider,
+ E_TYPE_SOURCE_EXTENSION)
+
+static gint
+subclass_get_binding_index (GParamSpec *settings_property)
+{
+ gint ii;
+
+ /* Return the index in the bindings list for the given
+ * CamelSettings property specification, or else -1. */
+
+ for (ii = 0; ii < G_N_ELEMENTS (bindings); ii++) {
+ const gchar *property_name;
+
+ property_name = bindings[ii].settings_property_name;
+ if (g_strcmp0 (settings_property->name, property_name) == 0)
+ return ii;
+ }
+
+ return -1;
+}
+
+static void
+subclass_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ ESourceCamelProvider *extension;
+ CamelSettings *settings;
+
+ /* Forward the value to CamelSettings. */
+ extension = E_SOURCE_CAMEL_PROVIDER (object);
+ settings = e_source_camel_provider_get_settings (extension);
+ g_object_set_property (G_OBJECT (settings), pspec->name, value);
+}
+
+static void
+subclass_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ ESourceCamelProvider *extension;
+ CamelSettings *settings;
+
+ /* Obtain the value from CamelSettings. */
+ extension = E_SOURCE_CAMEL_PROVIDER (object);
+ settings = e_source_camel_provider_get_settings (extension);
+ g_object_get_property (G_OBJECT (settings), pspec->name, value);
+}
+
+static void
+subclass_init (gpointer g_class,
+ gpointer class_data)
+{
+ GObjectClass *object_class;
+ ESourceCamelProviderClass *extension_class;
+ GObjectClass *settings_class;
+ GParamSpec **properties;
+ GType settings_type;
+ guint ii, n_properties;
+
+ settings_type = GPOINTER_TO_SIZE (class_data);
+
+ object_class = G_OBJECT_CLASS (g_class);
+ object_class->set_property = subclass_set_property;
+ object_class->get_property = subclass_get_property;
+
+ extension_class = E_SOURCE_CAMEL_PROVIDER_CLASS (g_class);
+ extension_class->settings_type = settings_type;
+
+ settings_class = g_type_class_ref (settings_type);
+
+ properties = g_object_class_list_properties (
+ settings_class, &n_properties);
+
+ /* For each property in the CamelSettings class, register
+ * an equivalent GObject property in this class and add an
+ * E_SOURCE_PARAM_SETTING flag so the value gets written to
+ * the ESource's key file. */
+ for (ii = 0; ii < n_properties; ii++) {
+ GParamSpec *pspec;
+ const gchar *name;
+
+ /* Some properties in CamelSettings may be covered
+ * by other ESourceExtensions. Skip them here. */
+ if (subclass_get_binding_index (properties[ii]) >= 0)
+ continue;
+
+ name = properties[ii]->name;
+ pspec = g_param_spec_override (name, properties[ii]);
+ pspec->flags |= E_SOURCE_PARAM_SETTING;
+ g_object_class_install_property (object_class, ii, pspec);
+ }
+
+ g_free (properties);
+
+ g_type_class_unref (settings_class);
+}
+
+static void
+source_camel_provider_register_subtype (GType service_type,
+ const gchar *type_name,
+ const gchar *extension_name)
+{
+ CamelServiceClass *service_class;
+ GTypeInfo type_info;
+ GType settings_type;
+ GType parent_type;
+
+ /* Check if the type name is already registered. */
+ if (g_type_from_name (type_name) != G_TYPE_INVALID)
+ return;
+
+ service_class = g_type_class_ref (service_type);
+ settings_type = service_class->settings_type;
+ g_type_class_unref (service_class);
+
+ type_info.class_size = sizeof (ESourceCamelProviderClass);
+ type_info.base_init = NULL;
+ type_info.base_finalize = NULL;
+ type_info.class_init = subclass_init;
+ type_info.class_finalize = NULL;
+ type_info.class_data = GSIZE_TO_POINTER (settings_type);
+ type_info.instance_size = sizeof (ESourceCamelProvider);
+ type_info.n_preallocs = 0;
+ type_info.instance_init = NULL;
+ type_info.value_table = NULL;
+
+ parent_type = E_TYPE_SOURCE_CAMEL_PROVIDER;
+ g_type_register_static (parent_type, type_name, &type_info, 0);
+}
+
+static void
+source_camel_provider_notify_cb (GObject *object,
+ GParamSpec *pspec)
+{
+ g_object_notify (object, pspec->name);
+}
+
+static void
+source_camel_provider_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_SETTINGS:
+ g_value_set_object (
+ value,
+ e_source_camel_provider_get_settings (
+ E_SOURCE_CAMEL_PROVIDER (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_camel_provider_dispose (GObject *object)
+{
+ ESourceCamelProviderPrivate *priv;
+
+ priv = E_SOURCE_CAMEL_PROVIDER_GET_PRIVATE (object);
+
+ if (priv->settings != NULL) {
+ g_object_unref (priv->settings);
+ priv->settings = NULL;
+ }
+
+ /* Chain up to parent's dispose() method. */
+ G_OBJECT_CLASS (e_source_camel_provider_parent_class)->dispose (object);
+}
+
+static void
+source_camel_provider_constructed (GObject *object)
+{
+ ESource *source;
+ ESourceCamelProviderClass *class;
+ ESourceCamelProviderPrivate *priv;
+ GObjectClass *settings_class;
+ GParamSpec **properties;
+ guint ii, n_properties;
+
+ /* Chain up to parent's constructed() method. */
+ G_OBJECT_CLASS (e_source_camel_provider_parent_class)->
+ constructed (object);
+
+ class = E_SOURCE_CAMEL_PROVIDER_GET_CLASS (object);
+ priv = E_SOURCE_CAMEL_PROVIDER_GET_PRIVATE (object);
+
+ source = e_source_extension_get_source (E_SOURCE_EXTENSION (object));
+
+ priv->settings = g_object_new (class->settings_type, NULL);
+
+ g_signal_connect (
+ priv->settings, "notify",
+ G_CALLBACK (source_camel_provider_notify_cb), NULL);
+
+ /* Here we bind all the GObject properties in the newly-created
+ * CamelSettings instance to either our own identical properties
+ * or properties in another ESourceExtensions. The bindings list
+ * at the top of the file maps out bindings to other extensions. */
+
+ settings_class = G_OBJECT_GET_CLASS (priv->settings);
+
+ properties = g_object_class_list_properties (
+ settings_class, &n_properties);
+
+ for (ii = 0; ii < n_properties; ii++) {
+ gint index;
+
+ index = subclass_get_binding_index (properties[ii]);
+
+ /* Bind the CamelSettings property to a
+ * one in a different ESourceExtension. */
+ if (index >= 0) {
+ ESourceExtension *extension;
+
+ extension = e_source_get_extension (
+ source, bindings[index].extension_name);
+
+ g_object_bind_property_full (
+ extension,
+ bindings[index].extension_property_name,
+ priv->settings,
+ bindings[index].settings_property_name,
+ G_BINDING_BIDIRECTIONAL |
+ G_BINDING_SYNC_CREATE,
+ bindings[index].extension_to_settings,
+ bindings[index].settings_to_extension,
+ NULL, (GDestroyNotify) NULL);
+
+ /* Bind the CamelSettings property to our own
+ * equivalent E_SOURCE_PARAM_SETTING property. */
+ } else {
+ ESourceExtension *extension;
+
+ extension = E_SOURCE_EXTENSION (object);
+
+ g_object_bind_property (
+ extension,
+ properties[ii]->name,
+ priv->settings,
+ properties[ii]->name,
+ G_BINDING_BIDIRECTIONAL |
+ G_BINDING_SYNC_CREATE);
+ }
+ }
+
+ g_free (properties);
+}
+
+static void
+e_source_camel_provider_class_init (ESourceCamelProviderClass *class)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (class, sizeof (ESourceCamelProviderPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->get_property = source_camel_provider_get_property;
+ object_class->dispose = source_camel_provider_dispose;
+ object_class->constructed = source_camel_provider_constructed;
+
+ /* CamelSettings itself has no properties. */
+ class->settings_type = CAMEL_TYPE_SETTINGS;
+
+ /* XXX This kind of stomps on CamelSettings' namespace, but it's
+ * unlikely a CamelSettings subclass would define a property
+ * named "settings". */
+ g_object_class_install_property (
+ object_class,
+ PROP_SETTINGS,
+ g_param_spec_object (
+ "settings",
+ "Settings",
+ "The CamelSettings instance being proxied",
+ CAMEL_TYPE_SETTINGS,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
+}
+
+static void
+e_source_camel_provider_init (ESourceCamelProvider *extension)
+{
+ extension->priv = E_SOURCE_CAMEL_PROVIDER_GET_PRIVATE (extension);
+}
+
+void
+e_source_camel_provider_register_types (void)
+{
+ GList *list, *link;
+
+ /* This implicitly takes care of provider initialization. */
+ list = camel_provider_list (TRUE);
+
+ for (link = list; link != NULL; link = g_list_next (link)) {
+ CamelProvider *provider;
+ gchar *extension_name;
+ gchar *type_name;
+ gchar *name;
+ gint ii;
+
+ provider = (CamelProvider *) list->data;
+
+ name = g_strdup (provider->protocol);
+ name[0] = g_ascii_toupper (name[0]);
+
+ /* Use the term "backend" for consistency with other
+ * calendar and address book backend extension names. */
+ extension_name = g_strdup_printf ("%s Backend", name);
+ type_name = g_strdup_printf ("ESourceCamel%sProvider", name);
+
+ /* This is the novel part: fabricate and register
+ * a new ESourceCamelProvider subclass on-the-fly
+ * for each object type listed in the provider. */
+ for (ii = 0; ii < CAMEL_NUM_PROVIDER_TYPES; ii++) {
+ GType service_type;
+
+ service_type = provider->object_types[ii];
+
+ if (service_type == G_TYPE_INVALID)
+ continue;
+
+ source_camel_provider_register_subtype (
+ service_type, type_name, extension_name);
+ }
+
+ g_free (extension_name);
+ g_free (type_name);
+ g_free (name);
+ }
+
+ g_list_free (list);
+}
+
+CamelSettings *
+e_source_camel_provider_get_settings (ESourceCamelProvider *extension)
+{
+ g_return_val_if_fail (E_IS_SOURCE_CAMEL_PROVIDER (extension), NULL);
+
+ return extension->priv->settings;
+}
diff --git a/mail/e-source-camel-provider.h b/mail/e-source-camel-provider.h
new file mode 100644
index 0000000..f20253e
--- /dev/null
+++ b/mail/e-source-camel-provider.h
@@ -0,0 +1,78 @@
+/*
+ * e-source-camel-provider.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_SOURCE_CAMEL_PROVIDER_H
+#define E_SOURCE_CAMEL_PROVIDER_H
+
+#include <camel/camel.h>
+#include <libedataserver/e-source-extension.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SOURCE_CAMEL_PROVIDER \
+ (e_source_camel_provider_get_type ())
+#define E_SOURCE_CAMEL_PROVIDER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_SOURCE_CAMEL_PROVIDER, ESourceCamelProvider))
+#define E_SOURCE_CAMEL_PROVIDER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_SOURCE_CAMEL_PROVIDER, ESourceCamelProviderClass))
+#define E_IS_SOURCE_CAMEL_PROVIDER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_SOURCE_CAMEL_PROVIDER))
+#define E_IS_SOURCE_CAMEL_PROVIDER_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_SOURCE_CAMEL_PROVIDER))
+#define E_SOURCE_CAMEL_PROVIDER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_SOURCE_CAMEL_PROVIDER, ESourceCamelProviderClass))
+
+G_BEGIN_DECLS
+
+typedef struct _ESourceCamelProvider ESourceCamelProvider;
+typedef struct _ESourceCamelProviderClass ESourceCamelProviderClass;
+typedef struct _ESourceCamelProviderPrivate ESourceCamelProviderPrivate;
+
+/**
+ * ESourceCamelProvider:
+ *
+ * Contains only private data that should be read and manipulated using the
+ * functions below.
+ *
+ * Since: 3.4
+ **/
+struct _ESourceCamelProvider {
+ ESourceExtension parent;
+ ESourceCamelProviderPrivate *priv;
+};
+
+struct _ESourceCamelProviderClass {
+ ESourceExtensionClass parent_class;
+
+ /* Same idea as in CamelServiceClass. */
+ GType settings_type;
+};
+
+GType e_source_camel_provider_get_type (void);
+void e_source_camel_provider_register_types (void);
+CamelSettings *
+ e_source_camel_provider_get_settings
+ (ESourceCamelProvider *extension);
+
+G_END_DECLS
+
+#endif /* E_SOURCE_CAMEL_PROVIDER_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]