[evolution-data-server] Bug #494394 - Update backend's ESource on its change immediately



commit 1fc363176806463ba89492c405f9198776a494b4
Author: Milan Crha <mcrha redhat com>
Date:   Fri Jun 12 15:48:01 2009 +0200

    Bug #494394 - Update backend's ESource on its change immediately

 calendar/backends/http/e-cal-backend-http.c |   71 +++++++++++++-
 calendar/libedata-cal/e-cal-backend-cache.h |    5 +-
 calendar/libedata-cal/e-cal-backend.c       |   85 ++++++++++++++++-
 calendar/libedata-cal/e-cal-backend.h       |    4 +
 calendar/libedata-cal/e-data-cal-factory.c  |  141 ++++++++++++++++++++++++---
 libedataserver/e-source.c                   |   17 +++-
 6 files changed, 299 insertions(+), 24 deletions(-)
---
diff --git a/calendar/backends/http/e-cal-backend-http.c b/calendar/backends/http/e-cal-backend-http.c
index 61d0e57..4d64b31 100644
--- a/calendar/backends/http/e-cal-backend-http.c
+++ b/calendar/backends/http/e-cal-backend-http.c
@@ -41,6 +41,8 @@
 
 /* Private part of the ECalBackendHttp structure */
 struct _ECalBackendHttpPrivate {
+	/* signal handler id for source's 'changed' signal */
+	gulong source_changed_id;
 	/* URI to get remote calendar data from */
 	gchar *uri;
 
@@ -97,6 +99,13 @@ e_cal_backend_http_dispose (GObject *object)
 
 	g_free (priv->username);
 	g_free (priv->password);
+	priv->username = NULL;
+	priv->password = NULL;
+
+	if (priv->source_changed_id) {
+		g_signal_handler_disconnect (e_cal_backend_get_source (E_CAL_BACKEND (cbhttp)), priv->source_changed_id);
+		priv->source_changed_id = 0;
+	}
 
 	if (G_OBJECT_CLASS (parent_class)->dispose)
 		(* G_OBJECT_CLASS (parent_class)->dispose) (object);
@@ -250,6 +259,12 @@ retrieval_done (SoupSession *session, SoupMessage *msg, ECalBackendHttp *cbhttp)
 	priv->is_loading = FALSE;
 	d(g_message ("Retrieval done.\n"));
 
+	if (!priv->uri) {
+		/* uri changed meanwhile, retrieve again */
+		begin_retrieval_cb (cbhttp);
+		return;
+	}
+
 	/* Handle redirection ourselves */
 	if (SOUP_STATUS_IS_REDIRECTION (msg->status_code)) {
 		newuri = soup_message_headers_get (msg->response_headers,
@@ -278,6 +293,8 @@ retrieval_done (SoupSession *session, SoupMessage *msg, ECalBackendHttp *cbhttp)
 			e_cal_backend_notify_error (E_CAL_BACKEND (cbhttp),
 						    soup_status_get_phrase (msg->status_code));
 		}
+
+		e_cal_backend_empty_cache (E_CAL_BACKEND (cbhttp), priv->cache);
 		return;
 	}
 
@@ -287,6 +304,7 @@ retrieval_done (SoupSession *session, SoupMessage *msg, ECalBackendHttp *cbhttp)
 	if (!icalcomp) {
 		if (!priv->opened)
 			e_cal_backend_notify_error (E_CAL_BACKEND (cbhttp), _("Bad file format."));
+		e_cal_backend_empty_cache (E_CAL_BACKEND (cbhttp), priv->cache);
 		return;
 	}
 
@@ -294,6 +312,7 @@ retrieval_done (SoupSession *session, SoupMessage *msg, ECalBackendHttp *cbhttp)
 		if (!priv->opened)
 			e_cal_backend_notify_error (E_CAL_BACKEND (cbhttp), _("Not a calendar."));
 		icalcomponent_free (icalcomp);
+		e_cal_backend_empty_cache (E_CAL_BACKEND (cbhttp), priv->cache);
 		return;
 	}
 
