[evolution-data-server/account-mgmt: 17/33] Add an ESource extension for the contacts backend.



commit d163f9fb8bb3adb54f06afc738016b1531b9a495
Author: Matthew Barnes <mbarnes redhat com>
Date:   Tue Nov 23 08:35:40 2010 -0500

    Add an ESource extension for the contacts backend.

 calendar/backends/contacts/Makefile.am             |    4 +-
 .../contacts/e-cal-backend-contacts-factory.c      |    2 +
 .../backends/contacts/e-cal-backend-contacts.c     |  217 +++++---------------
 calendar/backends/contacts/e-source-contacts.c     |  139 +++++++++++++
 calendar/backends/contacts/e-source-contacts.h     |   70 +++++++
 5 files changed, 262 insertions(+), 170 deletions(-)
---
diff --git a/calendar/backends/contacts/Makefile.am b/calendar/backends/contacts/Makefile.am
index f386ed7..3e96250 100644
--- a/calendar/backends/contacts/Makefile.am
+++ b/calendar/backends/contacts/Makefile.am
@@ -15,7 +15,9 @@ libecalbackendcontacts_la_SOURCES =		\
 	e-cal-backend-contacts-factory.c	\
 	e-cal-backend-contacts-factory.h	\
 	e-cal-backend-contacts.c		\
-	e-cal-backend-contacts.h
+	e-cal-backend-contacts.h		\
+	e-source-contacts.c			\
+	e-source-contacts.h
 
 libecalbackendcontacts_la_LIBADD =						\
 	$(top_builddir)/calendar/libecal/libecal-1.2.la				\
diff --git a/calendar/backends/contacts/e-cal-backend-contacts-factory.c b/calendar/backends/contacts/e-cal-backend-contacts-factory.c
index 36e1920..b9f4f5e 100644
--- a/calendar/backends/contacts/e-cal-backend-contacts-factory.c
+++ b/calendar/backends/contacts/e-cal-backend-contacts-factory.c
@@ -15,6 +15,7 @@
 
 #include "e-cal-backend-contacts-factory.h"
 #include "e-cal-backend-contacts.h"
+#include "e-source-contacts.h"
 
 typedef ECalBackendFactory ECalBackendContactsEventsFactory;
 typedef ECalBackendFactoryClass ECalBackendContactsEventsFactoryClass;
@@ -70,6 +71,7 @@ e_cal_backend_contacts_events_factory_init (ECalBackendFactory *factory)
 void
 eds_module_initialize (GTypeModule *type_module)
 {
+	e_source_contacts_type_register (type_module);
 	e_cal_backend_contacts_events_factory_register_type (type_module);
 }
 
diff --git a/calendar/backends/contacts/e-cal-backend-contacts.c b/calendar/backends/contacts/e-cal-backend-contacts.c
index 230c48c..ff22e27 100644
--- a/calendar/backends/contacts/e-cal-backend-contacts.c
+++ b/calendar/backends/contacts/e-cal-backend-contacts.c
@@ -33,7 +33,7 @@
 #include <glib/gi18n-lib.h>
 #include <gconf/gconf-client.h>
 #include <libedataserver/e-xml-hash-utils.h>
-#include <libedataserver/e-source-list.h>
+#include <libedataserver/e-source-registry.h>
 #include <libedataserver/e-flag.h>
 #include <libecal/e-cal-recur.h>
 #include <libecal/e-cal-util.h>
@@ -42,6 +42,9 @@
 #include <libebook/e-book-client.h>
 #include <libebook/e-book-query.h>
 #include <libebook/e-contact.h>
+#include <libebook/e-source-address-book.h>
+
+#include "e-source-contacts.h"
 
 #define EDC_ERROR(_code) e_data_cal_create_error (_code, NULL)
 
