aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@src.gnome.org>2008-12-14 12:06:26 +0800
committerMatthew Barnes <mbarnes@src.gnome.org>2008-12-14 12:06:26 +0800
commit22638789fafe044f3c25a5ddbbc371e5da727293 (patch)
tree23900ef688d52a40421fb7469f6454a7cfeb5f24
parentb7333387e8bd19299794e6485e3407d03c2eb73f (diff)
downloadgsoc2013-evolution-22638789fafe044f3c25a5ddbbc371e5da727293.tar.gz
gsoc2013-evolution-22638789fafe044f3c25a5ddbbc371e5da727293.tar.zst
gsoc2013-evolution-22638789fafe044f3c25a5ddbbc371e5da727293.zip
- Get offline synchronization working in the mailer (I think).
svn path=/branches/kill-bonobo/; revision=36876
-rw-r--r--mail/e-mail-shell-module.c103
-rw-r--r--mail/mail-component.c226
-rw-r--r--shell/e-shell.c111
3 files changed, 303 insertions, 137 deletions
diff --git a/mail/e-mail-shell-module.c b/mail/e-mail-shell-module.c
index 04446b1e73..5662067b54 100644
--- a/mail/e-mail-shell-module.c
+++ b/mail/e-mail-shell-module.c
@@ -20,6 +20,8 @@
*/
#include <glib/gi18n.h>
+#include <camel/camel-disco-store.h>
+#include <camel/camel-offline-store.h>
#include <camel/camel-session.h>
#include <camel/camel-url.h>
@@ -48,6 +50,7 @@
#include "mail-config.h"
#include "mail-folder-cache.h"
#include "mail-mt.h"
+#include "mail-ops.h"
#include "mail-send-recv.h"
#include "mail-session.h"
#include "mail-vfolder.h"
@@ -461,6 +464,17 @@ mail_shell_module_init_preferences (EShell *shell)
500);
}
+static void
+mail_shell_module_notify_online_mode_cb (EShell *shell,
+ GParamSpec *pspec,
+ EShellModule *shell_module)
+{
+ gboolean online;
+
+ online = e_shell_get_online_mode (shell);
+ camel_session_set_online (session, online);
+}
+
static gboolean
mail_shell_module_handle_uri_cb (EShell *shell,
const gchar *uri,
@@ -470,6 +484,80 @@ mail_shell_module_handle_uri_cb (EShell *shell,
return FALSE;
}
+/* Helper for mail_shell_module_prepare_for_[off|on]line_cb() */
+static void
+mail_shell_store_line_transition_done_cb (CamelStore *store,
+ gpointer user_data)
+{
+ EActivity *activity = user_data;
+
+ g_object_unref (activity);
+}
+
+/* Helper for mail_shell_module_prepare_for_offline_cb() */
+static void
+mail_shell_store_prepare_for_offline_cb (CamelService *service,
+ gpointer unused,
+ EActivity *activity)
+{
+ if (CAMEL_IS_DISCO_STORE (service) || CAMEL_IS_OFFLINE_STORE (service))
+ mail_store_set_offline (
+ CAMEL_STORE (service), TRUE,
+ mail_shell_store_line_transition_done_cb,
+ g_object_ref (activity));
+}
+
+static void
+mail_shell_module_prepare_for_offline_cb (EShell *shell,
+ EActivity *activity,
+ EShellModule *shell_module)
+{
+ GtkWidget *parent;
+ gboolean synchronize = FALSE;
+
+ parent = e_shell_get_focused_window (shell);
+
+ if (e_shell_get_network_available (shell))
+ synchronize = em_utils_prompt_user (
+ GTK_WINDOW (parent),
+ "/apps/evolution/mail/prompts/quick_offline",
+ "mail:ask-quick-offline", NULL);
+
+ if (!synchronize) {
+ mail_cancel_all ();
+ camel_session_set_network_state (session, FALSE);
+ }
+
+ e_mail_shell_module_stores_foreach (
+ shell_module, (GHFunc)
+ mail_shell_store_prepare_for_offline_cb, activity);
+}
+
+/* Helper for mail_shell_module_prepare_for_online_cb() */
+static void
+mail_shell_store_prepare_for_online_cb (CamelService *service,
+ gpointer unused,
+ EActivity *activity)
+{
+ if (CAMEL_IS_DISCO_STORE (service) || CAMEL_IS_OFFLINE_STORE (service))
+ mail_store_set_offline (
+ CAMEL_STORE (service), FALSE,
+ mail_shell_store_line_transition_done_cb,
+ g_object_ref (activity));
+}
+
+static void
+mail_shell_module_prepare_for_online_cb (EShell *shell,
+ EActivity *activity,
+ EShellModule *shell_module)
+{
+ camel_session_set_online (session, TRUE);
+
+ e_mail_shell_module_stores_foreach (
+ shell_module, (GHFunc)
+ mail_shell_store_prepare_for_online_cb, activity);
+}
+
static void
mail_shell_module_send_receive_cb (EShell *shell,
GtkWindow *parent,
@@ -559,11 +647,26 @@ e_shell_module_init (GTypeModule *type_module)
folder_tree_model = em_folder_tree_model_new (shell_module);
g_signal_connect (
+ shell, "notify::online-mode",
+ G_CALLBACK (mail_shell_module_notify_online_mode_cb),
+ shell_module);
+
+ g_signal_connect (
shell, "handle-uri",
G_CALLBACK (mail_shell_module_handle_uri_cb),
shell_module);
g_signal_connect (
+ shell, "prepare-for-offline",
+ G_CALLBACK (mail_shell_module_prepare_for_offline_cb),
+ shell_module);
+
+ g_signal_connect (
+ shell, "prepare-for-online",
+ G_CALLBACK (mail_shell_module_prepare_for_online_cb),
+ shell_module);
+
+ g_signal_connect (
shell, "send-receive",
G_CALLBACK (mail_shell_module_send_receive_cb),
shell_module);
diff --git a/mail/mail-component.c b/mail/mail-component.c
index 890046e48c..33468cb459 100644
--- a/mail/mail-component.c
+++ b/mail/mail-component.c
@@ -1126,104 +1126,104 @@ call_mail_sync (gpointer user_data)
return !camel_application_is_exiting;
}
-struct _setline_data {
- GNOME_Evolution_Listener listener;
- CORBA_boolean status;
- int pending;
-};
-
-static void
-setline_done(CamelStore *store, void *data)
-{
- struct _setline_data *sd = data;
-
- g_return_if_fail (sd->pending > 0);
-
- sd->pending--;
- if (sd->pending == 0) {
- CORBA_Environment ev = { NULL };
-
- GNOME_Evolution_Listener_complete(sd->listener, &ev);
- CORBA_exception_free(&ev);
- CORBA_Object_release(sd->listener, &ev);
- CORBA_exception_free(&ev);
- if (!sd->status)
- camel_session_set_online(session, sd->status);
- g_free(sd);
- }
-}
-
-static void
-setline_check(void *key, void *value, void *data)
-{
- CamelService *service = key;
- struct _setline_data *sd = data;
-
- if (CAMEL_IS_DISCO_STORE(service)
- || CAMEL_IS_OFFLINE_STORE(service)) {
- sd->pending++;
- mail_store_set_offline((CamelStore *)service, !sd->status, setline_done, sd);
- }
-}
-
-int
-status_check (GNOME_Evolution_ShellState shell_state)
-{
- int status = 0;
-
- switch (shell_state)
- {
- case GNOME_Evolution_USER_OFFLINE:
- status = OFFLINE;
- if (em_utils_prompt_user (NULL, "/apps/evolution/mail/prompts/quick_offline", "mail:ask-quick-offline", NULL))
- break;
- case GNOME_Evolution_FORCED_OFFLINE:
- /*Network is down so change network state on the camel session*/
- status = OFFLINE;
- /* Cancel all operations as they wont happen anyway cos Network is down*/
- mail_cancel_all ();
- camel_session_set_network_state (session, FALSE);
- break;
- case GNOME_Evolution_USER_ONLINE:
- camel_session_set_network_state (session, TRUE);
- status = ONLINE;
- }
-
- return status;
-}
+//struct _setline_data {
+// GNOME_Evolution_Listener listener;
+// CORBA_boolean status;
+// int pending;
+//};
-static void
-impl_setLineStatus(PortableServer_Servant servant, GNOME_Evolution_ShellState shell_state, GNOME_Evolution_Listener listener, CORBA_Environment *ev)
-{
- struct _setline_data *sd;
- int status = status_check(shell_state);
-
- /* This will dis/enable further auto-mail-check action. */
- /* FIXME: If send/receive active, wait for it to finish? */
- if (status)
- camel_session_set_online(session, status);
-
- sd = g_malloc0(sizeof(*sd));
- sd->status = status;
- sd->listener = CORBA_Object_duplicate(listener, ev);
- if (ev->_major == CORBA_NO_EXCEPTION)
- mail_component_stores_foreach(mail_component_peek(), setline_check, sd);
- else
- CORBA_exception_free(ev);
+//static void
+//setline_done(CamelStore *store, void *data)
+//{
+// struct _setline_data *sd = data;
+//
+// g_return_if_fail (sd->pending > 0);
+//
+// sd->pending--;
+// if (sd->pending == 0) {
+// CORBA_Environment ev = { NULL };
+//
+// GNOME_Evolution_Listener_complete(sd->listener, &ev);
+// CORBA_exception_free(&ev);
+// CORBA_Object_release(sd->listener, &ev);
+// CORBA_exception_free(&ev);
+// if (!sd->status)
+// camel_session_set_online(session, sd->status);
+// g_free(sd);
+// }
+//}
- if (sd->pending == 0) {
- if (sd->listener) {
- CORBA_Object_release(sd->listener, ev);
- CORBA_exception_free(ev);
- }
+//static void
+//setline_check(void *key, void *value, void *data)
+//{
+// CamelService *service = key;
+// struct _setline_data *sd = data;
+//
+// if (CAMEL_IS_DISCO_STORE(service)
+// || CAMEL_IS_OFFLINE_STORE(service)) {
+// sd->pending++;
+// mail_store_set_offline((CamelStore *)service, !sd->status, setline_done, sd);
+// }
+//}
- g_free(sd);
+//int
+//status_check (GNOME_Evolution_ShellState shell_state)
+//{
+// int status = 0;
+//
+// switch (shell_state)
+// {
+// case GNOME_Evolution_USER_OFFLINE:
+// status = OFFLINE;
+// if (em_utils_prompt_user (NULL, "/apps/evolution/mail/prompts/quick_offline", "mail:ask-quick-offline", NULL))
+// break;
+// case GNOME_Evolution_FORCED_OFFLINE:
+// /*Network is down so change network state on the camel session*/
+// status = OFFLINE;
+// /* Cancel all operations as they wont happen anyway cos Network is down*/
+// mail_cancel_all ();
+// camel_session_set_network_state (session, FALSE);
+// break;
+// case GNOME_Evolution_USER_ONLINE:
+// camel_session_set_network_state (session, TRUE);
+// status = ONLINE;
+// }
+//
+// return status;
+//}
- if (!status)
- camel_session_set_online(session, status);
- GNOME_Evolution_Listener_complete(listener, ev);
- }
-}
+//static void
+//impl_setLineStatus(PortableServer_Servant servant, GNOME_Evolution_ShellState shell_state, GNOME_Evolution_Listener listener, CORBA_Environment *ev)
+//{
+// struct _setline_data *sd;
+// int status = status_check(shell_state);
+//
+// /* This will dis/enable further auto-mail-check action. */
+// /* FIXME: If send/receive active, wait for it to finish? */
+// if (status)
+// camel_session_set_online(session, status);
+//
+// sd = g_malloc0(sizeof(*sd));
+// sd->status = status;
+// sd->listener = CORBA_Object_duplicate(listener, ev);
+// if (ev->_major == CORBA_NO_EXCEPTION)
+// mail_component_stores_foreach(mail_component_peek(), setline_check, sd);
+// else
+// CORBA_exception_free(ev);
+//
+// if (sd->pending == 0) {
+// if (sd->listener) {
+// CORBA_Object_release(sd->listener, ev);
+// CORBA_exception_free(ev);
+// }
+//
+// g_free(sd);
+//
+// if (!status)
+// camel_session_set_online(session, status);
+// GNOME_Evolution_Listener_complete(listener, ev);
+// }
+//}
static void
impl_mail_test(PortableServer_Servant servant, CORBA_Environment *ev)
@@ -1484,27 +1484,27 @@ mail_component_remove_store_by_uri (MailComponent *component, const char *uri)
// return g_hash_table_size (component->priv->store_hash);
//}
-/* need to map from internal struct to external api */
-struct _store_foreach_data {
- GHFunc func;
- void *data;
-};
-
-static void
-mc_stores_foreach(CamelStore *store, struct _store_info *si, struct _store_foreach_data *data)
-{
- data->func((void *)store, (void *)si->name, data->data);
-}
-
-void
-mail_component_stores_foreach (MailComponent *component, GHFunc func, void *user_data)
-{
- struct _store_foreach_data data = { func, user_data };
+///* need to map from internal struct to external api */
+//struct _store_foreach_data {
+// GHFunc func;
+// void *data;
+//};
- MAIL_COMPONENT_DEFAULT(component);
+//static void
+//mc_stores_foreach(CamelStore *store, struct _store_info *si, struct _store_foreach_data *data)
+//{
+// data->func((void *)store, (void *)si->name, data->data);
+//}
- g_hash_table_foreach (component->priv->store_hash, (GHFunc)mc_stores_foreach, &data);
-}
+//void
+//mail_component_stores_foreach (MailComponent *component, GHFunc func, void *user_data)
+//{
+// struct _store_foreach_data data = { func, user_data };
+//
+// MAIL_COMPONENT_DEFAULT(component);
+//
+// g_hash_table_foreach (component->priv->store_hash, (GHFunc)mc_stores_foreach, &data);
+//}
//void
//mail_component_remove_folder (MailComponent *component, CamelStore *store, const char *path)
diff --git a/shell/e-shell.c b/shell/e-shell.c
index 57118a4e14..95303b8b39 100644
--- a/shell/e-shell.c
+++ b/shell/e-shell.c
@@ -46,7 +46,7 @@ struct _EShellPrivate {
GHashTable *modules_by_name;
GHashTable *modules_by_scheme;
- gpointer preparing_for_offline; /* weak pointer */
+ gpointer preparing_for_line_change; /* weak pointer */
guint auto_reconnect : 1;
guint network_available : 1;
@@ -65,6 +65,7 @@ enum {
EVENT,
HANDLE_URI,
PREPARE_FOR_OFFLINE,
+ PREPARE_FOR_ONLINE,
SEND_RECEIVE,
WINDOW_CREATED,
WINDOW_DESTROYED,
@@ -164,27 +165,74 @@ static void
shell_prepare_for_offline (EShell *shell)
{
/* Are preparations already in progress? */
- if (shell->priv->preparing_for_offline != NULL)
+ if (shell->priv->preparing_for_line_change != NULL)
return;
g_message ("Preparing for offline mode...");
- shell->priv->preparing_for_offline =
+ shell->priv->preparing_for_line_change =
e_activity_new (_("Preparing to go offline..."));
g_object_add_toggle_ref (
- G_OBJECT (shell->priv->preparing_for_offline),
+ G_OBJECT (shell->priv->preparing_for_line_change),
(GToggleNotify) shell_ready_for_offline, shell);
g_object_add_weak_pointer (
- G_OBJECT (shell->priv->preparing_for_offline),
- &shell->priv->preparing_for_offline);
+ G_OBJECT (shell->priv->preparing_for_line_change),
+ &shell->priv->preparing_for_line_change);
g_signal_emit (
shell, signals[PREPARE_FOR_OFFLINE], 0,
- shell->priv->preparing_for_offline);
+ shell->priv->preparing_for_line_change);
- g_object_unref (shell->priv->preparing_for_offline);
+ g_object_unref (shell->priv->preparing_for_line_change);
+}
+
+static void
+shell_ready_for_online (EShell *shell,
+ EActivity *activity,
+ gboolean is_last_ref)
+{
+ if (!is_last_ref)
+ return;
+
+ e_activity_complete (activity);
+
+ g_object_remove_toggle_ref (
+ G_OBJECT (activity), (GToggleNotify)
+ shell_ready_for_online, shell);
+
+ shell->priv->online_mode = TRUE;
+ g_object_notify (G_OBJECT (shell), "online-mode");
+
+ g_message ("Online preparations complete.");
+}
+
+static void
+shell_prepare_for_online (EShell *shell)
+{
+ /* Are preparations already in progress? */
+ if (shell->priv->preparing_for_line_change != NULL)
+ return;
+
+ g_message ("Preparing for online mode...");
+
+ shell->priv->preparing_for_line_change =
+ e_activity_new (_("Preparing to go online..."));
+
+ g_object_add_toggle_ref (
+ G_OBJECT (shell->priv->preparing_for_line_change),
+ (GToggleNotify) shell_ready_for_online, shell);
+
+ g_object_add_weak_pointer (
+ G_OBJECT (shell->priv->preparing_for_line_change),
+ &shell->priv->preparing_for_line_change);
+
+ g_signal_emit (
+ shell, signals[PREPARE_FOR_ONLINE], 0,
+ shell->priv->preparing_for_line_change);
+
+ g_object_unref (shell->priv->preparing_for_line_change);
}
/* Helper for shell_query_module() */
@@ -535,8 +583,8 @@ shell_class_init (EShellClass *class)
* the #EShellModule should reference the @activity until
* preparations are complete, and then unreference the @activity.
* This will delay Evolution from actually going to offline mode
- * until the all modules have unreferenced @activity.
- */
+ * until all modules have unreferenced @activity.
+ **/
signals[PREPARE_FOR_OFFLINE] = g_signal_new (
"prepare-for-offline",
G_OBJECT_CLASS_TYPE (object_class),
@@ -547,6 +595,31 @@ shell_class_init (EShellClass *class)
E_TYPE_ACTIVITY);
/**
+ * EShell:prepare-for-online
+ * @shell: the #EShell which emitted the signal
+ * @activity: the #EActivity for offline preparations
+ *
+ * Emitted when the user elects to work online. An #EShellModule
+ * should listen for this signal and make preparations for working
+ * in online mode.
+ *
+ * If preparations for working online cannot immediately be
+ * completed (such as when re-connecting to a remote server), the
+ * #EShellModule should reference the @activity until preparations
+ * are complete, and then unreference the @activity. This will
+ * delay Evolution from actually going to online mode until all
+ * modules have unreferenced @activity.
+ **/
+ signals[PREPARE_FOR_ONLINE] = g_signal_new (
+ "prepare-for-online",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ E_TYPE_ACTIVITY);
+
+ /**
* EShell:send-receive
* @shell: the #EShell which emitted the signal
* @parent: a parent #GtkWindow
@@ -957,7 +1030,7 @@ e_shell_get_online_mode (EShell *shell)
* @shell: an #EShell
* @online_mode: whether to put Evolution in online mode
*
- * Puts Evolution in online or offline mode.
+ * Asynchronously places Evolution in online or offline mode.
**/
void
e_shell_set_online_mode (EShell *shell,
@@ -968,20 +1041,10 @@ e_shell_set_online_mode (EShell *shell,
if (online_mode == shell->priv->online_mode)
return;
- if (!online_mode && e_shell_get_network_available (shell))
+ if (online_mode)
+ shell_prepare_for_online (shell);
+ else
shell_prepare_for_offline (shell);
- else {
- EActivity *activity;
-
- shell->priv->online_mode = online_mode;
- g_object_notify (G_OBJECT (shell), "online-mode");
-
- /* If we're being forced offline and we've already started
- * preparing for offline mode, cancel the preparations. */
- activity = shell->priv->preparing_for_offline;
- if (!online_mode && activity != NULL)
- e_activity_cancel (activity);
- }
}
GtkWidget *