@@ -414,7 +433,7 @@ begin_retrieval_cb (ECalBackendHttp *cbhttp)
 	priv = cbhttp->priv;
 
 	if (priv->mode != CAL_MODE_REMOTE)
-		return TRUE;
+		return FALSE;
 
 	maybe_start_reload_timeout (cbhttp);
 
@@ -459,6 +478,7 @@ begin_retrieval_cb (ECalBackendHttp *cbhttp)
 	soup_message = soup_message_new (SOUP_METHOD_GET, priv->uri);
 	if (soup_message == NULL) {
 		priv->is_loading = FALSE;
+		e_cal_backend_empty_cache (E_CAL_BACKEND (cbhttp), priv->cache);
 		return FALSE;
 	}
 
@@ -517,6 +537,37 @@ maybe_start_reload_timeout (ECalBackendHttp *cbhttp)
 						 (GSourceFunc) reload_cb, cbhttp);
 }
 
+static void
+source_changed_cb (ESource *source, ECalBackendHttp *cbhttp)
+{
+	ECalBackendHttpPrivate *priv;
+
+	g_return_if_fail (cbhttp != NULL);
+	g_return_if_fail (cbhttp->priv != NULL);
+
+	priv = cbhttp->priv;
+
+	if (priv->uri) {
+		ESource *source = e_cal_backend_get_source (E_CAL_BACKEND (cbhttp));
+		const gchar *secure_prop = e_source_get_property (source, "use_ssl");
+		gchar *new_uri;
+
+		new_uri = webcal_to_http_method (e_cal_backend_get_uri (E_CAL_BACKEND (cbhttp)),
+						 (secure_prop && g_str_equal(secure_prop, "1")));
+
+		if (new_uri && !g_str_equal (priv->uri, new_uri)) {
+			/* uri changed, do reload some time soon */
+			g_free (priv->uri);
+			priv->uri = NULL;
+
+			if (!priv->is_loading)
+				g_idle_add ((GSourceFunc) begin_retrieval_cb, cbhttp);
+		}
+
+		g_free (new_uri);
+	}
+}
+
 /* Open handler for the file backend */
 static ECalBackendSyncStatus
 e_cal_backend_http_open (ECalBackendSync *backend, EDataCal *cal, gboolean only_if_exists,
@@ -525,11 +576,21 @@ e_cal_backend_http_open (ECalBackendSync *backend, EDataCal *cal, gboolean only_
 	ECalBackendHttp *cbhttp;
 	ECalBackendHttpPrivate *priv;
 	ESource *source;
+	gchar *tmp;
 
 	cbhttp = E_CAL_BACKEND_HTTP (backend);
 	priv = cbhttp->priv;
 	source = e_cal_backend_get_source (E_CAL_BACKEND (backend));
 
+	if (priv->source_changed_id == 0) {
+		priv->source_changed_id = g_signal_connect (source, "changed", G_CALLBACK (source_changed_cb), cbhttp);
+	}
+
+	/* always read uri again */
+	tmp = priv->uri;
+	priv->uri = NULL;
+	g_free (tmp);
+
 	if (e_source_get_property (source, "auth") != NULL) {
 		if ((username == NULL || password == NULL)) {
 			return GNOME_Evolution_Calendar_AuthenticationRequired;
@@ -565,13 +626,13 @@ e_cal_backend_http_open (ECalBackendSync *backend, EDataCal *cal, gboolean only_
 		if (priv->default_zone) {
 			e_cal_backend_cache_put_default_timezone (priv->cache, priv->default_zone);
 		}
+	}
 
-		if (priv->mode == CAL_MODE_LOCAL)
-			return GNOME_Evolution_Calendar_Success;
+	if (priv->mode == CAL_MODE_LOCAL)
+		return GNOME_Evolution_Calendar_Success;
 
 
-		g_idle_add ((GSourceFunc) begin_retrieval_cb, cbhttp);
-	}
+	g_idle_add ((GSourceFunc) begin_retrieval_cb, cbhttp);
 
 	return GNOME_Evolution_Calendar_Success;
 }
diff --git a/calendar/libedata-cal/e-cal-backend-cache.h b/calendar/libedata-cal/e-cal-backend-cache.h
index 725a22e..15c694a 100644
--- a/calendar/libedata-cal/e-cal-backend-cache.h
+++ b/calendar/libedata-cal/e-cal-backend-cache.h
@@ -34,12 +34,13 @@ G_BEGIN_DECLS
 #define E_IS_CAL_BACKEND_CACHE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_CAL_BACKEND_CACHE))
 #define E_IS_CAL_BACKEND_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_CAL_BACKEND_CACHE))
 
+typedef struct _ECalBackendCache ECalBackendCache;
 typedef struct _ECalBackendCachePrivate ECalBackendCachePrivate;
 
-typedef struct {
+struct _ECalBackendCache {
 	EFileCache parent;
 	ECalBackendCachePrivate *priv;
-} ECalBackendCache;
+};
 
 typedef struct {
 	EFileCacheClass parent_class;
diff --git a/calendar/libedata-cal/e-cal-backend.c b/calendar/libedata-cal/e-cal-backend.c
index 7bc19c0..1d9345e 100644
--- a/calendar/libedata-cal/e-cal-backend.c
+++ b/calendar/libedata-cal/e-cal-backend.c
@@ -27,6 +27,7 @@
 #include <libxml/xmlmemory.h>
 
 #include "e-cal-backend.h"
+#include "e-cal-backend-cache.h"
 
 
 
@@ -36,6 +37,8 @@ G_DEFINE_TYPE (ECalBackend, e_cal_backend, G_TYPE_OBJECT)
 struct _ECalBackendPrivate {
 	/* The source for this backend */
 	ESource *source;
+	/* signal handler ID for source's 'changed' signal */
+	gulong source_changed_id;
 
 	/* URI, from source. This is cached, since we return const. */
 	gchar *uri;
@@ -86,6 +89,29 @@ static void e_cal_backend_finalize (GObject *object);
 
 
 static void
+source_changed_cb (ESource *source, ECalBackend *backend)
+{
+	ECalBackendPrivate *priv;
+	gchar *suri;
+
+	g_return_if_fail (source != NULL);
+	g_return_if_fail (backend != NULL);
+	g_return_if_fail (E_IS_CAL_BACKEND (backend));
+
+	priv = backend->priv;
+	g_return_if_fail (priv != NULL);
+	g_return_if_fail (priv->source == source);
+
+	suri = e_source_get_uri (priv->source);
+	if (!priv->uri || (suri && !g_str_equal (priv->uri, suri))) {
+		g_free (priv->uri);
+		priv->uri = suri;
+	} else {
+		g_free (suri);
+	}
+}
+
+static void
 e_cal_backend_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
 {
 	ECalBackend *backend;
@@ -99,9 +125,16 @@ e_cal_backend_set_property (GObject *object, guint property_id, const GValue *va
 		{
 			ESource *new_source;
 
+			if (priv->source_changed_id && priv->source) {
+				g_signal_handler_disconnect (priv->source, priv->source_changed_id);
+				priv->source_changed_id = 0;
+			}
+
 			new_source = g_value_get_object (value);
-			if (new_source)
+			if (new_source) {
 				g_object_ref (new_source);
+				priv->source_changed_id = g_signal_connect (new_source, "changed", G_CALLBACK (source_changed_cb), backend);
+			}
 
 			if (priv->source)
 				g_object_unref (priv->source);
@@ -275,6 +308,10 @@ e_cal_backend_finalize (GObject *object)
 	g_mutex_free (priv->queries_mutex);
 
 	g_free (priv->uri);
+	if (priv->source_changed_id && priv->source) {
+		g_signal_handler_disconnect (priv->source, priv->source_changed_id);
+		priv->source_changed_id = 0;
+	}
 	g_object_unref (priv->source);
 
 	G_OBJECT_CLASS (e_cal_backend_parent_class)->finalize (object);
@@ -1456,3 +1493,49 @@ e_cal_backend_notify_error (ECalBackend *backend, const gchar *message)
 	for (l = priv->clients; l; l = l->next)
 		e_data_cal_notify_error (l->data, message);
 }
+
+/**
+ * e_cal_backend_empty_cache:
+ * @backend: A calendar backend.
+ * @cache: Backend's cache to empty.
+ *
+ * Empties backend's cache with all notifications and so on, thus all listening
+ * will know there is nothing in this backend.
+ **/
+void
+e_cal_backend_empty_cache (ECalBackend *backend, ECalBackendCache *cache)
+{
+	GList *comps_in_cache;
+
+	g_return_if_fail (backend != NULL);
+	g_return_if_fail (E_IS_CAL_BACKEND (backend));
+
+	if (!cache)
+		return;
+
+	g_return_if_fail (E_IS_CAL_BACKEND_CACHE (cache));
+
+	e_file_cache_freeze_changes (E_FILE_CACHE (cache));
+
+	for (comps_in_cache = e_cal_backend_cache_get_components (cache);
+	     comps_in_cache;
+	     comps_in_cache = comps_in_cache->next) {
+		gchar *comp_str;
+		ECalComponentId *id;
+		ECalComponent *comp = comps_in_cache->data;
+
+		id = e_cal_component_get_id (comp);
+		comp_str = e_cal_component_get_as_string (comp);
+
+		e_cal_backend_cache_remove_component (cache, id->uid, id->rid);
+		e_cal_backend_notify_object_removed (backend, id, comp_str, NULL);
+
+		g_free (comp_str);
+		e_cal_component_free_id (id);
+		g_object_unref (comp);
+	}
+
+	g_list_free (comps_in_cache);
+
+	e_file_cache_thaw_changes (E_FILE_CACHE (cache));
+}
diff --git a/calendar/libedata-cal/e-cal-backend.h b/calendar/libedata-cal/e-cal-backend.h
index dd5c857..ea1fc81 100644
--- a/calendar/libedata-cal/e-cal-backend.h
+++ b/calendar/libedata-cal/e-cal-backend.h
@@ -44,6 +44,8 @@ G_BEGIN_DECLS
 #define E_IS_CAL_BACKEND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_CAL_BACKEND))
 #define E_CAL_BACKEND_GET_CLASS(obj) (E_CAL_BACKEND_CLASS (G_OBJECT_GET_CLASS (obj)))
 
+struct _ECalBackendCache;
+
 typedef struct _ECalBackendPrivate ECalBackendPrivate;
 
 struct _ECalBackend {
@@ -188,6 +190,8 @@ void e_cal_backend_notify_objects_added (ECalBackend *backend, EDataCalView *que
 void e_cal_backend_notify_objects_removed (ECalBackend *backend, EDataCalView *query, const GList *ids);
 void e_cal_backend_notify_objects_modified (ECalBackend *backend, EDataCalView *query, const GList *objects);
 
+void e_cal_backend_empty_cache (ECalBackend *backend, struct _ECalBackendCache *cache);
+
 G_END_DECLS
 
 #endif
diff --git a/calendar/libedata-cal/e-data-cal-factory.c b/calendar/libedata-cal/e-data-cal-factory.c
index 2c4da5b..090c323 100644
--- a/calendar/libedata-cal/e-data-cal-factory.c
+++ b/calendar/libedata-cal/e-data-cal-factory.c
@@ -25,7 +25,9 @@
 #include <bonobo/bonobo-main.h>
 #include "libedataserver/e-url.h"
 #include "libedataserver/e-source.h"
+#include "libedataserver/e-source-list.h"
 #include "libebackend/e-data-server-module.h"
+#include "libecal/e-cal.h"
 #include "e-cal-backend.h"
 #include "e-data-cal.h"
 #include "e-data-cal-factory.h"
@@ -52,6 +54,12 @@ struct _EDataCalFactoryPrivate {
 	guint registered : 1;
 
         gint mode;
+
+	/* this is for notifications of source changes */
+	ESourceList *lists[E_CAL_SOURCE_TYPE_LAST];
+
+	/* backends divided by their type */
+	GSList *backends_by_type[E_CAL_SOURCE_TYPE_LAST];
 };
 
 /* Signal IDs */
@@ -79,6 +87,74 @@ calobjtype_to_icalkind (const GNOME_Evolution_Calendar_CalObjType type)
 	return ICAL_NO_COMPONENT;
 }
 
+static ECalSourceType
+icalkind_to_ecalsourcetype (const icalcomponent_kind kind)
+{
+	switch (kind) {
+	case ICAL_VEVENT_COMPONENT:
+		return E_CAL_SOURCE_TYPE_EVENT;
+	case ICAL_VTODO_COMPONENT:
+		return E_CAL_SOURCE_TYPE_TODO;
+	case ICAL_VJOURNAL_COMPONENT:
+		return E_CAL_SOURCE_TYPE_JOURNAL;
+	default:
+		break;
+	}
+
+	return E_CAL_SOURCE_TYPE_LAST;
+}
+
+static void
+update_source_in_backend (ECalBackend *backend, ESource *updated_source)
+{
+	xmlNodePtr xml;
+
+	g_return_if_fail (backend != NULL);
+	g_return_if_fail (updated_source != NULL);
+
+	xml = xmlNewNode (NULL, (const xmlChar *)"dummy");
+	e_source_dump_to_xml_node (updated_source, xml);
+	e_source_update_from_xml_node (e_cal_backend_get_source (backend), xml->children, NULL);
+	xmlFreeNode (xml);
+}
+
+static void
+source_list_changed_cb (ESourceList *list, EDataCalFactory *factory)
+{
+	EDataCalFactoryPrivate *priv;
+	gint i;
+
+	g_return_if_fail (list != NULL);
+	g_return_if_fail (factory != NULL);
+	g_return_if_fail (E_IS_DATA_CAL_FACTORY (factory));
+
+	priv = factory->priv;
+
+	g_mutex_lock (priv->backends_mutex);
+
+	for (i = 0; i < E_CAL_SOURCE_TYPE_LAST; i++) {
+		if (list == priv->lists[i]) {
+			GSList *l;
+
+			for (l = priv->backends_by_type [i]; l; l = l->next) {
+				ECalBackend *backend = l->data;
+				ESource *source, *list_source;
+
+				source = e_cal_backend_get_source (backend);
+				list_source = e_source_list_peek_source_by_uid (priv->lists[i], e_source_peek_uid (source));
+
+				if (list_source) {
+					update_source_in_backend (backend, list_source);
+				}
+			}
+
+			break;
+		}
+	}
+
+	g_mutex_unlock (priv->backends_mutex);
+}
+
 static ECalBackendFactory*
 get_backend_factory (GHashTable *methods, const gchar *method, icalcomponent_kind kind)
 {
@@ -103,8 +179,9 @@ backend_last_client_gone_cb (ECalBackend *backend, gpointer data)
 	EDataCalFactory *factory;
 	EDataCalFactoryPrivate *priv;
 	ECalBackend *ret_backend;
-	const gchar *uristr;
-	gchar *uri;
+	ECalSourceType st;
+	ESource *source;
+	gchar *uid_type_string;
 	gboolean last_calendar;
 
 	fprintf (stderr, "backend_last_client_gone_cb() called!\n");
@@ -114,18 +191,23 @@ backend_last_client_gone_cb (ECalBackend *backend, gpointer data)
 
 	/* Remove the backend from the hash table */
 
-	uristr = e_cal_backend_get_uri (backend);
-	g_assert (uristr != NULL);
-	uri = g_strdup_printf("%s:%d", uristr, (gint)e_cal_backend_get_kind(backend));
+	source = e_cal_backend_get_source (backend);
+	g_assert (source != NULL);
+	uid_type_string = g_strdup_printf ("%s:%d", e_source_peek_uid (source), (gint)e_cal_backend_get_kind (backend));
 
 	g_mutex_lock (priv->backends_mutex);
 
-	ret_backend = g_hash_table_lookup (factory->priv->backends, uri);
+	st = icalkind_to_ecalsourcetype (e_cal_backend_get_kind (backend));
+	if (st != E_CAL_SOURCE_TYPE_LAST && priv->backends_by_type [st]) {
+		priv->backends_by_type [st] = g_slist_remove (priv->backends_by_type [st], backend);
+	}
+
+	ret_backend = g_hash_table_lookup (priv->backends, uid_type_string);
 	g_assert (ret_backend != NULL);
 	g_assert (ret_backend == backend);
 
-	g_hash_table_remove (priv->backends, uri);
-	g_free(uri);
+	g_hash_table_remove (priv->backends, uid_type_string);
+	g_free (uid_type_string);
 
 	g_signal_handlers_disconnect_matched (backend, G_SIGNAL_MATCH_DATA,
 					      0, 0, NULL, NULL, data);
@@ -157,7 +239,7 @@ impl_CalFactory_getCal (PortableServer_Servant servant,
 	ESource *source;
 	gchar *str_uri;
 	EUri *uri;
-	gchar *uri_type_string;
+	gchar *uid_type_string;
 
 	factory = E_DATA_CAL_FACTORY (bonobo_object_from_servant (servant));
 	priv = factory->priv;
@@ -186,22 +268,24 @@ impl_CalFactory_getCal (PortableServer_Servant servant,
 		return CORBA_OBJECT_NIL;
 	}
 
-	uri_type_string = g_strdup_printf ("%s:%d", str_uri, (gint)calobjtype_to_icalkind (type));
-	g_free(str_uri);
+	g_free (str_uri);
+	uid_type_string = g_strdup_printf ("%s:%d", e_source_peek_uid (source), (gint)calobjtype_to_icalkind (type));
 
 	/* Find the associated backend factory (if any) */
 	backend_factory = get_backend_factory (priv->methods, uri->protocol, calobjtype_to_icalkind (type));
 	if (!backend_factory) {
 		/* FIXME Distinguish between method and kind failures? */
 		bonobo_exception_set (ev, ex_GNOME_Evolution_Calendar_CalFactory_UnsupportedMethod);
-		goto cleanup;
+		goto cleanup2;
 	}
 
 	g_mutex_lock (priv->backends_mutex);
 
 	/* Look for an existing backend */
-	backend = g_hash_table_lookup (factory->priv->backends, uri_type_string);
+	backend = g_hash_table_lookup (factory->priv->backends, uid_type_string);
 	if (!backend) {
+		ECalSourceType st;
+
 		/* There was no existing backend, create a new one */
 		if (E_IS_CAL_BACKEND_LOADER_FACTORY (backend_factory)) {
 			backend = E_CAL_BACKEND_LOADER_FACTORY_GET_CLASS (backend_factory)->new_backend_with_protocol ((ECalBackendLoaderFactory *)backend_factory,
@@ -215,12 +299,25 @@ impl_CalFactory_getCal (PortableServer_Servant servant,
 			goto cleanup;
 		}
 
+		st = icalkind_to_ecalsourcetype (e_cal_backend_get_kind (backend));
+		if (st != E_CAL_SOURCE_TYPE_LAST) {
+			if (!priv->lists[st] && e_cal_get_sources (&(priv->lists[st]), st, NULL)) {
+				g_signal_connect (priv->lists[st], "changed", G_CALLBACK (source_list_changed_cb), factory);
+			}
+
+			if (priv->lists[st])
+				priv->backends_by_type[st] = g_slist_prepend (priv->backends_by_type[st], backend);
+		}
+
 		/* Track the backend */
-		g_hash_table_insert (priv->backends, g_strdup (uri_type_string), backend);
+		g_hash_table_insert (priv->backends, g_strdup (uid_type_string), backend);
 
 		g_signal_connect (G_OBJECT (backend), "last_client_gone",
 				  G_CALLBACK (backend_last_client_gone_cb),
 				  factory);
+	} else if (!e_source_equal (source, e_cal_backend_get_source (backend))) {
+		/* source changed, update it in a backend */
+		update_source_in_backend (backend, source);
 	}
 
 	/* Create the corba calendar */
@@ -241,8 +338,9 @@ impl_CalFactory_getCal (PortableServer_Servant servant,
 	   before e_cal_backend_finalize() is called from the
 	   backend_last_client_gone_cb(), for details see bug 506457. */
 	g_mutex_unlock (priv->backends_mutex);
+ cleanup2:
 	e_uri_free (uri);
-	g_free (uri_type_string);
+	g_free (uid_type_string);
 	g_object_unref (source);
 
 	return ret_cal;
@@ -276,6 +374,7 @@ e_data_cal_factory_finalize (GObject *object)
 {
 	EDataCalFactory *factory;
 	EDataCalFactoryPrivate *priv;
+	gint i;
 
 	g_return_if_fail (object != NULL);
 	g_return_if_fail (E_IS_DATA_CAL_FACTORY (object));
@@ -297,6 +396,18 @@ e_data_cal_factory_finalize (GObject *object)
 	}
 	g_free (priv->iid);
 
+	for (i = 0; i < E_CAL_SOURCE_TYPE_LAST; i++) {
+		if (priv->lists[i]) {
+			g_object_unref (priv->lists[i]);
+			priv->lists[i] = NULL;
+		}
+
+		if (priv->backends_by_type[i]) {
+			g_slist_free (priv->backends_by_type[i]);
+			priv->backends_by_type[i] = NULL;
+		}
+	}
+
 	g_free (priv);
 	factory->priv = NULL;
 
diff --git a/libedataserver/e-source.c b/libedataserver/e-source.c
index bdb1f57..21c1113 100644
--- a/libedataserver/e-source.c
+++ b/libedataserver/e-source.c
@@ -310,11 +310,26 @@ e_source_update_from_xml_node (ESource *source,
 	if (source->priv->name == NULL
 	    || strcmp ((gchar *)name, source->priv->name) != 0
 	    || source->priv->relative_uri == NULL
-	    || relative_uri != NULL
+	    || relative_uri == NULL
 	    || strcmp ((gchar *)relative_uri, source->priv->relative_uri) != 0) {
 		g_free (source->priv->name);
 		source->priv->name = g_strdup ((gchar *)name);
 
+		if (source->priv->group) {
+			/* reset the absolute uri to NULL to be regenerated when asked for */
+			g_free (source->priv->absolute_uri);
+			source->priv->absolute_uri = NULL;
+		} else if (source->priv->absolute_uri &&
+			   source->priv->relative_uri &&
+			   g_str_has_suffix (source->priv->absolute_uri, source->priv->relative_uri)) {
+			gchar *tmp = source->priv->absolute_uri;
+
+			tmp [strlen (tmp) - strlen (source->priv->relative_uri)] = 0;
+			source->priv->absolute_uri = g_strconcat (tmp, (gchar *)relative_uri, NULL);
+
+			g_free (tmp);
+		}
+
 		g_free (source->priv->relative_uri);
 		source->priv->relative_uri = g_strdup ((gchar *)relative_uri);
 



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