[evolution-data-server] e-cal-client.c cleanups.



commit 59066d58fc95bdc0de6cbdbaa0634e70b11c79ec
Author: Matthew Barnes <mbarnes redhat com>
Date:   Sat Oct 6 19:34:48 2012 -0400

    e-cal-client.c cleanups.
    
    Mostly just code rearrangement.

 calendar/libecal/e-cal-client.c | 2399 ++++++++++++++++++++-------------------
 1 files changed, 1217 insertions(+), 1182 deletions(-)
---
diff --git a/calendar/libecal/e-cal-client.c b/calendar/libecal/e-cal-client.c
index 5f80747..4b570df 100644
--- a/calendar/libecal/e-cal-client.c
+++ b/calendar/libecal/e-cal-client.c
@@ -65,6 +65,12 @@ static guint signals[LAST_SIGNAL];
 
 G_DEFINE_TYPE (ECalClient, e_cal_client, E_TYPE_CLIENT)
 
+static void
+free_zone_cb (gpointer zone)
+{
+	icaltimezone_free (zone, 1);
+}
+
 /*
  * Well-known calendar backend properties:
  * @CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS: Contains default calendar's email
@@ -228,46 +234,46 @@ set_proxy_gone_error (GError **error)
 }
 
 static guint active_cal_clients = 0, cal_connection_closed_id = 0;
-static EGdbusCalFactory *cal_factory_proxy = NULL;
-static GStaticRecMutex cal_factory_proxy_lock = G_STATIC_REC_MUTEX_INIT;
-#define LOCK_FACTORY()   g_static_rec_mutex_lock (&cal_factory_proxy_lock)
-#define UNLOCK_FACTORY() g_static_rec_mutex_unlock (&cal_factory_proxy_lock)
+static EGdbusCalFactory *cal_factory = NULL;
+static GStaticRecMutex cal_factory_lock = G_STATIC_REC_MUTEX_INIT;
+#define LOCK_FACTORY()   g_static_rec_mutex_lock (&cal_factory_lock)
+#define UNLOCK_FACTORY() g_static_rec_mutex_unlock (&cal_factory_lock)
 
-static void gdbus_cal_factory_proxy_closed_cb (GDBusConnection *connection, gboolean remote_peer_vanished, GError *error, gpointer user_data);
+static void gdbus_cal_factory_closed_cb (GDBusConnection *connection, gboolean remote_peer_vanished, GError *error, gpointer user_data);
 
 static void
-gdbus_cal_factory_proxy_disconnect (GDBusConnection *connection)
+gdbus_cal_factory_disconnect (GDBusConnection *connection)
 {
 	LOCK_FACTORY ();
 
-	if (!connection && cal_factory_proxy)
-		connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (cal_factory_proxy));
+	if (!connection && cal_factory)
+		connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (cal_factory));
 
 	if (connection && cal_connection_closed_id) {
 		g_dbus_connection_signal_unsubscribe (connection, cal_connection_closed_id);
-		g_signal_handlers_disconnect_by_func (connection, gdbus_cal_factory_proxy_closed_cb, NULL);
+		g_signal_handlers_disconnect_by_func (connection, gdbus_cal_factory_closed_cb, NULL);
 	}
 
-	if (cal_factory_proxy)
-		g_object_unref (cal_factory_proxy);
+	if (cal_factory != NULL)
+		g_object_unref (cal_factory);
 
 	cal_connection_closed_id = 0;
-	cal_factory_proxy = NULL;
+	cal_factory = NULL;
 
 	UNLOCK_FACTORY ();
 }
 
 static void
-gdbus_cal_factory_proxy_closed_cb (GDBusConnection *connection,
-                                   gboolean remote_peer_vanished,
-                                   GError *error,
-                                   gpointer user_data)
+gdbus_cal_factory_closed_cb (GDBusConnection *connection,
+                             gboolean remote_peer_vanished,
+                             GError *error,
+                             gpointer user_data)
 {
 	GError *err = NULL;
 
 	LOCK_FACTORY ();
 
-	gdbus_cal_factory_proxy_disconnect (connection);
+	gdbus_cal_factory_disconnect (connection);
 
 	if (error)
 		unwrap_dbus_error (g_error_copy (error), &err);
@@ -293,36 +299,37 @@ gdbus_cal_factory_connection_gone_cb (GDBusConnection *connection,
 {
 	/* signal subscription takes care of correct parameters,
 	 * thus just do what is to be done here */
-	gdbus_cal_factory_proxy_closed_cb (connection, TRUE, NULL, user_data);
+	gdbus_cal_factory_closed_cb (connection, TRUE, NULL, user_data);
 }
 
 static gboolean
-gdbus_cal_factory_activate (GError **error)
+gdbus_cal_factory_activate (GCancellable *cancellable,
+                            GError **error)
 {
 	GDBusConnection *connection;
 
 	LOCK_FACTORY ();
 
-	if (G_LIKELY (cal_factory_proxy)) {
+	if (G_LIKELY (cal_factory != NULL)) {
 		UNLOCK_FACTORY ();
 		return TRUE;
 	}
 
-	cal_factory_proxy = e_gdbus_cal_factory_proxy_new_for_bus_sync (
+	cal_factory = e_gdbus_cal_factory_proxy_new_for_bus_sync (
 		G_BUS_TYPE_SESSION,
 		G_DBUS_PROXY_FLAGS_NONE,
 		CALENDAR_DBUS_SERVICE_NAME,
 		"/org/gnome/evolution/dataserver/CalendarFactory",
-		NULL,
-		error);
+		cancellable, error);
 
-	if (!cal_factory_proxy) {
+	if (cal_factory == NULL) {
 		UNLOCK_FACTORY ();
 		return FALSE;
 	}
 
-	connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (cal_factory_proxy));
-	cal_connection_closed_id = g_dbus_connection_signal_subscribe (connection,
+	connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (cal_factory));
+	cal_connection_closed_id = g_dbus_connection_signal_subscribe (
+		connection,
 		NULL,						/* sender */
 		"org.freedesktop.DBus",				/* interface */
 		"NameOwnerChanged",				/* member */
@@ -331,7 +338,9 @@ gdbus_cal_factory_activate (GError **error)
 		G_DBUS_SIGNAL_FLAGS_NONE,
 		gdbus_cal_factory_connection_gone_cb, NULL, NULL);
 
-	g_signal_connect (connection, "closed", G_CALLBACK (gdbus_cal_factory_proxy_closed_cb), NULL);
+	g_signal_connect (
+		connection, "closed",
+		G_CALLBACK (gdbus_cal_factory_closed_cb), NULL);
 
 	UNLOCK_FACTORY ();
 
@@ -569,438 +578,870 @@ icalcomponent_slist_to_string_slist (GSList *icalcomponents)
 	return g_slist_reverse (strings);
 }
 
-/**
- * e_cal_client_new:
- * @source: An #ESource pointer
- * @source_type: source type of the calendar
- * @error: A #GError pointer
- *
- * Creates a new #ECalClient corresponding to the given source.  There are
- * only two operations that are valid on this calendar at this point:
- * e_client_open(), and e_client_remove().
- *
- * Returns: a new but unopened #ECalClient.
- *
- * Since: 3.2
- **/
-ECalClient *
-e_cal_client_new (ESource *source,
-                  ECalClientSourceType source_type,
-                  GError **error)
+static gboolean
+cal_client_get_backend_property_from_cache_finish (EClient *client,
+                                                   GAsyncResult *result,
+                                                   gchar **prop_value,
+                                                   GError **error)
 {
-	ECalClient *client;
-	GError *err = NULL;
-	GDBusConnection *connection;
-	const gchar *uid;
-	gchar **strv;
-	gchar *path = NULL;
-
-	g_return_val_if_fail (E_IS_SOURCE (source), NULL);
-	g_return_val_if_fail (source_type == E_CAL_CLIENT_SOURCE_TYPE_EVENTS || source_type == E_CAL_CLIENT_SOURCE_TYPE_TASKS || source_type == E_CAL_CLIENT_SOURCE_TYPE_MEMOS, NULL);
+	GSimpleAsyncResult *simple;
+	GError *local_error = NULL;
 
-	LOCK_FACTORY ();
-	if (!gdbus_cal_factory_activate (&err)) {
-		UNLOCK_FACTORY ();
-		if (err) {
-			unwrap_dbus_error (err, &err);
-			g_warning ("%s: Failed to run calendar factory: %s", G_STRFUNC, err->message);
-			g_propagate_error (error, err);
-		} else {
-			g_warning ("%s: Failed to run calendar factory: Unknown error", G_STRFUNC);
-			g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_DBUS_ERROR, _("Failed to run calendar factory"));
-		}
+	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+	g_return_val_if_fail (result != NULL, FALSE);
+	g_return_val_if_fail (prop_value != NULL, FALSE);
+	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (client), cal_client_get_backend_property_from_cache_finish), FALSE);
 
-		return NULL;
-	}
+	simple = G_SIMPLE_ASYNC_RESULT (result);
 
-	uid = e_source_get_uid (source);
-	strv = e_gdbus_cal_factory_encode_get_cal (uid, convert_type (source_type));
-	if (!strv) {
-		g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_OTHER_ERROR, _("Other error"));
-		return NULL;
+	if (g_simple_async_result_propagate_error (simple, &local_error)) {
+		e_client_unwrap_dbus_error (client, local_error, error);
+		return FALSE;
 	}
 
-	client = g_object_new (E_TYPE_CAL_CLIENT, "source", source, NULL);
-	client->priv->source_type = source_type;
-
-	UNLOCK_FACTORY ();
+	*prop_value = g_strdup (g_simple_async_result_get_op_res_gpointer (simple));
 
-	if (!e_gdbus_cal_factory_call_get_cal_sync (G_DBUS_PROXY (cal_factory_proxy), (const gchar * const *) strv, &path, NULL, &err)) {
-		unwrap_dbus_error (err, &err);
-		g_strfreev (strv);
-		g_warning ("%s: Cannot get calendar from factory: %s", G_STRFUNC, err ? err->message : "[no error]");
-		if (err)
-			g_propagate_error (error, err);
-		g_object_unref (client);
+	return *prop_value != NULL;
+}
 
-		return NULL;
-	}
+static void
+cal_client_dispose (GObject *object)
+{
+	EClient *client;
 
-	g_strfreev (strv);
+	client = E_CLIENT (object);
 
-	client->priv->gdbus_cal = G_DBUS_PROXY (e_gdbus_cal_proxy_new_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (cal_factory_proxy)),
-						      G_DBUS_PROXY_FLAGS_NONE,
-						      CALENDAR_DBUS_SERVICE_NAME,
-						      path,
-						      NULL,
-						      &err));
+	e_client_cancel_all (client);
 
-	if (!client->priv->gdbus_cal) {
-		g_free (path);
-		unwrap_dbus_error (err, &err);
-		g_warning ("%s: Cannot create calendar proxy: %s", G_STRFUNC, err ? err->message : "Unknown error");
-		if (err)
-			g_propagate_error (error, err);
+	gdbus_cal_client_disconnect (E_CAL_CLIENT (client));
 
-		g_object_unref (client);
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (e_cal_client_parent_class)->dispose (object);
+}
 
-		return NULL;
-	}
+static void
+cal_client_finalize (GObject *object)
+{
+	ECalClient *client;
+	ECalClientPrivate *priv;
 
-	g_free (path);
+	client = E_CAL_CLIENT (object);
 
-	connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (client->priv->gdbus_cal));
-	client->priv->gone_signal_id = g_dbus_connection_signal_subscribe (connection,
-		"org.freedesktop.DBus",				/* sender */
-		"org.freedesktop.DBus",				/* interface */
-		"NameOwnerChanged",				/* member */
-		"/org/freedesktop/DBus",			/* object_path */
-		"org.gnome.evolution.dataserver.Calendar",	/* arg0 */
-		G_DBUS_SIGNAL_FLAGS_NONE,
-		gdbus_cal_client_connection_gone_cb, client, NULL);
+	priv = client->priv;
 
-	g_signal_connect (connection, "closed", G_CALLBACK (gdbus_cal_client_closed_cb), client);
+	g_free (priv->cache_dir);
+	priv->cache_dir = NULL;
 
