[evolution-data-server] gnome-online-accounts: Add an EDataFactory extension.



commit 4b0ccdb2148f3a9b0dfd362fc91cef9fcd6b4d51
Author: Matthew Barnes <mbarnes redhat com>
Date:   Mon Nov 12 11:38:45 2012 -0500

    gnome-online-accounts: Add an EDataFactory extension.
    
    This extension takes over for the GOA bits in EDataBookFactory.
    
    Install this extension to both the addressbook and calendar backend
    directories, even though only EBookBackendGoogle uses it at present.

 modules/gnome-online-accounts/Makefile.am          |   45 +++
 .../module-data-factory-goa.c                      |  295 ++++++++++++++++++++
 2 files changed, 340 insertions(+), 0 deletions(-)
---
diff --git a/modules/gnome-online-accounts/Makefile.am b/modules/gnome-online-accounts/Makefile.am
index 2692b0b..855c7c4 100644
--- a/modules/gnome-online-accounts/Makefile.am
+++ b/modules/gnome-online-accounts/Makefile.am
@@ -2,6 +2,11 @@ NULL =
 
 module_LTLIBRARIES = module-gnome-online-accounts.la
 
+# These aren't actually backends, but that's all
+# the installation directory has historically held.
+ecal_backend_LTLIBRARIES = module-data-cal-factory-goa.la
+ebook_backend_LTLIBRARIES = module-data-book-factory-goa.la
+
 module_gnome_online_accounts_la_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
 	-I$(top_srcdir) \
@@ -31,4 +36,44 @@ module_gnome_online_accounts_la_LDFLAGS = \
 	-module -avoid-version $(NO_UNDEFINED) \
 	$(NULL)
 
+module_data_factory_goa_CPPFLAGS = \
+	$(AM_CPPFLAGS) \
+	-I$(top_srcdir) \
+	-DG_LOG_DOMAIN=\"module-data-factory-goa\" \
+	$(E_BACKEND_CFLAGS) \
+	$(CAMEL_CFLAGS) \
+	$(SOUP_CFLAGS) \
+	$(GOA_CFLAGS) \
+	$(NULL)
+
+module_data_factory_goa_SOURCES = \
+	module-data-factory-goa.c \
+	$(NULL)
+
+module_data_factory_goa_LIBADD = \
+	$(top_builddir)/libebackend/libebackend-1.2.la \
+	$(top_builddir)/libedataserver/libedataserver-1.2.la \
+	$(E_BACKEND_LIBS) \
+	$(CAMEL_LIBS) \
+	$(SOUP_LIBS) \
+	$(GOA_LIBS) \
+	$(NULL)
+
+module_data_factory_goa_LDFLAGS = \
+	-module -avoid-version $(NO_UNDEFINED) \
+	$(NULL)
+
+# Libtool forces us to build separate modules for the address book
+# and calendar factories, even though the modules are identical.
+
+module_data_cal_factory_goa_la_CPPFLAGS = $(module_data_factory_goa_CPPFLAGS)
+module_data_cal_factory_goa_la_SOURCES = $(module_data_factory_goa_SOURCES)
+module_data_cal_factory_goa_la_LIBADD = $(module_data_factory_goa_LIBADD)
+module_data_cal_factory_goa_la_LDFLAGS = $(module_data_factory_goa_LDFLAGS)
+
+module_data_book_factory_goa_la_CPPFLAGS = $(module_data_factory_goa_CPPFLAGS)
+module_data_book_factory_goa_la_SOURCES = $(module_data_factory_goa_SOURCES)
+module_data_book_factory_goa_la_LIBADD = $(module_data_factory_goa_LIBADD)
+module_data_book_factory_goa_la_LDFLAGS = $(module_data_factory_goa_LDFLAGS)
+
 -include $(top_srcdir)/git.mk
