[evolution-kolab/ek-wip-porting] ECalBackendKolab: implemented online/offline state switching



commit d82fc1d1983aa3e24b09777a4597fc9309f64349
Author: Christian Hilberg <hilberg kernelconcepts de>
Date:   Fri Mar 16 20:13:40 2012 +0100

    ECalBackendKolab: implemented online/offline state switching
    
    * implemented state switching (offline, online)
    * state is set initially according to the
      E-D-S status
    * state can subsequently be toggled by the
      online state button in Evolution

 src/calendar/e-cal-backend-kolab.c |  247 +++++++++++++++++++++++++++++++++---
 1 files changed, 226 insertions(+), 21 deletions(-)
---
diff --git a/src/calendar/e-cal-backend-kolab.c b/src/calendar/e-cal-backend-kolab.c
index 5b8f7f6..7f27f1f 100644
--- a/src/calendar/e-cal-backend-kolab.c
+++ b/src/calendar/e-cal-backend-kolab.c
@@ -71,20 +71,125 @@ typedef struct {
 /* Private part of the ECalBackendKolab structure */
 typedef struct _ECalBackendKolabPrivate ECalBackendKolabPrivate;
 struct _ECalBackendKolabPrivate {
-	GHashTable		*koma_table;
-	CalMode			cal_mode;
-	KolabMailAccess		*cal_koma;
-	ECalBackendCache	*cal_cache;
-	gchar			*user_email;
-	ECalComponent		*default_zone;
-	ECalSourceType		source_type;
-	gboolean		already_opened;
-	gchar *			cal_uri;
+	GHashTable *koma_table;
+	CalMode cal_mode;
+	KolabMailAccess *cal_koma;
+	ECalBackendCache *cal_cache;
+	gchar *user_email;
+	ECalComponent *default_zone;
+	ECalSourceType source_type;
+	gboolean already_opened;
+	gchar *cal_uri;
+	GError *mode_switch_err;
 };
 
 /*----------------------------------------------------------------------------*/
 /* internal statics */
 
+static void
+cal_backend_kolab_signal_online_cb (GObject *object)
+{
+	EBackend *backend = NULL;
+	ECalBackendKolab *self = NULL;
+	ECalBackendKolabPrivate *priv = NULL;
+	gboolean online = FALSE;
+	gboolean ok = FALSE;
+
+	g_return_if_fail (E_IS_CAL_BACKEND_KOLAB (object));
+
+	backend = E_BACKEND (object);
+	self = E_CAL_BACKEND_KOLAB (object);
+	priv = E_CAL_BACKEND_KOLAB_PRIVATE (self);
+
+	online = e_backend_get_online (backend);
+
+	g_debug ("%s()[%u] backend mode: %i",
+	         __func__, __LINE__, online);
+
+	/* FIXME
+	 *
+	 * This callback is for online state notifications only.
+	 * Doing I/O, which can fail, is the wrong thing to do
+	 * here since we do not have a proper way to let the user
+	 * cancel the I/O. Getting KolabMailAccess online can hang.
+	 * Thus, cancellation would be needed.
+	 *
+	 * e_backend_get_online (backend) could be called in the
+	 * "other" operations and the KolabMailAccess state changed
+	 * if needed, Problem: KolabMailAccess online/offline state
+	 * change involves synchronization with the server, which
+	 * may take long time and is not expected by the user if
+	 * they e.g. just add a contact or event.
+	 *
+	 * For now, we'll leave the cancellation issue aside
+	 * (we could not have cancelled in 2.30 either), but
+	 * at least bind a GError to our backend object, if we
+	 * have one. We can then propagate this error in the
+	 * first "other" operation the user triggers.
+	 *
+	 * It has been supposed by upstream to use a global static
+	 * GCancellable for the cancellation issue, but it will
+	 * not help us here since the Evolution online/offline
+	 * toggle button does not seem to expect heavy I/O to
+	 * be triggered. Our local GCancellabe would need transfer
+	 * to Evo and be registered there so the online/offline
+	 * switching in evo-kolab could be cancelled from the
+	 * frontend. Moreover, there is no telling how long a
+	 * synchronization run with the Kolab server may take,
+	 * so we also cannot set a sensible timeout here.
+	 *
+	 */
+
+	if (priv->mode_switch_err != NULL) {
+		g_warning ("%s()[%u]: Online mode switching error pending (%s)",
+		           __func__, __LINE__, priv->mode_switch_err->message);
+		g_error_free (priv->mode_switch_err);
+		priv->mode_switch_err = NULL;
+	}
+	ok = kolab_util_backend_deploy_mode_by_backend (priv->cal_koma,
+	                                                 online,
+	                                                 NULL, /* GCancellable (see above )*/
+	                                                &(priv->mode_switch_err));
+	if (priv->mode_switch_err) {
+		g_warning ("%s()[%u]: Online mode switching error pending (%s)",
+		           __func__, __LINE__, priv->mode_switch_err->message);
+	}
+
+	if (ok) {
+		e_cal_backend_notify_online (E_CAL_BACKEND (self), online);
+	}
+}
+
+static gboolean
+cal_backend_kolab_notify_open (ECalBackendKolab *self,
+                                GError **err)
+{
+	ECalBackend *cbackend = NULL;
+	ECalBackendKolabPrivate *priv = NULL;
+	KolabMailAccessOpmodeID tmp_mode = KOLAB_MAIL_ACCESS_OPMODE_INVAL;
+	GError *tmp_err = NULL;
+
+	g_assert (E_IS_CAL_BACKEND_KOLAB (self));
+	g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
+
+	priv = E_CAL_BACKEND_KOLAB_PRIVATE (self);
+	cbackend = E_CAL_BACKEND (self);
+
+	tmp_mode = kolab_mail_access_get_opmode (priv->cal_koma, &tmp_err);
+	if (tmp_err != NULL) {
+		g_propagate_error (err, tmp_err);
+		return FALSE;
+	}
+	e_cal_backend_notify_online (cbackend,
+	                              tmp_mode = KOLAB_MAIL_ACCESS_OPMODE_ONLINE ? TRUE : FALSE);
+	e_cal_backend_notify_opened (cbackend, NULL);
+
+	return TRUE;
+}
+
+/*----------------------------------------------------------------------------*/
+/* class functions */
+
 /**
  * e_cal_backend_kolab_open:
  * @backend: An ECalBackendSync object.
@@ -110,7 +215,6 @@ e_cal_backend_kolab_open (ECalBackendSync *backend,
 	KolabSettingsHandler *ksettings = NULL;
 	KolabMailAccess *tmp_koma = NULL;
 	KolabSyncStrategyID sync_value = KOLAB_SYNC_STRATEGY_DEFAULT;
-	KolabMailAccessOpmodeID tmp_mode = KOLAB_MAIL_ACCESS_OPMODE_INVAL;
 	icalcomponent_kind icalkind = ICAL_VEVENT_COMPONENT;
 	gchar *sourcename = NULL;
 	gchar *servername = NULL;
@@ -118,8 +222,9 @@ e_cal_backend_kolab_open (ECalBackendSync *backend,
 	gchar *user_at_server = NULL;
 	gchar *tmp_key = NULL;
 	const gchar *prop_str = NULL;
-	GError *tmp_err = NULL;
+	gboolean online = FALSE;
 	gboolean ok = FALSE;
+	GError *tmp_err = NULL;
 
 	g_return_if_fail (error == NULL || *error == NULL);
 	e_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_KOLAB (backend), InvalidArg);
@@ -209,6 +314,8 @@ e_cal_backend_kolab_open (ECalBackendSync *backend,
 	sync_value = kolab_util_misc_sync_value_from_property (prop_str);
 	sourcename = kolab_util_backend_get_relative_path_from_uri (priv->cal_uri);
 
+	/* Check whether we have a KolabMailAccess (KoMA) instance already */
+
 	user_at_server = g_strdup_printf ("%s %s",
 	                                  username, servername);
 
@@ -217,7 +324,9 @@ e_cal_backend_kolab_open (ECalBackendSync *backend,
 	                                   (gpointer *) &tmp_key,
 	                                   (gpointer *) &tmp_koma);
 	if (ok) {
-		/* There is already a KoMA instance for $servername. Use it and return */
+		/* There already is a KoMA instance for user_at_server.
+		 * Use it and return
+		 */
 		g_object_ref (tmp_koma);
 		priv->cal_koma = tmp_koma;
 		g_free (servername);
@@ -231,7 +340,29 @@ e_cal_backend_kolab_open (ECalBackendSync *backend,
 		                                     NULL,
 		                                     sourcename,
 		                                     &sync_value);
-		goto notifications;
+		g_object_unref (ksettings);
+		/* We should have received authentication data (password)
+		 * at this point, since it was requested and stored when
+		 * the KolabMailAccess object was initially created.
+		 * We can just skip the AuthenticationRequested part here
+		 * and move along...
+		 */
+		online = e_backend_get_online (E_BACKEND (backend));
+		ok = kolab_util_backend_deploy_mode_by_backend (priv->cal_koma,
+		                                                online,
+		                                                cancellable,
+		                                                &tmp_err);
+		if (! ok) {
+			kolab_util_calendar_err_to_edb_err (error, tmp_err, __func__, __LINE__);
+			g_error_free (tmp_err);
+			return;
+		}
+		ok = cal_backend_kolab_notify_open (self, &tmp_err);
+		if (! ok) {
+			kolab_util_calendar_err_to_edb_err (error, tmp_err, __func__, __LINE__);
+			g_error_free (tmp_err);
+		}
+		return;
 	}
 
 	/* Nope, we need to setup a new KoMA instance and a settings handler */
@@ -307,12 +438,15 @@ e_cal_backend_kolab_open (ECalBackendSync *backend,
 	 */
 	priv->user_email = g_strdup (user_at_server);
 
- notifications:
+	/* If we are here (just created a fresh KolabMailAccess),
+	 * we did not yet receive authentication data. Though we
+	 * do not need it if we want to stay in offline mode, once
+	 * we're asked to go online, we'll need the credentials
+	 * (password in our case) anyway, so we can just request
+	 * it once the book gets opened.
+	 */
+	e_cal_backend_notify_auth_required (E_CAL_BACKEND (self), TRUE, NULL);
 	priv->already_opened = TRUE;
-#if 0 /* FIXME */
-	e_cal_backend_kolab_set_mode (E_CAL_BACKEND (backend),
-	                              priv->cal_mode);
-#endif
 }
 
 static void
@@ -449,6 +583,7 @@ e_cal_backend_kolab_get_backend_property (ECalBackendSync *backend,
 	return processed;
 }
 
+#if 0 /* probably not needed */
 static gboolean
 e_cal_backend_kolab_set_backend_property (ECalBackendSync *backend,
                                           EDataCal *cal,
@@ -474,6 +609,7 @@ e_cal_backend_kolab_set_backend_property (ECalBackendSync *backend,
 
 	return FALSE;
 }
+#endif
 
 /**
  * e_cal_backend_kolab_get_object:
@@ -1463,6 +1599,13 @@ e_cal_backend_kolab_authenticate_user (ECalBackendSync *backend,
 {
 	ECalBackendKolab *self = NULL;
 	ECalBackendKolabPrivate *priv = NULL;
+	KolabSettingsHandler *ksettings = NULL;
+	const gchar *cred_user = NULL;
+	const gchar *cred_pwd  = NULL;
+	const gchar *kset_user = NULL;
+	gboolean online = FALSE;
+	gboolean ok = FALSE;
+	GError *tmp_err = NULL;
 
 	g_return_if_fail (error == NULL || *error == NULL);
 	e_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_KOLAB (backend), InvalidArg);
@@ -1472,7 +1615,56 @@ e_cal_backend_kolab_authenticate_user (ECalBackendSync *backend,
 	self = E_CAL_BACKEND_KOLAB (backend);
 	priv = E_CAL_BACKEND_KOLAB_PRIVATE (self);
 
-	g_error ("%s: FIXME implement me", __func__);
+	g_debug ("%s()[%u] called.", __func__, __LINE__);
+
+	ksettings = kolab_mail_access_get_settings_handler (priv->cal_koma);
+
+	/* warn about a possible inconsistency in user names */
+	kset_user = kolab_settings_handler_get_char_field (ksettings,
+	                                                  KOLAB_SETTINGS_HANDLER_CHAR_FIELD_KOLAB_USER_NAME,
+	                                                  &tmp_err);
+	if (tmp_err != NULL) {
+		g_object_unref (ksettings);
+		kolab_util_calendar_err_to_edb_err (error, tmp_err, __func__, __LINE__);
+		g_error_free (tmp_err);
+		return;
+	}
+	cred_user = e_credentials_peek (credentials,
+	                                E_CREDENTIALS_KEY_USERNAME);
+	if (g_strcmp0 (kset_user, cred_user) != 0) {
+		g_warning ("%s()[%u] username from argument and username in "
+		           "KolabSettingsHandler do not match: %s vs. %s",
+		           __func__, __LINE__, cred_user, kset_user);
+	}
+
+	cred_pwd = e_credentials_peek (credentials,
+	                               E_CREDENTIALS_KEY_PASSWORD);
+
+	kolab_util_backend_prepare_settings (ksettings,
+	                                     NULL,
+	                                     NULL,
+	                                     NULL,
+	                                     cred_pwd,
+	                                     NULL,
+	                                     NULL);
+	g_object_unref (ksettings);
+
+	online = e_backend_get_online (E_BACKEND (backend));
+	ok = kolab_util_backend_deploy_mode_by_backend (priv->cal_koma,
+	                                                 online,
+	                                                 cancellable,
+	                                                 &tmp_err);
+	if (! ok) {
+		kolab_util_calendar_err_to_edb_err (error, tmp_err, __func__, __LINE__);
+		g_error_free (tmp_err);
+		return;
+	}
+
+	ok = cal_backend_kolab_notify_open (self, &tmp_err);
+	if (! ok) {
+		kolab_util_calendar_err_to_edb_err (error, tmp_err, __func__, __LINE__);
+		g_error_free (tmp_err);
+	}
 }
 
 /**
@@ -1495,7 +1687,8 @@ e_cal_backend_kolab_start_view (ECalBackend *backend,
 	self = E_CAL_BACKEND_KOLAB (backend);
 	priv = E_CAL_BACKEND_KOLAB_PRIVATE (self);
 
-	g_error ("%s: FIXME implement me", __func__);
+	g_warning ("%s: FIXME implement me", __func__);
+	e_data_cal_view_notify_complete (view, NULL);
 
 #if 0 /* FIXME old */
 	query = e_data_cal_view_get_text (cal_view);
@@ -1567,7 +1760,8 @@ e_cal_backend_kolab_stop_view (ECalBackend *backend,
 	self = E_CAL_BACKEND_KOLAB (backend);
 	priv = E_CAL_BACKEND_KOLAB_PRIVATE (self);
 
-	g_error ("%s: FIXME implement me", __func__);
+	g_warning ("%s: FIXME implement me", __func__);
+	e_data_cal_view_notify_complete (view, NULL);
 }
 
 static void
@@ -1610,6 +1804,9 @@ e_cal_backend_kolab_init (ECalBackendKolab *backend)
 	priv->source_type = 0;
 	priv->already_opened = FALSE;
 	priv->cal_uri = NULL;
+	priv->mode_switch_err = NULL;
+
+	g_signal_connect (E_BACKEND (backend), "notify::online", G_CALLBACK (cal_backend_kolab_signal_online_cb), NULL);
 } /* e_cal_backend_kolab_init () */
 
 static void