-	g_signal_connect (client->priv->gdbus_cal, "backend_error", G_CALLBACK (backend_error_cb), client);
-	g_signal_connect (client->priv->gdbus_cal, "readonly", G_CALLBACK (readonly_cb), client);
-	g_signal_connect (client->priv->gdbus_cal, "online", G_CALLBACK (online_cb), client);
-	g_signal_connect (client->priv->gdbus_cal, "opened", G_CALLBACK (opened_cb), client);
-	g_signal_connect (client->priv->gdbus_cal, "free-busy-data", G_CALLBACK (free_busy_data_cb), client);
-	g_signal_connect (client->priv->gdbus_cal, "backend-property-changed", G_CALLBACK (backend_property_changed_cb), client);
+	if (priv->default_zone && priv->default_zone != icaltimezone_get_utc_timezone ())
+		icaltimezone_free (priv->default_zone, 1);
+	priv->default_zone = NULL;
 
-	return client;
-}
+	g_mutex_lock (priv->zone_cache_lock);
+	g_hash_table_destroy (priv->zone_cache);
+	priv->zone_cache = NULL;
+	g_mutex_unlock (priv->zone_cache_lock);
+	g_mutex_free (priv->zone_cache_lock);
+	priv->zone_cache_lock = NULL;
 
-/**
- * e_cal_client_get_source_type:
- * @client: A calendar client.
- *
- * Gets the source type of the calendar client.
- *
- * Returns: an #ECalClientSourceType value corresponding
- * to the source type of the calendar client.
- *
- * Since: 3.2
- **/
-ECalClientSourceType
-e_cal_client_get_source_type (ECalClient *client)
-{
-	g_return_val_if_fail (E_IS_CAL_CLIENT (client), E_CAL_CLIENT_SOURCE_TYPE_LAST);
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (e_cal_client_parent_class)->finalize (object);
 
-	return client->priv->source_type;
+	LOCK_FACTORY ();
+	active_cal_clients--;
+	if (!active_cal_clients)
+		gdbus_cal_factory_disconnect (NULL);
+	UNLOCK_FACTORY ();
 }
 
-/**
- * e_cal_client_get_local_attachment_store:
- * @client: A calendar client.
- *
- * Queries the URL where the calendar attachments are
- * serialized in the local filesystem. This enable clients
- * to operate with the reference to attachments rather than the data itself
- * unless it specifically uses the attachments for open/sending
- * operations.
- *
- * Returns: The URL where the attachments are serialized in the
- * local filesystem.
- *
- * Since: 3.2
- **/
-const gchar *
-e_cal_client_get_local_attachment_store (ECalClient *client)
+static GDBusProxy *
+cal_client_get_dbus_proxy (EClient *client)
 {
-	gchar *cache_dir = NULL;
-	GError *error = NULL;
+	ECalClient *cal_client;
 
 	g_return_val_if_fail (E_IS_CAL_CLIENT (client), NULL);
 
-	if (client->priv->cache_dir || !client->priv->gdbus_cal)
-		return client->priv->cache_dir;
-
-	cache_dir = e_client_get_backend_property_from_cache (E_CLIENT (client), CLIENT_BACKEND_PROPERTY_CACHE_DIR);
-	if (!cache_dir)
-		e_gdbus_cal_call_get_backend_property_sync (client->priv->gdbus_cal, CLIENT_BACKEND_PROPERTY_CACHE_DIR, &cache_dir, NULL, &error);
-
-	if (error == NULL) {
-		client->priv->cache_dir = cache_dir;
-	} else {
-		unwrap_dbus_error (error, &error);
-		g_warning ("%s", error->message);
-		g_error_free (error);
-	}
+	cal_client = E_CAL_CLIENT (client);
 
-	return client->priv->cache_dir;
+	return cal_client->priv->gdbus_cal;
 }
 
-/* icaltimezone_copy does a shallow copy while icaltimezone_free tries to free the entire 
- * the contents inside the structure with libical 0.43. Use this, till eds allows older libical.
-*/
-static icaltimezone *
-copy_timezone (icaltimezone *ozone)
+static void
+cal_client_unwrap_dbus_error (EClient *client,
+                              GError *dbus_error,
+                              GError **out_error)
 {
-	icaltimezone *zone = NULL;
-	const gchar *tzid;
-
-	tzid = icaltimezone_get_tzid (ozone);
-
-	if (g_strcmp0 (tzid, "UTC") != 0) {
-		icalcomponent *comp;
-
-		comp = icaltimezone_get_component (ozone);
-		if (comp) {
-			zone = icaltimezone_new ();
-			icaltimezone_set_component (zone, icalcomponent_new_clone (comp));
-		}
-	}
-
-	if (!zone)
-		zone = icaltimezone_get_utc_timezone ();
-
-	return zone;
+	unwrap_dbus_error (dbus_error, out_error);
 }
 
-/**
- * e_cal_client_set_default_timezone:
- * @client: A calendar client.
- * @zone: A timezone object.
- *
- * Sets the default timezone to use to resolve DATE and floating DATE-TIME
- * values. This will typically be from the user's timezone setting. Call this
- * before using any other object fetching functions.
- *
- * Since: 3.2
- **/
-void
-e_cal_client_set_default_timezone (ECalClient *client, /* const */ icaltimezone *zone)
+static void
+cal_client_retrieve_capabilities (EClient *client,
+                                  GCancellable *cancellable,
+                                  GAsyncReadyCallback callback,
+                                  gpointer user_data)
 {
 	g_return_if_fail (E_IS_CAL_CLIENT (client));
-	g_return_if_fail (zone != NULL);
-
-	if (client->priv->default_zone != icaltimezone_get_utc_timezone ())
-		icaltimezone_free (client->priv->default_zone, 1);
 
-	if (zone == icaltimezone_get_utc_timezone ())
-		client->priv->default_zone = zone;
-	else
-		client->priv->default_zone = copy_timezone (zone);
+	e_client_get_backend_property (client, CLIENT_BACKEND_PROPERTY_CAPABILITIES, cancellable, callback, user_data);
 }
 
-/**
- * e_cal_client_get_default_timezone:
- * @client: A calendar client.
- *
- * Returns: Default timezone previously set with e_cal_client_set_default_timezone().
- * Returned pointer is owned by the @client and should not be freed.
- *
- * Since: 3.2
- **/
-/* const */ icaltimezone *
-e_cal_client_get_default_timezone (ECalClient *client)
+static gboolean
+cal_client_retrieve_capabilities_finish (EClient *client,
+                                         GAsyncResult *result,
+                                         gchar **capabilities,
+                                         GError **error)
 {
-	g_return_val_if_fail (E_IS_CAL_CLIENT (client), NULL);
+	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
 
-	return client->priv->default_zone;
+	return e_client_get_backend_property_finish (client, result, capabilities, error);
 }
 
-/**
- * e_cal_client_check_one_alarm_only:
- * @client: A calendar client.
- *
- * Checks if a calendar supports only one alarm per component.
- *
- * Returns: TRUE if the calendar allows only one alarm, FALSE otherwise.
- *
- * Since: 3.2
- **/
-gboolean
-e_cal_client_check_one_alarm_only (ECalClient *client)
+static gboolean
+cal_client_retrieve_capabilities_sync (EClient *client,
+                                       gchar **capabilities,
+                                       GCancellable *cancellable,
+                                       GError **error)
 {
 	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
 
-	return e_client_check_capability (E_CLIENT (client), CAL_STATIC_CAPABILITY_ONE_ALARM_ONLY);
+	return e_client_get_backend_property_sync (client, CLIENT_BACKEND_PROPERTY_CAPABILITIES, capabilities, cancellable, error);
 }
 
-/**
- * e_cal_client_check_save_schedules:
- * @client: A calendar client.
- *
- * Checks whether the calendar saves schedules.
- *
- * Returns: TRUE if it saves schedules, FALSE otherwise.
- *
- * Since: 3.2
- **/
-gboolean
-e_cal_client_check_save_schedules (ECalClient *client)
+static void
+cal_client_get_backend_property (EClient *client,
+                                 const gchar *prop_name,
+                                 GCancellable *cancellable,
+                                 GAsyncReadyCallback callback,
+                                 gpointer user_data)
 {
-	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+	gchar *prop_value;
 
-	return e_client_check_capability (E_CLIENT (client), CAL_STATIC_CAPABILITY_SAVE_SCHEDULES);
+	prop_value = e_client_get_backend_property_from_cache (client, prop_name);
+	if (prop_value) {
+		e_client_finish_async_without_dbus (client, cancellable, callback, user_data, cal_client_get_backend_property_from_cache_finish, prop_value, g_free);
+	} else {
+		e_client_proxy_call_string_with_res_op_data (client, prop_name, cancellable, callback, user_data, cal_client_get_backend_property, prop_name,
+			e_gdbus_cal_call_get_backend_property,
+			NULL, NULL, e_gdbus_cal_call_get_backend_property_finish, NULL, NULL);
+	}
 }
 
-/**
- * e_cal_client_check_organizer_must_attend:
- * @client: A calendar client.
- *
- * Checks if a calendar forces organizers of meetings to be also attendees.
- *
- * Returns: TRUE if the calendar forces organizers to attend meetings,
- * FALSE otherwise.
- *
- * Since: 3.2
- **/
-gboolean
-e_cal_client_check_organizer_must_attend (ECalClient *client)
+static gboolean
+cal_client_get_backend_property_finish (EClient *client,
+                                        GAsyncResult *result,
+                                        gchar **prop_value,
+                                        GError **error)
 {
-	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+	gchar *str = NULL;
+	gboolean res;
 
-	return e_client_check_capability (E_CLIENT (client), CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ATTEND);
-}
+	g_return_val_if_fail (prop_value != NULL, FALSE);
 
-/**
- * e_cal_client_check_organizer_must_accept:
- * @client: A calendar client.
- *
- * Checks whether a calendar requires organizer to accept their attendance to
- * meetings.
- *
- * Returns: TRUE if the calendar requires organizers to accept, FALSE
- * otherwise.
- *
- * Since: 3.2
- **/
-gboolean
-e_cal_client_check_organizer_must_accept (ECalClient *client)
-{
-	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+	if (g_simple_async_result_get_source_tag (G_SIMPLE_ASYNC_RESULT (result)) == cal_client_get_backend_property_from_cache_finish) {
+		res = cal_client_get_backend_property_from_cache_finish (client, result, &str, error);
+	} else {
+		res = e_client_proxy_call_finish_string (client, result, &str, error, cal_client_get_backend_property);
+		if (res && str) {
+			const gchar *prop_name = g_object_get_data (G_OBJECT (result), "res-op-data");
 
-	return e_client_check_capability (E_CLIENT (client), CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ACCEPT);
-}
+			if (prop_name && *prop_name)
+				e_client_update_backend_property_cache (client, prop_name, str);
+		}
+	}
 
-/**
- * e_cal_client_check_recurrences_no_master:
- * @client: A calendar client.
- *
- * Checks if the calendar has a master object for recurrences.
- *
- * Returns: TRUE if the calendar has a master object for recurrences,
- * FALSE otherwise.
- *
- * Since: 3.2
- **/
-gboolean
-e_cal_client_check_recurrences_no_master (ECalClient *client)
-{
-	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+	*prop_value = str;
 
-	return e_client_check_capability (E_CLIENT (client), CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER);
+	return res;
 }
 
-/**
- * e_cal_client_free_icalcomp_slist:
- * @icalcomps: (element-type icalcomponent): list of icalcomponent objects
- *
- * Frees each element of the @icalcomps list and the list itself.
- * Each element is an object of type #icalcomponent.
- *
- * Since: 3.2
- **/
-void
-e_cal_client_free_icalcomp_slist (GSList *icalcomps)
+static gboolean
+cal_client_get_backend_property_sync (EClient *client,
+                                      const gchar *prop_name,
+                                      gchar **prop_value,
+                                      GCancellable *cancellable,
+                                      GError **error)
 {
-	g_slist_foreach (icalcomps, (GFunc) icalcomponent_free, NULL);
-	g_slist_free (icalcomps);
-}
+	ECalClient *cal_client;
+	gchar *prop_val;
+	gboolean res;
 
-/**
- * e_cal_client_free_ecalcomp_slist:
- * @ecalcomps: (element-type ECalComponent): list of #ECalComponent objects
- *
- * Frees each element of the @ecalcomps list and the list itself.
- * Each element is an object of type #ECalComponent.
- *
- * Since: 3.2
- **/
-void
-e_cal_client_free_ecalcomp_slist (GSList *ecalcomps)
-{
-	g_slist_foreach (ecalcomps, (GFunc) g_object_unref, NULL);
-	g_slist_free (ecalcomps);
-}
+	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
 