diff --git a/modules/gnome-online-accounts/module-data-factory-goa.c b/modules/gnome-online-accounts/module-data-factory-goa.c
new file mode 100644
index 0000000..2ca2930
--- /dev/null
+++ b/modules/gnome-online-accounts/module-data-factory-goa.c
@@ -0,0 +1,295 @@
+/*
+ * module-data-factory-goa.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/>
+ *
+ */
+
+#include <libebackend/libebackend.h>
+
+#define GOA_API_IS_SUBJECT_TO_CHANGE
+#include <goa/goa.h>
+
+/* Standard GObject macros */
+#define E_TYPE_DATA_FACTORY_GOA \
+	(e_data_factory_goa_get_type ())
+#define E_DATA_FACTORY_GOA(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_DATA_FACTORY_GOA, EDataFactoryGoa))
+
+typedef struct _EDataFactoryGoa EDataFactoryGoa;
+typedef struct _EDataFactoryGoaClass EDataFactoryGoaClass;
+
+struct _EDataFactoryGoa {
+	EExtension parent;
+
+	GoaClient *goa_client;
+	GHashTable *goa_accounts;
+
+	gulong account_added_handler_id;
+	gulong account_removed_handler_id;
+};
+
+struct _EDataFactoryGoaClass {
+	EExtensionClass parent_class;
+};
+
+/* Module Entry Points */
+void e_module_load (GTypeModule *type_module);
+void e_module_unload (GTypeModule *type_module);
+
+/* Forward Declarations */
+GType e_data_factory_goa_get_type (void);
+
+G_DEFINE_DYNAMIC_TYPE (
+	EDataFactoryGoa,
+	e_data_factory_goa,
+	E_TYPE_EXTENSION)
+
+static void
+data_factory_goa_collect_accounts (EDataFactoryGoa *extension)
+{
+	GList *list, *link;
+
+	g_hash_table_remove_all (extension->goa_accounts);
+
+	list = goa_client_get_accounts (extension->goa_client);
+
+	for (link = list; link != NULL; link = g_list_next (link)) {
+		GoaObject *goa_object;
+		GoaAccount *goa_account;
+		const gchar *goa_account_id;
+
+		goa_object = GOA_OBJECT (link->data);
+
+		goa_account = goa_object_peek_account (goa_object);
+		goa_account_id = goa_account_get_id (goa_account);
+		g_return_if_fail (goa_account_id != NULL);
+
+		g_hash_table_insert (
+			extension->goa_accounts,
+			g_strdup (goa_account_id),
+			g_object_ref (goa_object));
+	}
+
+	g_list_free_full (list, (GDestroyNotify) g_object_unref);
+}
+
+static void
+data_factory_goa_account_added_cb (GoaClient *goa_client,
+                                   GoaObject *goa_object,
+                                   EDataFactoryGoa *extension)
+{
+	GoaAccount *goa_account;
+	const gchar *goa_account_id;
+
+	goa_account = goa_object_peek_account (goa_object);
+	goa_account_id = goa_account_get_id (goa_account);
+	g_return_if_fail (goa_account_id != NULL);
+
+	g_hash_table_insert (
+		extension->goa_accounts,
+		g_strdup (goa_account_id),
+		g_object_ref (goa_object));
+}
+
+static void
+data_factory_goa_account_removed_cb (GoaClient *goa_client,
+                                     GoaObject *goa_object,
+                                     EDataFactoryGoa *extension)
+{
+	GoaAccount *goa_account;
+	const gchar *goa_account_id;
+
+	goa_account = goa_object_peek_account (goa_object);
+	goa_account_id = goa_account_get_id (goa_account);
+	g_return_if_fail (goa_account_id != NULL);
+
+	g_hash_table_remove (extension->goa_accounts, goa_account_id);
+}
+
+static void
+data_factory_goa_backend_created_cb (EDataFactory *factory,
+                                     EBackend *backend,
+                                     EDataFactoryGoa *extension)
+{
+	ESource *source;
+	GoaObject *goa_object;
+	ESourceGoa *goa_extension;
+	ESourceRegistry *registry = NULL;
+	const gchar *extension_name;
+	gchar *goa_account_id;
+
+	/* Embed the corresponding GoaObject in the EBackend so the
+	 * backend can retrieve it by name with g_object_get_data(). */
+
+	source = e_backend_get_source (backend);
+	extension_name = E_SOURCE_EXTENSION_GOA;
+
+	/* XXX Both EDataBookFactory and EDataCalFactory have an
+	 *     ESourceRegistry property, so retrieve it by name. */
+	g_object_get (factory, "registry", &registry, NULL);
+	g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
+
+	/* Check source and its ancestors for a GOA extension. */
+	source = e_source_registry_find_extension (
+		registry, source, extension_name);
+
+	g_object_unref (registry);
+
+	if (source == NULL)
+		return;
+
+	goa_extension = e_source_get_extension (source, extension_name);
+	goa_account_id = e_source_goa_dup_account_id (goa_extension);
+	g_return_if_fail (goa_account_id != NULL);
+
+	goa_object = g_hash_table_lookup (
+		extension->goa_accounts, goa_account_id);
+	if (goa_object != NULL) {
+		g_object_set_data_full (
+			G_OBJECT (backend),
+			"GNOME Online Account",
+			g_object_ref (goa_object),
+			(GDestroyNotify) g_object_unref);
+	}
+
+	g_free (goa_account_id);
+	g_object_unref (source);
+}
+
+static void
+data_factory_goa_dispose (GObject *object)
+{
+	EDataFactoryGoa *extension;
+
+	extension = E_DATA_FACTORY_GOA (object);
+
+	if (extension->goa_client != NULL) {
+		g_signal_handler_disconnect (
+			extension->goa_client,
+			extension->account_added_handler_id);
+		g_signal_handler_disconnect (
+			extension->goa_client,
+			extension->account_removed_handler_id);
+		g_object_unref (extension->goa_client);
+		extension->goa_client = NULL;
+	}
+
+	g_hash_table_remove_all (extension->goa_accounts);
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_data_factory_goa_parent_class)->dispose (object);
+}
+
+static void
+data_factory_goa_finalize (GObject *object)
+{
+	EDataFactoryGoa *extension;
+
+	extension = E_DATA_FACTORY_GOA (object);
+
+	g_hash_table_destroy (extension->goa_accounts);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (e_data_factory_goa_parent_class)->finalize (object);
+}
+
+static void
+data_factory_goa_constructed (GObject *object)
+{
+	EDataFactoryGoa *extension;
+	EExtensible *extensible;
+	GError *error = NULL;
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_data_factory_goa_parent_class)->constructed (object);
+
+	extension = E_DATA_FACTORY_GOA (object);
+	extensible = e_extension_get_extensible (E_EXTENSION (extension));
+
+	/* XXX This blocks to make sure we don't miss any
+	 *     "backend-created" signals from EDataFactory. */
+	extension->goa_client = goa_client_new_sync (NULL, &error);
+
+	if (extension->goa_client != NULL) {
+		gulong handler_id;
+
+		data_factory_goa_collect_accounts (extension);
+
+		handler_id = g_signal_connect (
+			extension->goa_client, "account-added",
+			G_CALLBACK (data_factory_goa_account_added_cb),
+			extension);
+		extension->account_added_handler_id = handler_id;
+
+		handler_id = g_signal_connect (
+			extension->goa_client, "account-removed",
+			G_CALLBACK (data_factory_goa_account_removed_cb),
+			extension);
+		extension->account_removed_handler_id = handler_id;
+
+		g_signal_connect (
+			extensible, "backend-created",
+			G_CALLBACK (data_factory_goa_backend_created_cb),
+			extension);
+	} else {
+		g_warning (
+			"Failed to create a GoaClient: %s",
+			error->message);
+		g_error_free (error);
+	}
+}
+
+static void
+e_data_factory_goa_class_init (EDataFactoryGoaClass *class)
+{
+	GObjectClass *object_class;
+	EExtensionClass *extension_class;
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->dispose = data_factory_goa_dispose;
+	object_class->finalize = data_factory_goa_finalize;
+	object_class->constructed = data_factory_goa_constructed;
+
+	extension_class = E_EXTENSION_CLASS (class);
+	extension_class->extensible_type = E_TYPE_DATA_FACTORY;
+}
+
+static void
+e_data_factory_goa_class_finalize (EDataFactoryGoaClass *class)
+{
+}
+
+static void
+e_data_factory_goa_init (EDataFactoryGoa *extension)
+{
+	extension->goa_accounts = g_hash_table_new_full (
+		(GHashFunc) g_str_hash,
+		(GEqualFunc) g_str_equal,
+		(GDestroyNotify) g_free,
+		(GDestroyNotify) g_object_unref);
+}
+
+G_MODULE_EXPORT void
+e_module_load (GTypeModule *type_module)
+{
+	e_data_factory_goa_register_type (type_module);
+}
+
+G_MODULE_EXPORT void
+e_module_unload (GTypeModule *type_module)
+{
+}
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]