diff options
author | Matthew Barnes <mbarnes@src.gnome.org> | 2008-12-14 12:06:26 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@src.gnome.org> | 2008-12-14 12:06:26 +0800 |
commit | 22638789fafe044f3c25a5ddbbc371e5da727293 (patch) | |
tree | 23900ef688d52a40421fb7469f6454a7cfeb5f24 | |
parent | b7333387e8bd19299794e6485e3407d03c2eb73f (diff) | |
download | gsoc2013-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.c | 103 | ||||
-rw-r--r-- | mail/mail-component.c | 226 | ||||
-rw-r--r-- | shell/e-shell.c | 111 |
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 * |