-/**
- * e_cal_client_resolve_tzid_cb:
- * @tzid: ID of the timezone to resolve.
- * @data: Closure data for the callback, in this case #ECalClient.
- *
- * Resolves TZIDs for the recurrence generator.
- *
- * Returns: The timezone identified by the @tzid argument, or %NULL if
- * it could not be found.
- *
- * Since: 3.2
- */
-icaltimezone *
-e_cal_client_resolve_tzid_cb (const gchar *tzid,
-                              gpointer data)
-{
-	ECalClient *client = data;
-	icaltimezone *zone = NULL;
-	GError *error = NULL;
+	cal_client = E_CAL_CLIENT (client);
 
-	g_return_val_if_fail (E_IS_CAL_CLIENT (client), NULL);
+	if (!cal_client->priv->gdbus_cal) {
+		set_proxy_gone_error (error);
+		return FALSE;
+	}
 
-	e_cal_client_get_timezone_sync (client, tzid, &zone, NULL, &error);
+	prop_val = e_client_get_backend_property_from_cache (client, prop_name);
+	if (prop_val) {
+		g_return_val_if_fail (prop_value != NULL, FALSE);
 
-	if (error) {
-		g_debug ("%s: Failed to find '%s' timezone: %s", G_STRFUNC, tzid, error->message);
-		g_error_free (error);
+		*prop_value = prop_val;
+
+		return TRUE;
 	}
 
-	return zone;
+	res = e_client_proxy_call_sync_string__string (client, prop_name, prop_value, cancellable, error, e_gdbus_cal_call_get_backend_property_sync);
+
+	if (res && prop_value)
+		e_client_update_backend_property_cache (client, prop_name, *prop_value);
+
+	return res;
 }
 
-struct comp_instance {
-	ECalComponent *comp;
-	time_t start;
-	time_t end;
-};
+static void
+cal_client_set_backend_property (EClient *client,
+                                 const gchar *prop_name,
+                                 const gchar *prop_value,
+                                 GCancellable *cancellable,
+                                 GAsyncReadyCallback callback,
+                                 gpointer user_data)
+{
+	gchar **prop_name_value;
 
-struct instances_info {
-	GSList **instances;
-	icaltimezone *start_zone;
-	icaltimezone *end_zone;
-};
+	prop_name_value = e_gdbus_cal_encode_set_backend_property (prop_name, prop_value);
+
+	e_client_proxy_call_strv (client, (const gchar * const *) prop_name_value, cancellable, callback, user_data, cal_client_set_backend_property,
+			e_gdbus_cal_call_set_backend_property,
+			e_gdbus_cal_call_set_backend_property_finish, NULL, NULL, NULL, NULL);
+
+	g_strfreev (prop_name_value);
+}
 
-/* Called from cal_recur_generate_instances(); adds an instance to the list */
 static gboolean
-add_instance (ECalComponent *comp,
-              time_t start,
-              time_t end,
-              gpointer data)
+cal_client_set_backend_property_finish (EClient *client,
+                                        GAsyncResult *result,
+                                        GError **error)
 {
-	GSList **list;
-	struct comp_instance *ci;
-	icalcomponent *icalcomp;
-	struct instances_info *instances_hold;
+	return e_client_proxy_call_finish_void (client, result, error, cal_client_set_backend_property);
+}
 
-	instances_hold = data;
-	list = instances_hold->instances;
+static gboolean
+cal_client_set_backend_property_sync (EClient *client,
+                                      const gchar *prop_name,
+                                      const gchar *prop_value,
+                                      GCancellable *cancellable,
+                                      GError **error)
+{
+	ECalClient *cal_client;
+	gboolean res;
+	gchar **prop_name_value;
 
-	ci = g_new (struct comp_instance, 1);
+	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
 
-	icalcomp = icalcomponent_new_clone (e_cal_component_get_icalcomponent (comp));
+	cal_client = E_CAL_CLIENT (client);
 
-	/* add the instance to the list */
+	if (!cal_client->priv->gdbus_cal) {
+		set_proxy_gone_error (error);
+		return FALSE;
+	}
+
+	prop_name_value = e_gdbus_cal_encode_set_backend_property (prop_name, prop_value);
+	res = e_client_proxy_call_sync_strv__void (client, (const gchar * const *) prop_name_value, cancellable, error, e_gdbus_cal_call_set_backend_property_sync);
+	g_strfreev (prop_name_value);
+
+	return res;
+}
+
+static void
+cal_client_open (EClient *client,
+                 gboolean only_if_exists,
+                 GCancellable *cancellable,
+                 GAsyncReadyCallback callback,
+                 gpointer user_data)
+{
+	e_client_proxy_call_boolean (client, only_if_exists, cancellable, callback, user_data, cal_client_open,
+			e_gdbus_cal_call_open,
+			e_gdbus_cal_call_open_finish, NULL, NULL, NULL, NULL);
+}
+
+static gboolean
+cal_client_open_finish (EClient *client,
+                        GAsyncResult *result,
+                        GError **error)
+{
+	return e_client_proxy_call_finish_void (client, result, error, cal_client_open);
+}
+
+static gboolean
+cal_client_open_sync (EClient *client,
+                      gboolean only_if_exists,
+                      GCancellable *cancellable,
+                      GError **error)
+{
+	ECalClient *cal_client;
+
+	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+
+	cal_client = E_CAL_CLIENT (client);
+
+	if (!cal_client->priv->gdbus_cal) {
+		set_proxy_gone_error (error);
+		return FALSE;
+	}
+
+	return e_client_proxy_call_sync_boolean__void (client, only_if_exists, cancellable, error, e_gdbus_cal_call_open_sync);
+}
+
+static void
+cal_client_refresh (EClient *client,
+                    GCancellable *cancellable,
+                    GAsyncReadyCallback callback,
+                    gpointer user_data)
+{
+	e_client_proxy_call_void (client, cancellable, callback, user_data, cal_client_refresh,
+			e_gdbus_cal_call_refresh,
+			e_gdbus_cal_call_refresh_finish, NULL, NULL, NULL, NULL);
+}
+
+static gboolean
+cal_client_refresh_finish (EClient *client,
+                           GAsyncResult *result,
+                           GError **error)
+{
+	return e_client_proxy_call_finish_void (client, result, error, cal_client_refresh);
+}
+
+static gboolean
+cal_client_refresh_sync (EClient *client,
+                         GCancellable *cancellable,
+                         GError **error)
+{
+	ECalClient *cal_client;
+
+	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+
+	cal_client = E_CAL_CLIENT (client);
+
+	if (!cal_client->priv->gdbus_cal) {
+		set_proxy_gone_error (error);
+		return FALSE;
+	}
+
+	return e_client_proxy_call_sync_void__void (client, cancellable, error, e_gdbus_cal_call_refresh_sync);
+}
+
+static void
+e_cal_client_class_init (ECalClientClass *class)
+{
+	GObjectClass *object_class;
+	EClientClass *client_class;
+
+	g_type_class_add_private (class, sizeof (ECalClientPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->dispose = cal_client_dispose;
+	object_class->finalize = cal_client_finalize;
+
+	client_class = E_CLIENT_CLASS (class);
+	client_class->get_dbus_proxy			= cal_client_get_dbus_proxy;
+	client_class->unwrap_dbus_error			= cal_client_unwrap_dbus_error;
+	client_class->retrieve_capabilities		= cal_client_retrieve_capabilities;
+	client_class->retrieve_capabilities_finish	= cal_client_retrieve_capabilities_finish;
+	client_class->retrieve_capabilities_sync	= cal_client_retrieve_capabilities_sync;
+	client_class->get_backend_property		= cal_client_get_backend_property;
+	client_class->get_backend_property_finish	= cal_client_get_backend_property_finish;
+	client_class->get_backend_property_sync		= cal_client_get_backend_property_sync;
+	client_class->set_backend_property		= cal_client_set_backend_property;
+	client_class->set_backend_property_finish	= cal_client_set_backend_property_finish;
+	client_class->set_backend_property_sync		= cal_client_set_backend_property_sync;
+	client_class->open				= cal_client_open;
+	client_class->open_finish			= cal_client_open_finish;
+	client_class->open_sync				= cal_client_open_sync;
+	client_class->refresh				= cal_client_refresh;
+	client_class->refresh_finish			= cal_client_refresh_finish;
+	client_class->refresh_sync			= cal_client_refresh_sync;
+
+	signals[FREE_BUSY_DATA] = g_signal_new (
+		"free-busy-data",
+		G_OBJECT_CLASS_TYPE (class),
+		G_SIGNAL_RUN_FIRST,
+		G_STRUCT_OFFSET (ECalClientClass, free_busy_data),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__POINTER,
+		G_TYPE_NONE, 1,
+		G_TYPE_POINTER);
+}
+
+static void
+e_cal_client_init (ECalClient *client)
+{
+	LOCK_FACTORY ();
+	active_cal_clients++;
+	UNLOCK_FACTORY ();
+
+	client->priv = E_CAL_CLIENT_GET_PRIVATE (client);
+	client->priv->source_type = E_CAL_CLIENT_SOURCE_TYPE_LAST;
+	client->priv->default_zone = icaltimezone_get_utc_timezone ();
+	client->priv->cache_dir = NULL;
+	client->priv->zone_cache_lock = g_mutex_new ();
+	client->priv->zone_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_zone_cb);
+}
+
+/**
+ * e_cal_client_new:
+ * @source: An #ESource pointer
+ * @source_type: source type of the calendar
+ * @error: A #GError pointer
+ *
+ * Creates a new #ECalClient corresponding to the given source.  There are
+ * only two operations that are valid on this calendar at this point:
+ * e_client_open(), and e_client_remove().
+ *
+ * Returns: a new but unopened #ECalClient.
+ *
+ * Since: 3.2
+ **/
+ECalClient *
+e_cal_client_new (ESource *source,
+                  ECalClientSourceType source_type,
+                  GError **error)
+{
+	ECalClient *client;
+	GError *err = NULL;
+	GDBusConnection *connection;
+	const gchar *uid;
+	gchar **strv;
+	gchar *object_path = NULL;
+
+	g_return_val_if_fail (E_IS_SOURCE (source), NULL);
+	g_return_val_if_fail (
+		source_type == E_CAL_CLIENT_SOURCE_TYPE_EVENTS ||
+		source_type == E_CAL_CLIENT_SOURCE_TYPE_TASKS ||
+		source_type == E_CAL_CLIENT_SOURCE_TYPE_MEMOS, NULL);
+
+	LOCK_FACTORY ();
+	/* XXX Oops, e_cal_client_new() forgot to take a GCancellable. */
+	if (!gdbus_cal_factory_activate (NULL, &err)) {
+		UNLOCK_FACTORY ();
+		if (err) {
+			unwrap_dbus_error (err, &err);
+			g_warning ("%s: Failed to run calendar factory: %s", G_STRFUNC, err->message);
+			g_propagate_error (error, err);
+		} else {
+			g_warning ("%s: Failed to run calendar factory: Unknown error", G_STRFUNC);
+			g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_DBUS_ERROR, _("Failed to run calendar factory"));
+		}
+
+		return NULL;
+	}
+
+	uid = e_source_get_uid (source);
+	strv = e_gdbus_cal_factory_encode_get_cal (uid, convert_type (source_type));
+	if (!strv) {
+		g_set_error_literal (error, E_CLIENT_ERROR, E_CLIENT_ERROR_OTHER_ERROR, _("Other error"));
+		return NULL;
+	}
+
+	client = g_object_new (E_TYPE_CAL_CLIENT, "source", source, NULL);
+	client->priv->source_type = source_type;
+
+	UNLOCK_FACTORY ();
+
+	e_gdbus_cal_factory_call_get_cal_sync (
+		G_DBUS_PROXY (cal_factory),
+		(const gchar * const *) strv,
+		&object_path, NULL, &err);
+
+	g_strfreev (strv);
+
+	/* Sanity check. */
+	g_return_val_if_fail (
+		((object_path != NULL) && (err == NULL)) ||
+		((object_path == NULL) && (err != NULL)), NULL);
+
+	if (err != NULL) {
+		unwrap_dbus_error (err, &err);
+		g_propagate_error (error, err);
+		g_object_unref (client);
+		return NULL;
+	}
+
+	connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (cal_factory));
+
+	client->priv->gdbus_cal = G_DBUS_PROXY (e_gdbus_cal_proxy_new_sync (
+		connection,
+		G_DBUS_PROXY_FLAGS_NONE,
+		CALENDAR_DBUS_SERVICE_NAME,
+		object_path,
+		NULL, &err));
+
+	g_free (object_path);
+
+	/* Sanity check. */
+	g_return_val_if_fail (
+		((object_path != NULL) && (err == NULL)) ||
+		((object_path == NULL) && (err != NULL)), NULL);
+
+	if (err != NULL) {
+		unwrap_dbus_error (err, &err);
+		g_propagate_error (error, err);
+		g_object_unref (client);
+		return NULL;
+	}
+
+	client->priv->gone_signal_id = g_dbus_connection_signal_subscribe (
+		connection,
+		"org.freedesktop.DBus",				/* sender */
+		"org.freedesktop.DBus",				/* interface */
+		"NameOwnerChanged",				/* member */
+		"/org/freedesktop/DBus",			/* object_path */
+		"org.gnome.evolution.dataserver.Calendar",	/* arg0 */
+		G_DBUS_SIGNAL_FLAGS_NONE,
+		gdbus_cal_client_connection_gone_cb, client, NULL);
+
+	g_signal_connect (
+		connection, "closed",
+		G_CALLBACK (gdbus_cal_client_closed_cb), client);
+
+	g_signal_connect (
+		client->priv->gdbus_cal, "backend_error",
+		G_CALLBACK (backend_error_cb), client);
+
+	g_signal_connect (
+		client->priv->gdbus_cal, "readonly",
+		G_CALLBACK (readonly_cb), client);
+
+	g_signal_connect (
+		client->priv->gdbus_cal, "online",
+		G_CALLBACK (online_cb), client);
+
+	g_signal_connect (
+		client->priv->gdbus_cal, "opened",
+		G_CALLBACK (opened_cb), client);
+
+	g_signal_connect (
+		client->priv->gdbus_cal, "free-busy-data",
+		G_CALLBACK (free_busy_data_cb), client);
+
+	g_signal_connect (
+		client->priv->gdbus_cal, "backend-property-changed",
+		G_CALLBACK (backend_property_changed_cb), client);
+
+	return client;
+}
+
+/**
+ * e_cal_client_get_source_type:
+ * @client: A calendar client.
+ *
+ * Gets the source type of the calendar client.
+ *
+ * Returns: an #ECalClientSourceType value corresponding
+ * to the source type of the calendar client.
+ *
+ * Since: 3.2
+ **/
+ECalClientSourceType
+e_cal_client_get_source_type (ECalClient *client)
+{
+	g_return_val_if_fail (E_IS_CAL_CLIENT (client), E_CAL_CLIENT_SOURCE_TYPE_LAST);
+
+	return client->priv->source_type;
+}
+
+/**
+ * e_cal_client_get_local_attachment_store:
+ * @client: A calendar client.
+ *
+ * Queries the URL where the calendar attachments are
+ * serialized in the local filesystem. This enable clients
+ * to operate with the reference to attachments rather than the data itself
+ * unless it specifically uses the attachments for open/sending
+ * operations.
+ *
+ * Returns: The URL where the attachments are serialized in the
+ * local filesystem.
+ *
+ * Since: 3.2
+ **/
+const gchar *
+e_cal_client_get_local_attachment_store (ECalClient *client)
+{
+	gchar *cache_dir = NULL;
+	GError *error = NULL;
+
+	g_return_val_if_fail (E_IS_CAL_CLIENT (client), NULL);
+
+	if (client->priv->cache_dir || !client->priv->gdbus_cal)
+		return client->priv->cache_dir;
+
+	cache_dir = e_client_get_backend_property_from_cache (E_CLIENT (client), CLIENT_BACKEND_PROPERTY_CACHE_DIR);
+	if (!cache_dir)
+		e_gdbus_cal_call_get_backend_property_sync (client->priv->gdbus_cal, CLIENT_BACKEND_PROPERTY_CACHE_DIR, &cache_dir, NULL, &error);
+
+	if (error == NULL) {
+		client->priv->cache_dir = cache_dir;
+	} else {
+		unwrap_dbus_error (error, &error);
+		g_warning ("%s", error->message);
+		g_error_free (error);
+	}
+
+	return client->priv->cache_dir;
+}
+
+/* icaltimezone_copy does a shallow copy while icaltimezone_free tries to free the entire 
+ * the contents inside the structure with libical 0.43. Use this, till eds allows older libical.
+*/
+static icaltimezone *
+copy_timezone (icaltimezone *ozone)
+{
+	icaltimezone *zone = NULL;
+	const gchar *tzid;
+
+	tzid = icaltimezone_get_tzid (ozone);
+
+	if (g_strcmp0 (tzid, "UTC") != 0) {
+		icalcomponent *comp;
+
+		comp = icaltimezone_get_component (ozone);
+		if (comp) {
+			zone = icaltimezone_new ();
+			icaltimezone_set_component (zone, icalcomponent_new_clone (comp));
+		}
+	}
+
+	if (!zone)
+		zone = icaltimezone_get_utc_timezone ();
+
+	return zone;
+}
+
+/**
+ * e_cal_client_set_default_timezone:
+ * @client: A calendar client.
+ * @zone: A timezone object.
+ *
+ * Sets the default timezone to use to resolve DATE and floating DATE-TIME
+ * values. This will typically be from the user's timezone setting. Call this
+ * before using any other object fetching functions.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_set_default_timezone (ECalClient *client, /* const */ icaltimezone *zone)
+{
+	g_return_if_fail (E_IS_CAL_CLIENT (client));
+	g_return_if_fail (zone != NULL);
+
+	if (client->priv->default_zone != icaltimezone_get_utc_timezone ())
+		icaltimezone_free (client->priv->default_zone, 1);
+
+	if (zone == icaltimezone_get_utc_timezone ())
+		client->priv->default_zone = zone;
+	else
+		client->priv->default_zone = copy_timezone (zone);
+}
+
+/**
+ * e_cal_client_get_default_timezone:
+ * @client: A calendar client.
+ *
+ * Returns: Default timezone previously set with e_cal_client_set_default_timezone().
+ * Returned pointer is owned by the @client and should not be freed.
+ *
+ * Since: 3.2
+ **/
+/* const */ icaltimezone *
+e_cal_client_get_default_timezone (ECalClient *client)
+{
+	g_return_val_if_fail (E_IS_CAL_CLIENT (client), NULL);
+
+	return client->priv->default_zone;
+}
+
+/**
+ * e_cal_client_check_one_alarm_only:
+ * @client: A calendar client.
+ *
+ * Checks if a calendar supports only one alarm per component.
+ *
+ * Returns: TRUE if the calendar allows only one alarm, FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_check_one_alarm_only (ECalClient *client)
+{
+	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+
+	return e_client_check_capability (E_CLIENT (client), CAL_STATIC_CAPABILITY_ONE_ALARM_ONLY);
+}
+
+/**
+ * e_cal_client_check_save_schedules:
+ * @client: A calendar client.
+ *
+ * Checks whether the calendar saves schedules.
+ *
+ * Returns: TRUE if it saves schedules, FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_check_save_schedules (ECalClient *client)
+{
+	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+
+	return e_client_check_capability (E_CLIENT (client), CAL_STATIC_CAPABILITY_SAVE_SCHEDULES);
+}
+
+/**
+ * e_cal_client_check_organizer_must_attend:
+ * @client: A calendar client.
+ *
+ * Checks if a calendar forces organizers of meetings to be also attendees.
+ *
+ * Returns: TRUE if the calendar forces organizers to attend meetings,
+ * FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_check_organizer_must_attend (ECalClient *client)
+{
+	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+
+	return e_client_check_capability (E_CLIENT (client), CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ATTEND);
+}
+
+/**
+ * e_cal_client_check_organizer_must_accept:
+ * @client: A calendar client.
+ *
+ * Checks whether a calendar requires organizer to accept their attendance to
+ * meetings.
+ *
+ * Returns: TRUE if the calendar requires organizers to accept, FALSE
+ * otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_check_organizer_must_accept (ECalClient *client)
+{
+	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+
+	return e_client_check_capability (E_CLIENT (client), CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ACCEPT);
+}
+
+/**
+ * e_cal_client_check_recurrences_no_master:
+ * @client: A calendar client.
+ *
+ * Checks if the calendar has a master object for recurrences.
+ *
+ * Returns: TRUE if the calendar has a master object for recurrences,
+ * FALSE otherwise.
+ *
+ * Since: 3.2
+ **/
+gboolean
+e_cal_client_check_recurrences_no_master (ECalClient *client)
+{
+	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+
+	return e_client_check_capability (E_CLIENT (client), CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER);
+}
+
+/**
+ * e_cal_client_free_icalcomp_slist:
+ * @icalcomps: (element-type icalcomponent): list of icalcomponent objects
+ *
+ * Frees each element of the @icalcomps list and the list itself.
+ * Each element is an object of type #icalcomponent.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_free_icalcomp_slist (GSList *icalcomps)
+{
+	g_slist_foreach (icalcomps, (GFunc) icalcomponent_free, NULL);
+	g_slist_free (icalcomps);
+}
+
+/**
+ * e_cal_client_free_ecalcomp_slist:
+ * @ecalcomps: (element-type ECalComponent): list of #ECalComponent objects
+ *
+ * Frees each element of the @ecalcomps list and the list itself.
+ * Each element is an object of type #ECalComponent.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_free_ecalcomp_slist (GSList *ecalcomps)
+{
+	g_slist_foreach (ecalcomps, (GFunc) g_object_unref, NULL);
+	g_slist_free (ecalcomps);
+}
+
+/**
+ * e_cal_client_resolve_tzid_cb:
+ * @tzid: ID of the timezone to resolve.
+ * @data: Closure data for the callback, in this case #ECalClient.
+ *
+ * Resolves TZIDs for the recurrence generator.
+ *
+ * Returns: The timezone identified by the @tzid argument, or %NULL if
+ * it could not be found.
+ *
+ * Since: 3.2
+ */
+icaltimezone *
+e_cal_client_resolve_tzid_cb (const gchar *tzid,
+                              gpointer data)
+{
+	ECalClient *client = data;
+	icaltimezone *zone = NULL;
+	GError *error = NULL;
+
+	g_return_val_if_fail (E_IS_CAL_CLIENT (client), NULL);
+
+	e_cal_client_get_timezone_sync (client, tzid, &zone, NULL, &error);
+
+	if (error) {
+		g_debug ("%s: Failed to find '%s' timezone: %s", G_STRFUNC, tzid, error->message);
+		g_error_free (error);
+	}
+
+	return zone;
+}
+
+struct comp_instance {
+	ECalComponent *comp;
+	time_t start;
+	time_t end;
+};
+
+struct instances_info {
+	GSList **instances;
+	icaltimezone *start_zone;
+	icaltimezone *end_zone;
+};
+
+/* Called from cal_recur_generate_instances(); adds an instance to the list */
+static gboolean
+add_instance (ECalComponent *comp,
+              time_t start,
+              time_t end,
+              gpointer data)
+{
+	GSList **list;
+	struct comp_instance *ci;
+	icalcomponent *icalcomp;
+	struct instances_info *instances_hold;
+
+	instances_hold = data;
+	list = instances_hold->instances;
+
+	ci = g_new (struct comp_instance, 1);
+
+	icalcomp = icalcomponent_new_clone (e_cal_component_get_icalcomponent (comp));
+
+	/* add the instance to the list */
 	ci->comp = e_cal_component_new ();
 	e_cal_component_set_icalcomponent (ci->comp, icalcomp);
 
@@ -1586,200 +2027,28 @@ get_objects_async (void (*ready_cb) (struct get_objects_async_data *goad,
 		goad->query = g_strdup_printf ("(occur-in-time-range? (make-time \"%s\") (make-time \"%s\"))", iso_start, iso_end);
 
 		g_free (iso_start);
-		g_free (iso_end);
-
-		e_cal_client_get_object_list_as_comps (goad->client, goad->query, goad->cancellable, got_object_list_as_comps_cb, goad);
-	}
-}
-
-static void
-generate_instances_got_objects_cb (struct get_objects_async_data *goad,
-                                   GSList *objects)
-{
-	g_return_if_fail (goad != NULL);
-
-	/* generate_instaces () frees 'objects' slist */
-	if (objects)
-		generate_instances (goad->client, goad->start, goad->end, objects, goad->cancellable, goad->cb, goad->cb_data);
-
-	free_get_objects_async_data (goad);
-}
-
-/**
- * e_cal_client_generate_instances:
- * @client: A calendar client.
- * @start: Start time for query.
- * @end: End time for query.
- * @cancellable: a #GCancellable; can be %NULL
- * @cb: Callback for each generated instance.
- * @cb_data: Closure data for the callback.
- * @destroy_cb_data: Function to call when the processing is done, to free @cb_data; can be %NULL.
- *
- * Does a combination of #e_cal_client_get_object_list () and
- * #e_cal_client_recur_generate_instances(). Unlike #e_cal_client_generate_instances_sync (),
- * this returns immediately and the @cb callback is called asynchronously.
- *
- * The callback function should do a g_object_ref() of the calendar component
- * it gets passed if it intends to keep it around, since it will be unref'ed
- * as soon as the callback returns.
- *
- * Since: 3.2
- **/
-void
-e_cal_client_generate_instances (ECalClient *client,
-                                 time_t start,
-                                 time_t end,
-                                 GCancellable *cancellable,
-                                 ECalRecurInstanceFn cb,
-                                 gpointer cb_data,
-                                 GDestroyNotify destroy_cb_data)
-{
-	struct get_objects_async_data *goad;
-	GCancellable *use_cancellable;
-
-	g_return_if_fail (E_IS_CAL_CLIENT (client));
-	g_return_if_fail (e_client_is_opened (E_CLIENT (client)));
-
-	g_return_if_fail (start >= 0);
-	g_return_if_fail (end >= 0);
-	g_return_if_fail (cb != NULL);
-
-	use_cancellable = cancellable;
-	if (!use_cancellable)
-		use_cancellable = g_cancellable_new ();
-
-	goad = g_new0 (struct get_objects_async_data, 1);
-	goad->cancellable = g_object_ref (use_cancellable);
-	goad->client = g_object_ref (client);
-	goad->start = start;
-	goad->end = end;
-	goad->cb = cb;
-	goad->cb_data = cb_data;
-	goad->destroy_cb_data = destroy_cb_data;
-
-	get_objects_async (generate_instances_got_objects_cb, goad);
-
-	if (use_cancellable != cancellable)
-		g_object_unref (use_cancellable);
-}
-
-/**
- * e_cal_client_generate_instances_sync:
- * @client: A calendar client
- * @start: Start time for query
- * @end: End time for query
- * @cb: (closure cb_data) (scope call): Callback for each generated instance
- * @cb_data: (closure): Closure data for the callback
- *
- * Does a combination of e_cal_client_get_object_list() and
- * e_cal_client_recur_generate_instances().
- *
- * The callback function should do a g_object_ref() of the calendar component
- * it gets passed if it intends to keep it around, since it will be unreffed
- * as soon as the callback returns.
- *
- * Since: 3.2
- **/
-void
-e_cal_client_generate_instances_sync (ECalClient *client,
-                                      time_t start,
-                                      time_t end,
-                                      ECalRecurInstanceFn cb,
-                                      gpointer cb_data)
-{
-	GSList *objects = NULL;
-
-	g_return_if_fail (E_IS_CAL_CLIENT (client));
-	g_return_if_fail (e_client_is_opened (E_CLIENT (client)));
-
-	g_return_if_fail (start >= 0);
-	g_return_if_fail (end >= 0);
-	g_return_if_fail (cb != NULL);
-
-	objects = get_objects_sync (client, start, end, NULL);
-	if (!objects)
-		return;
-
-	/* generate_instaces frees 'objects' slist */
-	generate_instances (client, start, end, objects, NULL, cb, cb_data);
-}
-
-/* also frees 'instances' GSList */
-static void
-process_instances (ECalComponent *comp,
-                   GSList *instances,
-                   ECalRecurInstanceFn cb,
-                   gpointer cb_data)
-{
-	gchar *rid;
-	gboolean result;
-
-	g_return_if_fail (comp != NULL);
-	g_return_if_fail (cb != NULL);
-
-	rid = e_cal_component_get_recurid_as_string (comp);
-
-	/* Reverse the instances list because the add_instance() function is prepending */
-	instances = g_slist_reverse (instances);
-
-	/* now only return back the instances for the given object */
-	result = TRUE;
-	while (instances != NULL) {
-		struct comp_instance *ci;
-		gchar *instance_rid = NULL;
-
-		ci = instances->data;
-
-		if (result) {
-			instance_rid = e_cal_component_get_recurid_as_string (ci->comp);
-
-			if (rid && *rid) {
-				if (instance_rid && *instance_rid && strcmp (rid, instance_rid) == 0)
-					result = (* cb) (ci->comp, ci->start, ci->end, cb_data);
-			} else
-				result = (* cb)  (ci->comp, ci->start, ci->end, cb_data);
-		}
-
-		/* remove instance from list */
-		instances = g_slist_remove (instances, ci);
-		g_object_unref (ci->comp);
-		g_free (ci);
-		g_free (instance_rid);
-	}
+		g_free (iso_end);
 
-	/* clean up */
-	g_free (rid);
+		e_cal_client_get_object_list_as_comps (goad->client, goad->query, goad->cancellable, got_object_list_as_comps_cb, goad);
+	}
 }
 
 static void