@@ -58,7 +61,6 @@ typedef enum
 
 /* Private part of the ECalBackendContacts structure */
 struct _ECalBackendContactsPrivate {
-        ESourceList  *addressbook_sources;
 
 	GHashTable   *addressbooks;       /* UID -> BookRecord */
 	gboolean      addressbook_loaded;
@@ -68,8 +70,6 @@ struct _ECalBackendContactsPrivate {
 
 	GHashTable *zones;
 
-	EFlag   *init_done_flag; /* is set, when the init thread gone */
-
 	/* properties related to track alarm settings for this backend */
 	GConfClient *conf_client;
 	guint notifyid1;
@@ -142,7 +142,7 @@ book_record_new (ECalBackendContacts *cbc,
 	e_book_query_unref (query);
 
 	if (!e_book_client_get_view_sync (book_client, query_sexp, &book_view, NULL, &error)) {
-		g_warning ("%s: Failed to get book view on '%s': %s", G_STRFUNC, e_source_peek_name (source), error ? error->message : "Unknown error");
+		g_warning ("%s: Failed to get book view on '%s': %s", G_STRFUNC, e_source_get_display_name (source), error ? error->message : "Unknown error");
 
 		g_free (query_sexp);
 		g_object_unref (book_client);
@@ -306,138 +306,44 @@ contact_record_cb (gpointer key,
 	}
 }
 
-static gboolean
-is_source_usable (ESource *source,
-                  ESourceGroup *group)
+static void
+source_added_cb (ESourceRegistry *registry,
+                 ESource *source,
+                 ECalBackendContacts *cbc)
 {
-	const gchar *base_uri;
-	const gchar *prop;
+	ESourceContacts *extension;
+	const gchar *extension_name;
+	BookRecord *br;
+	const gchar *uid;
 
-	base_uri = e_source_group_peek_base_uri (group);
-	if (!base_uri)
-		return FALSE;
+	extension_name = E_SOURCE_EXTENSION_CONTACTS_BACKEND;
+	extension = e_source_get_extension (source, extension_name);
 
-	prop = e_source_get_property (source, "use-in-contacts-calendar");
+	if (extension == NULL)
+		return;
 
-	/* the later check is for backward compatibility */
-	return (prop && g_str_equal (prop, "1")) || (!prop && g_str_has_prefix (base_uri, "file://")) || (!prop && g_str_has_prefix (base_uri, "local:"));
-}
+	if (!e_source_contacts_get_include_me (extension))
+		return;
 
-/* SourceList callbacks */
-static void
-add_source (ECalBackendContacts *cbc,
-            ESource *source)
-{
-	BookRecord *br = book_record_new (cbc, source);
-	const gchar *uid = e_source_peek_uid (source);
+	uid = e_source_get_uid (source);
+	br = book_record_new (cbc, source);
 
-	if (!br)
+	if (br == NULL)
 		return;
 
 	g_hash_table_insert (cbc->priv->addressbooks, g_strdup (uid), br);
 }
 
 static void
-source_added_cb (ESourceGroup *group,
-                 ESource *source,
-                 gpointer user_data)
-{
-	ECalBackendContacts *cbc = E_CAL_BACKEND_CONTACTS (user_data);
-
-	g_return_if_fail (cbc);
-
-	if (is_source_usable (source, group))
-		add_source (cbc, source);
-}
-
-static void
-source_removed_cb (ESourceGroup *group,
+source_removed_cb (ESourceRegistry *registry,
                    ESource *source,
-                   gpointer user_data)
+                   ECalBackendContacts *cbc)
 {
-	ECalBackendContacts *cbc = E_CAL_BACKEND_CONTACTS (user_data);
-	const gchar          *uid = e_source_peek_uid (source);
-
-	g_return_if_fail (cbc);
+	const gchar *uid = e_source_get_uid (source);
 
 	g_hash_table_remove (cbc->priv->addressbooks, uid);
 }
 
-static void
-source_list_changed_cb (ESourceList *source_list,
-                        gpointer user_data)
-{
-	ECalBackendContacts *cbc = E_CAL_BACKEND_CONTACTS (user_data);
-	GSList *g, *s;
-
-	g_return_if_fail (cbc);
-
-	for (g = e_source_list_peek_groups (source_list); g; g = g->next) {
-		ESourceGroup *group = E_SOURCE_GROUP (g->data);
-
-		if (!group)
-			continue;
-
-		for (s = e_source_group_peek_sources (group); s; s = s->next) {
-			ESource *source = E_SOURCE (s->data);
-			const gchar *uid;
-
-			if (!source)
-				continue;
-
-			uid = e_source_peek_uid (source);
-			if (!uid)
-				continue;
-
-			if (is_source_usable (source, group)) {
-				if (!g_hash_table_lookup (cbc->priv->addressbooks, uid))
-					source_added_cb (group, source, cbc);
-			} else if (g_hash_table_lookup (cbc->priv->addressbooks, uid)) {
-				source_removed_cb (group, source, cbc);
-			}
-		}
-	}
-}
-
-static void
-source_group_added_cb (ESourceList *source_list,
-                       ESourceGroup *group,
-                       gpointer user_data)
-{
-	ECalBackendContacts *cbc = E_CAL_BACKEND_CONTACTS (user_data);
-	GSList *i;
-
-	g_return_if_fail (cbc);
-
-	for (i = e_source_group_peek_sources (group); i; i = i->next) {
-		ESource *source = E_SOURCE (i->data);
-		source_added_cb (group, source, cbc);
-	}
-
-	/* Watch for future changes */
-	g_signal_connect (group, "source_added", G_CALLBACK (source_added_cb), cbc);
-	g_signal_connect (group, "source_removed", G_CALLBACK (source_removed_cb), cbc);
-}
-
-static void
-source_group_removed_cb (ESourceList *source_list,
-                         ESourceGroup *group,
-                         gpointer user_data)
-{
-	ECalBackendContacts *cbc = E_CAL_BACKEND_CONTACTS (user_data);
-	GSList *i = NULL;
-
-	g_return_if_fail (cbc);
-
-        /* Unload all address books from this group */
-	for (i = e_source_group_peek_sources (group); i; i = i->next) {
-		ESource *source = E_SOURCE (i->data);
-		const gchar *uid = e_source_peek_uid (source);
-
-		g_hash_table_remove (cbc->priv->addressbooks, uid);
-	}
-}
-
 /************************************************************************************/
 
 static void
@@ -994,33 +900,6 @@ e_cal_backend_contacts_set_online (ECalBackend *backend,
 	e_cal_backend_notify_readonly (backend, TRUE);
 }
 
-static gpointer
-init_sources_cb (ECalBackendContacts *cbc)
-{
-	ECalBackendContactsPrivate *priv;
-	GSList *i;
-
-	g_return_val_if_fail (cbc != NULL, NULL);
-
-	priv = cbc->priv;
-
-	/* Create address books for existing sources */
-	for (i = e_source_list_peek_groups (priv->addressbook_sources); i; i = i->next) {
-		ESourceGroup *source_group = E_SOURCE_GROUP (i->data);
-
-		source_group_added_cb (priv->addressbook_sources, source_group, cbc);
-	}
-
-        /* Listen for source list changes */
-        g_signal_connect (priv->addressbook_sources, "changed", G_CALLBACK (source_list_changed_cb), cbc);
-        g_signal_connect (priv->addressbook_sources, "group_added", G_CALLBACK (source_group_added_cb), cbc);
-        g_signal_connect (priv->addressbook_sources, "group_removed", G_CALLBACK (source_group_removed_cb), cbc);
-
-	e_flag_set (priv->init_done_flag);
-
-	return NULL;
-}
-
 static void
 e_cal_backend_contacts_open (ECalBackendSync *backend,
                              EDataCal *cal,
@@ -1030,23 +909,10 @@ e_cal_backend_contacts_open (ECalBackendSync *backend,
 {
 	ECalBackendContacts *cbc = E_CAL_BACKEND_CONTACTS (backend);
 	ECalBackendContactsPrivate *priv = cbc->priv;
-	GError *error = NULL;
 
 	if (priv->addressbook_loaded)
 		return;
 
-	/* initialize addressbook sources in new thread to make this function quick as much as possible */
-	if (!g_thread_create ((GThreadFunc) init_sources_cb, cbc, FALSE, &error)) {
-		e_flag_set (priv->init_done_flag);
-		g_warning ("%s: Cannot create thread to initialize sources! (%s)", G_STRFUNC, error ? error->message : "Unknown error");
-		if (error)
-			g_error_free (error);
-
-		g_propagate_error (perror, EDC_ERROR (OtherError));
-		e_cal_backend_notify_opened (E_CAL_BACKEND (backend), EDC_ERROR (OtherError));
-		return;
-	}
-
 	priv->addressbook_loaded = TRUE;
 	e_cal_backend_notify_readonly (E_CAL_BACKEND (backend), TRUE);
 	e_cal_backend_notify_online (E_CAL_BACKEND (backend), TRUE);
@@ -1181,18 +1047,11 @@ e_cal_backend_contacts_finalize (GObject *object)
 	cbc = E_CAL_BACKEND_CONTACTS (object);
 	priv = cbc->priv;
 
-	if (priv->init_done_flag) {
-		e_flag_wait (priv->init_done_flag);
-		e_flag_free (priv->init_done_flag);
-		priv->init_done_flag = NULL;
-	}
-
 	if (priv->update_alarms_id) {
 		g_source_remove (priv->update_alarms_id);
 		priv->update_alarms_id = 0;
 	}
 
-	g_object_unref (priv->addressbook_sources);
 	g_hash_table_destroy (priv->addressbooks);
 	g_hash_table_destroy (priv->tracked_contacts);
 	g_hash_table_destroy (priv->zones);
@@ -1217,18 +1076,18 @@ static void
 e_cal_backend_contacts_init (ECalBackendContacts *cbc)
 {
 	ECalBackendContactsPrivate *priv;
+	ESourceRegistry *registry;
+	GList *sources, *iter;
+	const gchar *extension_name;
 
 	priv = g_new0 (ECalBackendContactsPrivate, 1);
 
-	e_book_client_get_sources (&priv->addressbook_sources, NULL);
-
 	priv->addressbooks = g_hash_table_new_full (g_str_hash, g_str_equal,
 						    g_free, (GDestroyNotify) book_record_free);
 	priv->tracked_contacts = g_hash_table_new_full (g_str_hash, g_str_equal,
 							g_free, (GDestroyNotify) contact_record_free);
 
 	priv->zones = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_zone);
-	priv->init_done_flag = e_flag_new ();
 	priv->conf_client = gconf_client_get_default ();
 	priv->notifyid1 = 0;
 	priv->notifyid2 = 0;
@@ -1241,6 +1100,23 @@ e_cal_backend_contacts_init (ECalBackendContacts *cbc)
 	cbc->priv = priv;
 
 	e_cal_backend_sync_set_lock (E_CAL_BACKEND_SYNC (cbc), TRUE);
+
+	/* Query all address book sources from the registry. */
+
+	registry = e_source_registry_get_default ();
+	extension_name = E_SOURCE_EXTENSION_ADDRESS_BOOK;
+	sources = e_source_registry_list_sources (registry, extension_name);
+	for (iter = sources; iter != NULL; iter = g_list_next (iter))
+		source_added_cb (registry, E_SOURCE (iter->data), cbc);
+	g_list_free (sources);
+
+	g_signal_connect (
+		registry, "source-added",
+		G_CALLBACK (source_added_cb), cbc);
+
+	g_signal_connect (
+		registry, "source-removed",
+		G_CALLBACK (source_removed_cb), cbc);
 }
 
 static void
@@ -1285,4 +1161,7 @@ e_cal_backend_contacts_class_init (ECalBackendContactsClass *class)
 	backend_class->start_view		= e_cal_backend_contacts_start_view;
 	backend_class->set_online		= e_cal_backend_contacts_set_online;
 	backend_class->internal_get_timezone	= e_cal_backend_contacts_internal_get_timezone;
+
+	/* Register our ESource extension. */
+	E_TYPE_SOURCE_CONTACTS;
 }
diff --git a/calendar/backends/contacts/e-source-contacts.c b/calendar/backends/contacts/e-source-contacts.c
new file mode 100644
index 0000000..32ba589
--- /dev/null
+++ b/calendar/backends/contacts/e-source-contacts.c
@@ -0,0 +1,139 @@
+/*
+ * e-source-contacts.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 <webcal://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-source-contacts.h"
+
+#define E_SOURCE_CONTACTS_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_SOURCE_CONTACTS, ESourceContactsPrivate))
+
+struct _ESourceContactsPrivate {
+	gboolean include_me;
+};
+
+enum {
+	PROP_0,
+	PROP_INCLUDE_ME
+};
+
+G_DEFINE_DYNAMIC_TYPE (
+	ESourceContacts,
+	e_source_contacts,
+	E_TYPE_SOURCE_EXTENSION)
+
+static void
+source_contacts_set_property (GObject *object,
+                              guint property_id,
+                              const GValue *value,
+                              GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_INCLUDE_ME:
+			e_source_contacts_set_include_me (
+				E_SOURCE_CONTACTS (object),
+				g_value_get_boolean (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_contacts_get_property (GObject *object,
+                              guint property_id,
+                              GValue *value,
+                              GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_INCLUDE_ME:
+			g_value_set_boolean (
+				value,
+				e_source_contacts_get_include_me (
+				E_SOURCE_CONTACTS (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+e_source_contacts_class_init (ESourceContactsClass *class)
+{
+	GObjectClass *object_class;
+	ESourceExtensionClass *extension_class;
+
+	g_type_class_add_private (class, sizeof (ESourceContactsPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = source_contacts_set_property;
+	object_class->get_property = source_contacts_get_property;
+
+	extension_class = E_SOURCE_EXTENSION_CLASS (class);
+	extension_class->name = E_SOURCE_EXTENSION_CONTACTS_BACKEND;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_INCLUDE_ME,
+		g_param_spec_boolean (
+			"include-me",
+			"Include Me",
+			"Include this address book in the contacts calendar",
+			TRUE,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT |
+			E_SOURCE_PARAM_SETTING));
+}
+
+static void
+e_source_contacts_class_finalize (ESourceContactsClass *class)
+{
+}
+
+static void
+e_source_contacts_init (ESourceContacts *extension)
+{
+	extension->priv = E_SOURCE_CONTACTS_GET_PRIVATE (extension);
+}
+
+void
+e_source_contacts_type_register (GTypeModule *type_module)
+{
+	/* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
+	 *     function, so we have to wrap it with a public function in
+	 *     order to register types from a separate compilation unit. */
+	e_source_contacts_register_type (type_module);
+}
+
+gboolean
+e_source_contacts_get_include_me (ESourceContacts *extension)
+{
+	g_return_val_if_fail (E_IS_SOURCE_CONTACTS (extension), FALSE);
+
+	return extension->priv->include_me;
+}
+
+void
+e_source_contacts_set_include_me (ESourceContacts *extension,
+                                  gboolean include_me)
+{
+	g_return_if_fail (E_IS_SOURCE_CONTACTS (extension));
+
+	extension->priv->include_me = include_me;
+
+	g_object_notify (G_OBJECT (extension), "include-me");
+}
diff --git a/calendar/backends/contacts/e-source-contacts.h b/calendar/backends/contacts/e-source-contacts.h
new file mode 100644
index 0000000..95d9b83
--- /dev/null
+++ b/calendar/backends/contacts/e-source-contacts.h
@@ -0,0 +1,70 @@
+/*
+ * e-source-contacts.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 <webcal://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_SOURCE_CONTACTS_H
+#define E_SOURCE_CONTACTS_H
+
+#include <libedataserver/e-source-extension.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SOURCE_CONTACTS \
+	(e_source_contacts_get_type ())
+#define E_SOURCE_CONTACTS(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_SOURCE_CONTACTS, ESourceContacts))
+#define E_SOURCE_CONTACTS_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_SOURCE_CONTACTS, ESourceContactsClass))
+#define E_IS_SOURCE_CONTACTS(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_SOURCE_CONTACTS))
+#define E_IS_SOURCE_CONTACTS_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_SOURCE_CONTACTS))
+#define E_SOURCE_CONTACTS_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_SOURCE_CONTACTS, ESourceContactsClass))
+
+#define E_SOURCE_EXTENSION_CONTACTS_BACKEND "Contacts Backend"
+
+G_BEGIN_DECLS
+
+typedef struct _ESourceContacts ESourceContacts;
+typedef struct _ESourceContactsClass ESourceContactsClass;
+typedef struct _ESourceContactsPrivate ESourceContactsPrivate;
+
+struct _ESourceContacts {
+	ESourceExtension parent;
+	ESourceContactsPrivate *priv;
+};
+
+struct _ESourceContactsClass {
+	ESourceExtensionClass parent_class;
+};
+
+GType		e_source_contacts_get_type	(void);
+void		e_source_contacts_type_register	(GTypeModule *type_module);
+gboolean	e_source_contacts_get_include_me
+						(ESourceContacts *extension);
+void		e_source_contacts_set_include_me
+						(ESourceContacts *extension,
+						 gboolean include_me);
+
+G_END_DECLS
+
+#endif /* E_SOURCE_CONTACTS_H */



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