@@ -1652,6 +1849,12 @@ e_cal_backend_kolab_finalize (GObject *object)
 	if (priv->cal_uri != NULL)
 		g_free (priv->cal_uri);
 
+	if (priv->mode_switch_err != NULL) {
+		g_warning ("%s()[%u]: %s",
+		           __func__, __LINE__, priv->mode_switch_err->message);
+		g_error_free (priv->mode_switch_err);
+	}
+
 	G_OBJECT_CLASS (e_cal_backend_kolab_parent_class)->finalize (object);
 } /* e_book_backend_kolab_finalize () */
 
@@ -1683,7 +1886,9 @@ e_cal_backend_kolab_class_init (ECalBackendKolabClass *klass)
 	sync_class->remove_sync = e_cal_backend_kolab_remove;
 	sync_class->refresh_sync = e_cal_backend_kolab_refresh;
 	sync_class->get_backend_property_sync = e_cal_backend_kolab_get_backend_property;
+#if 0 /* probably not needed */
 	sync_class->set_backend_property_sync = e_cal_backend_kolab_set_backend_property;
+#endif
 	sync_class->get_object_sync = e_cal_backend_kolab_get_object;
 	sync_class->get_object_list_sync = e_cal_backend_kolab_get_object_list;
 	sync_class->get_free_busy_sync = e_cal_backend_kolab_get_free_busy;



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