-generate_instances_for_object_got_objects_cb (struct get_objects_async_data *goad,
-                                              GSList *objects)
+generate_instances_got_objects_cb (struct get_objects_async_data *goad,
+                                   GSList *objects)
 {
-	struct instances_info *instances_hold;
-	GSList *instances = NULL;
-
 	g_return_if_fail (goad != NULL);
 
-	instances_hold = g_new0 (struct instances_info, 1);
-	instances_hold->instances = &instances;
-	instances_hold->start_zone = goad->start_zone;
-	instances_hold->end_zone = goad->end_zone;
-
-	/* generate all instances in the given time range */
-	generate_instances (goad->client, goad->start, goad->end, objects, goad->cancellable, add_instance, instances_hold);
-
-	/* it also frees 'instances' GSList */
-	process_instances (goad->comp, *(instances_hold->instances), goad->cb, goad->cb_data);
+	/* generate_instaces () frees 'objects' slist */
+	if (objects)
+		generate_instances (goad->client, goad->start, goad->end, objects, goad->cancellable, goad->cb, goad->cb_data);
 
-	/* clean up */
 	free_get_objects_async_data (goad);
-	g_free (instances_hold);
 }
 
 /**
- * e_cal_client_generate_instances_for_object:
+ * e_cal_client_generate_instances:
  * @client: A calendar client.
- * @icalcomp: Object to generate instances from.
  * @start: Start time for query.
  * @end: End time for query.
  * @cancellable: a #GCancellable; can be %NULL
@@ -1788,8 +2057,7 @@ generate_instances_for_object_got_objects_cb (struct get_objects_async_data *goa
  * @destroy_cb_data: Function to call when the processing is done, to free @cb_data; can be %NULL.
  *
  * Does a combination of #e_cal_client_get_object_list () and
- * #e_cal_client_recur_generate_instances(), like #e_cal_client_generate_instances(), but
- * for a single object. Unlike #e_cal_client_generate_instances_for_object_sync (),
+ * #e_cal_client_recur_generate_instances(). Unlike #e_cal_client_generate_instances_sync (),
  * this returns immediately and the @cb callback is called asynchronously.
  *
  * The callback function should do a g_object_ref() of the calendar component
@@ -1799,20 +2067,14 @@ generate_instances_for_object_got_objects_cb (struct get_objects_async_data *goa
  * Since: 3.2
  **/
 void
-e_cal_client_generate_instances_for_object (ECalClient *client,
-                                            icalcomponent *icalcomp,
-                                            time_t start,
-                                            time_t end,
-                                            GCancellable *cancellable,
-                                            ECalRecurInstanceFn cb,
-                                            gpointer cb_data,
-                                            GDestroyNotify destroy_cb_data)
+e_cal_client_generate_instances (ECalClient *client,
+                                 time_t start,
+                                 time_t end,
+                                 GCancellable *cancellable,
+                                 ECalRecurInstanceFn cb,
+                                 gpointer cb_data,
+                                 GDestroyNotify destroy_cb_data)
 {
-	ECalComponent *comp;
-	const gchar *uid;
-	ECalComponentDateTime datetime;
-	icaltimezone *start_zone = NULL, *end_zone = NULL;
-	gboolean is_single_instance = FALSE;
 	struct get_objects_async_data *goad;
 	GCancellable *use_cancellable;
 
@@ -1823,529 +2085,466 @@ e_cal_client_generate_instances_for_object (ECalClient *client,
 	g_return_if_fail (end >= 0);
 	g_return_if_fail (cb != NULL);
 
-	comp = e_cal_component_new ();
-	e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (icalcomp));
-
-	if (!e_cal_component_has_recurrences (comp))
-		is_single_instance = TRUE;
-
-	/* If the backend stores it as individual instances and does not
-	 * have a master object - do not expand */
-	if (is_single_instance || e_client_check_capability (E_CLIENT (client), CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER)) {
-		/* return the same instance */
-		(* cb)  (comp, icaltime_as_timet_with_zone (icalcomponent_get_dtstart (icalcomp), client->priv->default_zone),
-				icaltime_as_timet_with_zone (icalcomponent_get_dtend (icalcomp), client->priv->default_zone), cb_data);
-		g_object_unref (comp);
-
-		if (destroy_cb_data)
-			destroy_cb_data (cb_data);
-		return;
-	}
-
-	e_cal_component_get_uid (comp, &uid);
-
-	/* Get the start timezone */
-	e_cal_component_get_dtstart (comp, &datetime);
-	if (datetime.tzid)
-		e_cal_client_get_timezone_sync (client, datetime.tzid, &start_zone, NULL, NULL);
-	else
-		start_zone = NULL;
-	e_cal_component_free_datetime (&datetime);
-
-	/* Get the end timezone */
-	e_cal_component_get_dtend (comp, &datetime);
-	if (datetime.tzid)
-		e_cal_client_get_timezone_sync (client, datetime.tzid, &end_zone, NULL, NULL);
-	else
-		end_zone = NULL;
-	e_cal_component_free_datetime (&datetime);
-
-	use_cancellable = cancellable;
-	if (!use_cancellable)
-		use_cancellable = g_cancellable_new ();
-
-	goad = g_new0 (struct get_objects_async_data, 1);
-	goad->cancellable = g_object_ref (use_cancellable);
-	goad->client = g_object_ref (client);
-	goad->start = start;
-	goad->end = end;
-	goad->cb = cb;
-	goad->cb_data = cb_data;
-	goad->destroy_cb_data = destroy_cb_data;
-	goad->start_zone = start_zone;
-	goad->end_zone = end_zone;
-	goad->comp = comp;
-	goad->uid = g_strdup (uid);
-
-	get_objects_async (generate_instances_for_object_got_objects_cb, goad);
-
-	if (use_cancellable != cancellable)
-		g_object_unref (use_cancellable);
-}
-
-/**
- * e_cal_client_generate_instances_for_object_sync:
- * @client: A calendar client
- * @icalcomp: Object to generate instances from
- * @start: Start time for query
- * @end: End time for query
- * @cb: (closure cb_data) (scope call): Callback for each generated instance
- * @cb_data: (closure): Closure data for the callback
- *
- * Does a combination of #e_cal_client_get_object_list () and
- * #e_cal_client_recur_generate_instances(), like #e_cal_client_generate_instances_sync(), but
- * for a single object.
- *
- * The callback function should do a g_object_ref() of the calendar component
- * it gets passed if it intends to keep it around, since it will be unref'ed
- * as soon as the callback returns.
- *
- * Since: 3.2
- **/
-void
-e_cal_client_generate_instances_for_object_sync (ECalClient *client,
-                                                 icalcomponent *icalcomp,
-                                                 time_t start,
-                                                 time_t end,
-                                                 ECalRecurInstanceFn cb,
-                                                 gpointer cb_data)
-{
-	ECalComponent *comp;
-	const gchar *uid;
-	GSList *instances = NULL;
-	ECalComponentDateTime datetime;
-	icaltimezone *start_zone = NULL, *end_zone = NULL;
-	struct instances_info *instances_hold;
-	gboolean is_single_instance = FALSE;
-
-	g_return_if_fail (E_IS_CAL_CLIENT (client));
-	g_return_if_fail (e_client_is_opened (E_CLIENT (client)));
-
-	g_return_if_fail (start >= 0);
-	g_return_if_fail (end >= 0);
-	g_return_if_fail (cb != NULL);
-
-	comp = e_cal_component_new ();
-	e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (icalcomp));
-
-	if (!e_cal_component_has_recurrences (comp))
-		is_single_instance = TRUE;
-
-	/* If the backend stores it as individual instances and does not
-	 * have a master object - do not expand */
-	if (is_single_instance || e_client_check_capability (E_CLIENT (client), CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER)) {
-		/* return the same instance */
-		(* cb)  (comp, icaltime_as_timet_with_zone (icalcomponent_get_dtstart (icalcomp), client->priv->default_zone),
-				icaltime_as_timet_with_zone (icalcomponent_get_dtend (icalcomp), client->priv->default_zone), cb_data);
-		g_object_unref (comp);
-		return;
-	}
-
-	e_cal_component_get_uid (comp, &uid);
-
-	/* Get the start timezone */
-	e_cal_component_get_dtstart (comp, &datetime);
-	if (datetime.tzid)
-		e_cal_client_get_timezone_sync (client, datetime.tzid, &start_zone, NULL, NULL);
-	else
-		start_zone = NULL;
-	e_cal_component_free_datetime (&datetime);
-
-	/* Get the end timezone */
-	e_cal_component_get_dtend (comp, &datetime);
-	if (datetime.tzid)
-		e_cal_client_get_timezone_sync (client, datetime.tzid, &end_zone, NULL, NULL);
-	else
-		end_zone = NULL;
-	e_cal_component_free_datetime (&datetime);
-
-	instances_hold = g_new0 (struct instances_info, 1);
-	instances_hold->instances = &instances;
-	instances_hold->start_zone = start_zone;
-	instances_hold->end_zone = end_zone;
-
-	/* generate all instances in the given time range */
-	generate_instances (client, start, end, get_objects_sync (client, start, end, uid), NULL, add_instance, instances_hold);
-
-	/* it also frees 'instances' GSList */
-	process_instances (comp, *(instances_hold->instances), cb, cb_data);
-
-	/* clean up */
-	g_object_unref (comp);
-	g_free (instances_hold);
-}
-
-typedef struct _ForeachTZIDCallbackData ForeachTZIDCallbackData;
-struct _ForeachTZIDCallbackData {
-	ECalClient *client;
-	GHashTable *timezone_hash;
-	gboolean success;
-};
-
-/* This adds the VTIMEZONE given by the TZID parameter to the GHashTable in
- * data. */
-static void
-foreach_tzid_callback (icalparameter *param,
-                       gpointer cbdata)
-{
-	ForeachTZIDCallbackData *data = cbdata;
-	const gchar *tzid;
-	icaltimezone *zone = NULL;
-	icalcomponent *vtimezone_comp;
-	gchar *vtimezone_as_string;
-
-	/* Get the TZID string from the parameter. */
-	tzid = icalparameter_get_tzid (param);
-	if (!tzid)
-		return;
-
-	/* Check if we've already added it to the GHashTable. */
-	if (g_hash_table_lookup (data->timezone_hash, tzid))
-		return;
-
-	if (!e_cal_client_get_timezone_sync (data->client, tzid, &zone, NULL, NULL) || !zone) {
-		data->success = FALSE;
-		return;
-	}
-
-	/* Convert it to a string and add it to the hash. */
-	vtimezone_comp = icaltimezone_get_component (zone);
-	if (!vtimezone_comp)
-		return;
-
-	vtimezone_as_string = icalcomponent_as_ical_string_r (vtimezone_comp);
-
-	g_hash_table_insert (data->timezone_hash, (gchar *) tzid, vtimezone_as_string);
-}
-
-/* This appends the value string to the GString given in data. */
-static void
-append_timezone_string (gpointer key,
-                        gpointer value,
-                        gpointer data)
-{
-	GString *vcal_string = data;
-
-	g_string_append (vcal_string, value);
-	g_free (value);
-}
+	use_cancellable = cancellable;
+	if (!use_cancellable)
+		use_cancellable = g_cancellable_new ();
 
-/* This simply frees the hash values. */
-static void
-free_timezone_string (gpointer key,
-                      gpointer value,
-                      gpointer data)
-{
-	g_free (value);
+	goad = g_new0 (struct get_objects_async_data, 1);
+	goad->cancellable = g_object_ref (use_cancellable);
+	goad->client = g_object_ref (client);
+	goad->start = start;
+	goad->end = end;
+	goad->cb = cb;
+	goad->cb_data = cb_data;
+	goad->destroy_cb_data = destroy_cb_data;
+
+	get_objects_async (generate_instances_got_objects_cb, goad);
+
+	if (use_cancellable != cancellable)
+		g_object_unref (use_cancellable);
 }
 
 /**
- * e_cal_client_get_component_as_string:
- * @client: A calendar client.
- * @icalcomp: A calendar component object.
+ * e_cal_client_generate_instances_sync:
+ * @client: A calendar client
+ * @start: Start time for query
+ * @end: End time for query
+ * @cb: (closure cb_data) (scope call): Callback for each generated instance
+ * @cb_data: (closure): Closure data for the callback
  *
- * Gets a calendar component as an iCalendar string, with a toplevel
- * VCALENDAR component and all VTIMEZONEs needed for the component.
+ * Does a combination of e_cal_client_get_object_list() and
+ * e_cal_client_recur_generate_instances().
  *
- * Returns: the component as a complete iCalendar string, or NULL on
- * failure. The string should be freed with g_free().
+ * The callback function should do a g_object_ref() of the calendar component
+ * it gets passed if it intends to keep it around, since it will be unreffed
+ * as soon as the callback returns.
  *
  * Since: 3.2
  **/
-gchar *
-e_cal_client_get_component_as_string (ECalClient *client,
-                                      icalcomponent *icalcomp)
+void
+e_cal_client_generate_instances_sync (ECalClient *client,
+                                      time_t start,
+                                      time_t end,
+                                      ECalRecurInstanceFn cb,
+                                      gpointer cb_data)
 {
-	GHashTable *timezone_hash;
-	GString *vcal_string;
-	ForeachTZIDCallbackData cbdata;
-	gchar *obj_string;
-
-	g_return_val_if_fail (E_IS_CAL_CLIENT (client), NULL);
-	g_return_val_if_fail (icalcomp != NULL, NULL);
+	GSList *objects = NULL;
 
-	timezone_hash = g_hash_table_new (g_str_hash, g_str_equal);
+	g_return_if_fail (E_IS_CAL_CLIENT (client));
+	g_return_if_fail (e_client_is_opened (E_CLIENT (client)));
 
-	/* Add any timezones needed to the hash. We use a hash since we only
-	 * want to add each timezone once at most. */
-	cbdata.client = client;
-	cbdata.timezone_hash = timezone_hash;
-	cbdata.success = TRUE;
-	icalcomponent_foreach_tzid (icalcomp, foreach_tzid_callback, &cbdata);
-	if (!cbdata.success) {
-		g_hash_table_foreach (timezone_hash, free_timezone_string, NULL);
-		return NULL;
-	}
+	g_return_if_fail (start >= 0);
+	g_return_if_fail (end >= 0);
+	g_return_if_fail (cb != NULL);
 
-	/* Create the start of a VCALENDAR, to add the VTIMEZONES to,
-	 * and remember its length so we know if any VTIMEZONEs get added. */
-	vcal_string = g_string_new (NULL);
-	g_string_append (vcal_string,
-			 "BEGIN:VCALENDAR\n"
-			 "PRODID:-//Ximian//NONSGML Evolution Calendar//EN\n"
-			 "VERSION:2.0\n"
-			 "METHOD:PUBLISH\n");
+	objects = get_objects_sync (client, start, end, NULL);
+	if (!objects)
+		return;
 
-	/* Now concatenate all the timezone strings. This also frees the
-	 * timezone strings as it goes. */
-	g_hash_table_foreach (timezone_hash, append_timezone_string, vcal_string);
+	/* generate_instaces frees 'objects' slist */
+	generate_instances (client, start, end, objects, NULL, cb, cb_data);
+}
 
-	/* Get the string for the VEVENT/VTODO. */
-	obj_string = icalcomponent_as_ical_string_r (icalcomp);
+/* also frees 'instances' GSList */
+static void
+process_instances (ECalComponent *comp,
+                   GSList *instances,
+                   ECalRecurInstanceFn cb,
+                   gpointer cb_data)
+{
+	gchar *rid;
+	gboolean result;
 
-	/* If there were any timezones to send, create a complete VCALENDAR,
-	 * else just send the VEVENT/VTODO string. */
-	g_string_append (vcal_string, obj_string);
-	g_string_append (vcal_string, "END:VCALENDAR\n");
-	g_free (obj_string);
+	g_return_if_fail (comp != NULL);
+	g_return_if_fail (cb != NULL);
 
-	obj_string = g_string_free (vcal_string, FALSE);
+	rid = e_cal_component_get_recurid_as_string (comp);
 
-	g_hash_table_destroy (timezone_hash);
+	/* Reverse the instances list because the add_instance() function is prepending */
+	instances = g_slist_reverse (instances);
 
-	return obj_string;
-}
+	/* now only return back the instances for the given object */
+	result = TRUE;
+	while (instances != NULL) {
+		struct comp_instance *ci;
+		gchar *instance_rid = NULL;
 
-static gboolean
-cal_client_get_backend_property_from_cache_finish (EClient *client,
-                                                   GAsyncResult *result,
-                                                   gchar **prop_value,
-                                                   GError **error)
-{
-	GSimpleAsyncResult *simple;
-	GError *local_error = NULL;
+		ci = instances->data;
 
-	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
-	g_return_val_if_fail (result != NULL, FALSE);
-	g_return_val_if_fail (prop_value != NULL, FALSE);
-	g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (client), cal_client_get_backend_property_from_cache_finish), FALSE);
+		if (result) {
+			instance_rid = e_cal_component_get_recurid_as_string (ci->comp);
 
-	simple = G_SIMPLE_ASYNC_RESULT (result);
+			if (rid && *rid) {
+				if (instance_rid && *instance_rid && strcmp (rid, instance_rid) == 0)
+					result = (* cb) (ci->comp, ci->start, ci->end, cb_data);
+			} else
+				result = (* cb)  (ci->comp, ci->start, ci->end, cb_data);
+		}
 
-	if (g_simple_async_result_propagate_error (simple, &local_error)) {
-		e_client_unwrap_dbus_error (client, local_error, error);
-		return FALSE;
+		/* remove instance from list */
+		instances = g_slist_remove (instances, ci);
+		g_object_unref (ci->comp);
+		g_free (ci);
+		g_free (instance_rid);
 	}
 
-	*prop_value = g_strdup (g_simple_async_result_get_op_res_gpointer (simple));
-
-	return *prop_value != NULL;
+	/* clean up */
+	g_free (rid);
 }
 
 static void
-cal_client_get_backend_property (EClient *client,
-                                 const gchar *prop_name,
-                                 GCancellable *cancellable,
-                                 GAsyncReadyCallback callback,
-                                 gpointer user_data)
-{
-	gchar *prop_value;
-
-	prop_value = e_client_get_backend_property_from_cache (client, prop_name);
-	if (prop_value) {
-		e_client_finish_async_without_dbus (client, cancellable, callback, user_data, cal_client_get_backend_property_from_cache_finish, prop_value, g_free);
-	} else {
-		e_client_proxy_call_string_with_res_op_data (client, prop_name, cancellable, callback, user_data, cal_client_get_backend_property, prop_name,
-			e_gdbus_cal_call_get_backend_property,
-			NULL, NULL, e_gdbus_cal_call_get_backend_property_finish, NULL, NULL);
-	}
-}
-
-static gboolean
-cal_client_get_backend_property_finish (EClient *client,
-                                        GAsyncResult *result,
-                                        gchar **prop_value,
-                                        GError **error)
+generate_instances_for_object_got_objects_cb (struct get_objects_async_data *goad,
+                                              GSList *objects)
 {
-	gchar *str = NULL;
-	gboolean res;
+	struct instances_info *instances_hold;
+	GSList *instances = NULL;
 
-	g_return_val_if_fail (prop_value != NULL, FALSE);
+	g_return_if_fail (goad != NULL);
 
-	if (g_simple_async_result_get_source_tag (G_SIMPLE_ASYNC_RESULT (result)) == cal_client_get_backend_property_from_cache_finish) {
-		res = cal_client_get_backend_property_from_cache_finish (client, result, &str, error);
-	} else {
-		res = e_client_proxy_call_finish_string (client, result, &str, error, cal_client_get_backend_property);
-		if (res && str) {
-			const gchar *prop_name = g_object_get_data (G_OBJECT (result), "res-op-data");
+	instances_hold = g_new0 (struct instances_info, 1);
+	instances_hold->instances = &instances;
+	instances_hold->start_zone = goad->start_zone;
+	instances_hold->end_zone = goad->end_zone;
 
-			if (prop_name && *prop_name)
-				e_client_update_backend_property_cache (client, prop_name, str);
-		}
-	}
+	/* generate all instances in the given time range */
+	generate_instances (goad->client, goad->start, goad->end, objects, goad->cancellable, add_instance, instances_hold);
 
-	*prop_value = str;
+	/* it also frees 'instances' GSList */
+	process_instances (goad->comp, *(instances_hold->instances), goad->cb, goad->cb_data);
 
-	return res;
+	/* clean up */
+	free_get_objects_async_data (goad);
+	g_free (instances_hold);
 }
 
-static gboolean
-cal_client_get_backend_property_sync (EClient *client,
-                                      const gchar *prop_name,
-                                      gchar **prop_value,
-                                      GCancellable *cancellable,
-                                      GError **error)
+/**
+ * e_cal_client_generate_instances_for_object:
+ * @client: A calendar client.
+ * @icalcomp: Object to generate instances from.
+ * @start: Start time for query.
+ * @end: End time for query.
+ * @cancellable: a #GCancellable; can be %NULL
+ * @cb: Callback for each generated instance.
+ * @cb_data: Closure data for the callback.
+ * @destroy_cb_data: Function to call when the processing is done, to free @cb_data; can be %NULL.
+ *
+ * Does a combination of #e_cal_client_get_object_list () and
+ * #e_cal_client_recur_generate_instances(), like #e_cal_client_generate_instances(), but
+ * for a single object. Unlike #e_cal_client_generate_instances_for_object_sync (),
+ * this returns immediately and the @cb callback is called asynchronously.
+ *
+ * The callback function should do a g_object_ref() of the calendar component
+ * it gets passed if it intends to keep it around, since it will be unref'ed
+ * as soon as the callback returns.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_generate_instances_for_object (ECalClient *client,
+                                            icalcomponent *icalcomp,
+                                            time_t start,
+                                            time_t end,
+                                            GCancellable *cancellable,
+                                            ECalRecurInstanceFn cb,
+                                            gpointer cb_data,
+                                            GDestroyNotify destroy_cb_data)
 {
-	ECalClient *cal_client;
-	gchar *prop_val;
-	gboolean res;
+	ECalComponent *comp;
+	const gchar *uid;
+	ECalComponentDateTime datetime;
+	icaltimezone *start_zone = NULL, *end_zone = NULL;
+	gboolean is_single_instance = FALSE;
+	struct get_objects_async_data *goad;
+	GCancellable *use_cancellable;
 
-	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+	g_return_if_fail (E_IS_CAL_CLIENT (client));
+	g_return_if_fail (e_client_is_opened (E_CLIENT (client)));
 
-	cal_client = E_CAL_CLIENT (client);
+	g_return_if_fail (start >= 0);
+	g_return_if_fail (end >= 0);
+	g_return_if_fail (cb != NULL);
 
-	if (!cal_client->priv->gdbus_cal) {
-		set_proxy_gone_error (error);
-		return FALSE;
-	}
+	comp = e_cal_component_new ();
+	e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (icalcomp));
 
-	prop_val = e_client_get_backend_property_from_cache (client, prop_name);
-	if (prop_val) {
-		g_return_val_if_fail (prop_value != NULL, FALSE);
+	if (!e_cal_component_has_recurrences (comp))
+		is_single_instance = TRUE;
 
-		*prop_value = prop_val;
+	/* If the backend stores it as individual instances and does not
+	 * have a master object - do not expand */
+	if (is_single_instance || e_client_check_capability (E_CLIENT (client), CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER)) {
+		/* return the same instance */
+		(* cb)  (comp, icaltime_as_timet_with_zone (icalcomponent_get_dtstart (icalcomp), client->priv->default_zone),
+				icaltime_as_timet_with_zone (icalcomponent_get_dtend (icalcomp), client->priv->default_zone), cb_data);
+		g_object_unref (comp);
 
-		return TRUE;
+		if (destroy_cb_data)
+			destroy_cb_data (cb_data);
+		return;
 	}
 
-	res = e_client_proxy_call_sync_string__string (client, prop_name, prop_value, cancellable, error, e_gdbus_cal_call_get_backend_property_sync);
+	e_cal_component_get_uid (comp, &uid);
 
-	if (res && prop_value)
-		e_client_update_backend_property_cache (client, prop_name, *prop_value);
+	/* Get the start timezone */
+	e_cal_component_get_dtstart (comp, &datetime);
+	if (datetime.tzid)
+		e_cal_client_get_timezone_sync (client, datetime.tzid, &start_zone, NULL, NULL);
+	else
+		start_zone = NULL;
+	e_cal_component_free_datetime (&datetime);
 
-	return res;
-}
+	/* Get the end timezone */
+	e_cal_component_get_dtend (comp, &datetime);
+	if (datetime.tzid)
+		e_cal_client_get_timezone_sync (client, datetime.tzid, &end_zone, NULL, NULL);
+	else
+		end_zone = NULL;
+	e_cal_component_free_datetime (&datetime);
 
-static void
-cal_client_set_backend_property (EClient *client,
-                                 const gchar *prop_name,
-                                 const gchar *prop_value,
-                                 GCancellable *cancellable,
-                                 GAsyncReadyCallback callback,
-                                 gpointer user_data)
-{
-	gchar **prop_name_value;
+	use_cancellable = cancellable;
+	if (!use_cancellable)
+		use_cancellable = g_cancellable_new ();
 
-	prop_name_value = e_gdbus_cal_encode_set_backend_property (prop_name, prop_value);
+	goad = g_new0 (struct get_objects_async_data, 1);
+	goad->cancellable = g_object_ref (use_cancellable);
+	goad->client = g_object_ref (client);
+	goad->start = start;
+	goad->end = end;
+	goad->cb = cb;
+	goad->cb_data = cb_data;
+	goad->destroy_cb_data = destroy_cb_data;
+	goad->start_zone = start_zone;
+	goad->end_zone = end_zone;
+	goad->comp = comp;
+	goad->uid = g_strdup (uid);
 
-	e_client_proxy_call_strv (client, (const gchar * const *) prop_name_value, cancellable, callback, user_data, cal_client_set_backend_property,
-			e_gdbus_cal_call_set_backend_property,
-			e_gdbus_cal_call_set_backend_property_finish, NULL, NULL, NULL, NULL);
+	get_objects_async (generate_instances_for_object_got_objects_cb, goad);
 
-	g_strfreev (prop_name_value);
+	if (use_cancellable != cancellable)
+		g_object_unref (use_cancellable);
 }
 
-static gboolean
-cal_client_set_backend_property_finish (EClient *client,
-                                        GAsyncResult *result,
-                                        GError **error)
+/**
+ * e_cal_client_generate_instances_for_object_sync:
+ * @client: A calendar client
+ * @icalcomp: Object to generate instances from
+ * @start: Start time for query
+ * @end: End time for query
+ * @cb: (closure cb_data) (scope call): Callback for each generated instance
+ * @cb_data: (closure): Closure data for the callback
+ *
+ * Does a combination of #e_cal_client_get_object_list () and
+ * #e_cal_client_recur_generate_instances(), like #e_cal_client_generate_instances_sync(), but
+ * for a single object.
+ *
+ * The callback function should do a g_object_ref() of the calendar component
+ * it gets passed if it intends to keep it around, since it will be unref'ed
+ * as soon as the callback returns.
+ *
+ * Since: 3.2
+ **/
+void
+e_cal_client_generate_instances_for_object_sync (ECalClient *client,
+                                                 icalcomponent *icalcomp,
+                                                 time_t start,
+                                                 time_t end,
+                                                 ECalRecurInstanceFn cb,
+                                                 gpointer cb_data)
 {
-	return e_client_proxy_call_finish_void (client, result, error, cal_client_set_backend_property);
-}
+	ECalComponent *comp;
+	const gchar *uid;
+	GSList *instances = NULL;
+	ECalComponentDateTime datetime;
+	icaltimezone *start_zone = NULL, *end_zone = NULL;
+	struct instances_info *instances_hold;
+	gboolean is_single_instance = FALSE;
 
-static gboolean
-cal_client_set_backend_property_sync (EClient *client,
-                                      const gchar *prop_name,
-                                      const gchar *prop_value,
-                                      GCancellable *cancellable,
-                                      GError **error)
-{
-	ECalClient *cal_client;
-	gboolean res;
-	gchar **prop_name_value;
+	g_return_if_fail (E_IS_CAL_CLIENT (client));
+	g_return_if_fail (e_client_is_opened (E_CLIENT (client)));
 
-	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+	g_return_if_fail (start >= 0);
+	g_return_if_fail (end >= 0);
+	g_return_if_fail (cb != NULL);
 
-	cal_client = E_CAL_CLIENT (client);
+	comp = e_cal_component_new ();
+	e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (icalcomp));
 
-	if (!cal_client->priv->gdbus_cal) {
-		set_proxy_gone_error (error);
-		return FALSE;
+	if (!e_cal_component_has_recurrences (comp))
+		is_single_instance = TRUE;
+
+	/* If the backend stores it as individual instances and does not
+	 * have a master object - do not expand */
+	if (is_single_instance || e_client_check_capability (E_CLIENT (client), CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER)) {
+		/* return the same instance */
+		(* cb)  (comp, icaltime_as_timet_with_zone (icalcomponent_get_dtstart (icalcomp), client->priv->default_zone),
+				icaltime_as_timet_with_zone (icalcomponent_get_dtend (icalcomp), client->priv->default_zone), cb_data);
+		g_object_unref (comp);
+		return;
 	}
 
-	prop_name_value = e_gdbus_cal_encode_set_backend_property (prop_name, prop_value);
-	res = e_client_proxy_call_sync_strv__void (client, (const gchar * const *) prop_name_value, cancellable, error, e_gdbus_cal_call_set_backend_property_sync);
-	g_strfreev (prop_name_value);
+	e_cal_component_get_uid (comp, &uid);
 
-	return res;
-}
+	/* Get the start timezone */
+	e_cal_component_get_dtstart (comp, &datetime);
+	if (datetime.tzid)
+		e_cal_client_get_timezone_sync (client, datetime.tzid, &start_zone, NULL, NULL);
+	else
+		start_zone = NULL;
+	e_cal_component_free_datetime (&datetime);
 
-static void
-cal_client_open (EClient *client,
-                 gboolean only_if_exists,
-                 GCancellable *cancellable,
-                 GAsyncReadyCallback callback,
-                 gpointer user_data)
-{
-	e_client_proxy_call_boolean (client, only_if_exists, cancellable, callback, user_data, cal_client_open,
-			e_gdbus_cal_call_open,
-			e_gdbus_cal_call_open_finish, NULL, NULL, NULL, NULL);
-}
+	/* Get the end timezone */
+	e_cal_component_get_dtend (comp, &datetime);
+	if (datetime.tzid)
+		e_cal_client_get_timezone_sync (client, datetime.tzid, &end_zone, NULL, NULL);
+	else
+		end_zone = NULL;
+	e_cal_component_free_datetime (&datetime);
 
-static gboolean
-cal_client_open_finish (EClient *client,
-                        GAsyncResult *result,
-                        GError **error)
-{
-	return e_client_proxy_call_finish_void (client, result, error, cal_client_open);
+	instances_hold = g_new0 (struct instances_info, 1);
+	instances_hold->instances = &instances;
+	instances_hold->start_zone = start_zone;
+	instances_hold->end_zone = end_zone;
+
+	/* generate all instances in the given time range */
+	generate_instances (client, start, end, get_objects_sync (client, start, end, uid), NULL, add_instance, instances_hold);
+
+	/* it also frees 'instances' GSList */
+	process_instances (comp, *(instances_hold->instances), cb, cb_data);
+
+	/* clean up */
+	g_object_unref (comp);
+	g_free (instances_hold);
 }
 
-static gboolean
-cal_client_open_sync (EClient *client,
-                      gboolean only_if_exists,
-                      GCancellable *cancellable,
-                      GError **error)
+typedef struct _ForeachTZIDCallbackData ForeachTZIDCallbackData;
+struct _ForeachTZIDCallbackData {
+	ECalClient *client;
+	GHashTable *timezone_hash;
+	gboolean success;
+};
+
+/* This adds the VTIMEZONE given by the TZID parameter to the GHashTable in
+ * data. */
+static void
+foreach_tzid_callback (icalparameter *param,
+                       gpointer cbdata)
 {
-	ECalClient *cal_client;
+	ForeachTZIDCallbackData *data = cbdata;
+	const gchar *tzid;
+	icaltimezone *zone = NULL;
+	icalcomponent *vtimezone_comp;
+	gchar *vtimezone_as_string;
 
-	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+	/* Get the TZID string from the parameter. */
+	tzid = icalparameter_get_tzid (param);
+	if (!tzid)
+		return;
 
-	cal_client = E_CAL_CLIENT (client);
+	/* Check if we've already added it to the GHashTable. */
+	if (g_hash_table_lookup (data->timezone_hash, tzid))
+		return;
 
-	if (!cal_client->priv->gdbus_cal) {
-		set_proxy_gone_error (error);
-		return FALSE;
+	if (!e_cal_client_get_timezone_sync (data->client, tzid, &zone, NULL, NULL) || !zone) {
+		data->success = FALSE;
+		return;
 	}
 
-	return e_client_proxy_call_sync_boolean__void (client, only_if_exists, cancellable, error, e_gdbus_cal_call_open_sync);
+	/* Convert it to a string and add it to the hash. */
+	vtimezone_comp = icaltimezone_get_component (zone);
+	if (!vtimezone_comp)
+		return;
+
+	vtimezone_as_string = icalcomponent_as_ical_string_r (vtimezone_comp);
+
+	g_hash_table_insert (data->timezone_hash, (gchar *) tzid, vtimezone_as_string);
 }
 
+/* This appends the value string to the GString given in data. */
 static void
-cal_client_refresh (EClient *client,
-                    GCancellable *cancellable,
-                    GAsyncReadyCallback callback,
-                    gpointer user_data)
+append_timezone_string (gpointer key,
+                        gpointer value,
+                        gpointer data)
 {
-	e_client_proxy_call_void (client, cancellable, callback, user_data, cal_client_refresh,
-			e_gdbus_cal_call_refresh,
-			e_gdbus_cal_call_refresh_finish, NULL, NULL, NULL, NULL);
+	GString *vcal_string = data;
+
+	g_string_append (vcal_string, value);
+	g_free (value);
 }
 
-static gboolean
-cal_client_refresh_finish (EClient *client,
-                           GAsyncResult *result,
-                           GError **error)
+/* This simply frees the hash values. */
+static void
+free_timezone_string (gpointer key,
+                      gpointer value,
+                      gpointer data)
 {
-	return e_client_proxy_call_finish_void (client, result, error, cal_client_refresh);
+	g_free (value);
 }
 
-static gboolean
-cal_client_refresh_sync (EClient *client,
-                         GCancellable *cancellable,
-                         GError **error)
+/**
+ * e_cal_client_get_component_as_string:
+ * @client: A calendar client.
+ * @icalcomp: A calendar component object.
+ *
+ * Gets a calendar component as an iCalendar string, with a toplevel
+ * VCALENDAR component and all VTIMEZONEs needed for the component.
+ *
+ * Returns: the component as a complete iCalendar string, or NULL on
+ * failure. The string should be freed with g_free().
+ *
+ * Since: 3.2
+ **/
+gchar *
+e_cal_client_get_component_as_string (ECalClient *client,
+                                      icalcomponent *icalcomp)
 {
-	ECalClient *cal_client;
+	GHashTable *timezone_hash;
+	GString *vcal_string;
+	ForeachTZIDCallbackData cbdata;
+	gchar *obj_string;
 
-	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
+	g_return_val_if_fail (E_IS_CAL_CLIENT (client), NULL);
+	g_return_val_if_fail (icalcomp != NULL, NULL);
 
-	cal_client = E_CAL_CLIENT (client);
+	timezone_hash = g_hash_table_new (g_str_hash, g_str_equal);
 
-	if (!cal_client->priv->gdbus_cal) {
-		set_proxy_gone_error (error);
-		return FALSE;
+	/* Add any timezones needed to the hash. We use a hash since we only
+	 * want to add each timezone once at most. */
+	cbdata.client = client;
+	cbdata.timezone_hash = timezone_hash;
+	cbdata.success = TRUE;
+	icalcomponent_foreach_tzid (icalcomp, foreach_tzid_callback, &cbdata);
+	if (!cbdata.success) {
+		g_hash_table_foreach (timezone_hash, free_timezone_string, NULL);
+		return NULL;
 	}
 
-	return e_client_proxy_call_sync_void__void (client, cancellable, error, e_gdbus_cal_call_refresh_sync);
+	/* Create the start of a VCALENDAR, to add the VTIMEZONES to,
+	 * and remember its length so we know if any VTIMEZONEs get added. */
+	vcal_string = g_string_new (NULL);
+	g_string_append (vcal_string,
+			 "BEGIN:VCALENDAR\n"
+			 "PRODID:-//Ximian//NONSGML Evolution Calendar//EN\n"
+			 "VERSION:2.0\n"
+			 "METHOD:PUBLISH\n");
+
+	/* Now concatenate all the timezone strings. This also frees the
+	 * timezone strings as it goes. */
+	g_hash_table_foreach (timezone_hash, append_timezone_string, vcal_string);
+
+	/* Get the string for the VEVENT/VTODO. */
+	obj_string = icalcomponent_as_ical_string_r (icalcomp);
+
+	/* If there were any timezones to send, create a complete VCALENDAR,
+	 * else just send the VEVENT/VTODO string. */
+	g_string_append (vcal_string, obj_string);
+	g_string_append (vcal_string, "END:VCALENDAR\n");
+	g_free (obj_string);
+
+	obj_string = g_string_free (vcal_string, FALSE);
+
+	g_hash_table_destroy (timezone_hash);
+
+	return obj_string;
 }
 
 static gboolean
@@ -4572,11 +4771,11 @@ complete_get_view (ECalClient *client,
 {
 	g_return_val_if_fail (view != NULL, FALSE);
 
-	if (view_path && res && cal_factory_proxy) {
+	if (view_path && res && cal_factory) {
 		EGdbusCalView *gdbus_calview;
 		GError *local_error = NULL;
 
-		gdbus_calview = e_gdbus_cal_view_proxy_new_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (cal_factory_proxy)),
+		gdbus_calview = e_gdbus_cal_view_proxy_new_sync (g_dbus_proxy_get_connection (G_DBUS_PROXY (cal_factory)),
 								G_DBUS_PROXY_FLAGS_NONE,
 								CALENDAR_DBUS_SERVICE_NAME,
 								view_path,
@@ -5053,167 +5252,3 @@ e_cal_client_add_timezone_sync (ECalClient *client,
 	return res;
 }
 
-static GDBusProxy *
-cal_client_get_dbus_proxy (EClient *client)
-{
-	ECalClient *cal_client;
-
-	g_return_val_if_fail (E_IS_CAL_CLIENT (client), NULL);
-
-	cal_client = E_CAL_CLIENT (client);
-
-	return cal_client->priv->gdbus_cal;
-}
-
-static void
-cal_client_unwrap_dbus_error (EClient *client,
-                              GError *dbus_error,
-                              GError **out_error)
-{
-	unwrap_dbus_error (dbus_error, out_error);
-}
-
-static void
-cal_client_retrieve_capabilities (EClient *client,
-                                  GCancellable *cancellable,
-                                  GAsyncReadyCallback callback,
-                                  gpointer user_data)
-{
-	g_return_if_fail (E_IS_CAL_CLIENT (client));
-
-	cal_client_get_backend_property (client, CLIENT_BACKEND_PROPERTY_CAPABILITIES, cancellable, callback, user_data);
-}
-
-static gboolean
-cal_client_retrieve_capabilities_finish (EClient *client,
-                                         GAsyncResult *result,
-                                         gchar **capabilities,
-                                         GError **error)
-{
-	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
-
-	return cal_client_get_backend_property_finish (client, result, capabilities, error);
-}
-
-static gboolean
-cal_client_retrieve_capabilities_sync (EClient *client,
-                                       gchar **capabilities,
-                                       GCancellable *cancellable,
-                                       GError **error)
-{
-	g_return_val_if_fail (E_IS_CAL_CLIENT (client), FALSE);
-
-	return cal_client_get_backend_property_sync (client, CLIENT_BACKEND_PROPERTY_CAPABILITIES, capabilities, cancellable, error);
-}
-
-static void
-free_zone_cb (gpointer zone)
-{
-	icaltimezone_free (zone, 1);
-}
-
-static void
-e_cal_client_init (ECalClient *client)
-{
-	LOCK_FACTORY ();
-	active_cal_clients++;
-	UNLOCK_FACTORY ();
-
-	client->priv = E_CAL_CLIENT_GET_PRIVATE (client);
-	client->priv->source_type = E_CAL_CLIENT_SOURCE_TYPE_LAST;
-	client->priv->default_zone = icaltimezone_get_utc_timezone ();
-	client->priv->cache_dir = NULL;
-	client->priv->zone_cache_lock = g_mutex_new ();
-	client->priv->zone_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, free_zone_cb);
-}
-
-static void
-cal_client_dispose (GObject *object)
-{
-	EClient *client;
-
-	client = E_CLIENT (object);
-
-	e_client_cancel_all (client);
-
-	gdbus_cal_client_disconnect (E_CAL_CLIENT (client));
-
-	/* Chain up to parent's dispose() method. */
-	G_OBJECT_CLASS (e_cal_client_parent_class)->dispose (object);
-}
-
-static void
-cal_client_finalize (GObject *object)
-{
-	ECalClient *client;
-	ECalClientPrivate *priv;
-
-	client = E_CAL_CLIENT (object);
-
-	priv = client->priv;
-
-	g_free (priv->cache_dir);
-	priv->cache_dir = NULL;
-
-	if (priv->default_zone && priv->default_zone != icaltimezone_get_utc_timezone ())
-		icaltimezone_free (priv->default_zone, 1);
-	priv->default_zone = NULL;
-
-	g_mutex_lock (priv->zone_cache_lock);
-	g_hash_table_destroy (priv->zone_cache);
-	priv->zone_cache = NULL;
-	g_mutex_unlock (priv->zone_cache_lock);
-	g_mutex_free (priv->zone_cache_lock);
-	priv->zone_cache_lock = NULL;
-
-	/* Chain up to parent's finalize() method. */
-	G_OBJECT_CLASS (e_cal_client_parent_class)->finalize (object);
-
-	LOCK_FACTORY ();
-	active_cal_clients--;
-	if (!active_cal_clients)
-		gdbus_cal_factory_proxy_disconnect (NULL);
-	UNLOCK_FACTORY ();
-}
-
-static void
-e_cal_client_class_init (ECalClientClass *class)
-{
-	GObjectClass *object_class;
-	EClientClass *client_class;
-
-	g_type_class_add_private (class, sizeof (ECalClientPrivate));
-
-	object_class = G_OBJECT_CLASS (class);
-	object_class->dispose = cal_client_dispose;
-	object_class->finalize = cal_client_finalize;
-
-	client_class = E_CLIENT_CLASS (class);
-	client_class->get_dbus_proxy			= cal_client_get_dbus_proxy;
-	client_class->unwrap_dbus_error			= cal_client_unwrap_dbus_error;
-	client_class->retrieve_capabilities		= cal_client_retrieve_capabilities;
-	client_class->retrieve_capabilities_finish	= cal_client_retrieve_capabilities_finish;
-	client_class->retrieve_capabilities_sync	= cal_client_retrieve_capabilities_sync;
-	client_class->get_backend_property		= cal_client_get_backend_property;
-	client_class->get_backend_property_finish	= cal_client_get_backend_property_finish;
-	client_class->get_backend_property_sync		= cal_client_get_backend_property_sync;
-	client_class->set_backend_property		= cal_client_set_backend_property;
-	client_class->set_backend_property_finish	= cal_client_set_backend_property_finish;
-	client_class->set_backend_property_sync		= cal_client_set_backend_property_sync;
-	client_class->open				= cal_client_open;
-	client_class->open_finish			= cal_client_open_finish;
-	client_class->open_sync				= cal_client_open_sync;
-	client_class->refresh				= cal_client_refresh;
-	client_class->refresh_finish			= cal_client_refresh_finish;
-	client_class->refresh_sync			= cal_client_refresh_sync;
-
-	signals[FREE_BUSY_DATA] = g_signal_new (
-		"free-busy-data",
-		G_OBJECT_CLASS_TYPE (class),
-		G_SIGNAL_RUN_FIRST,
-		G_STRUCT_OFFSET (ECalClientClass, free_busy_data),
-		NULL, NULL,
-		g_cclosure_marshal_VOID__POINTER,
-		G_TYPE_NONE, 1,
-		G_TYPE_POINTER);
-}



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