diff options
-rw-r--r-- | mail/Makefile.am | 2 | ||||
-rw-r--r-- | mail/e-mail-backend.c | 408 | ||||
-rw-r--r-- | mail/e-mail-backend.h | 79 | ||||
-rw-r--r-- | modules/mail/e-mail-shell-backend.c | 513 | ||||
-rw-r--r-- | modules/mail/e-mail-shell-backend.h | 6 |
5 files changed, 647 insertions, 361 deletions
diff --git a/mail/Makefile.am b/mail/Makefile.am index 67497712ee..934a971f9b 100644 --- a/mail/Makefile.am +++ b/mail/Makefile.am @@ -37,6 +37,7 @@ libevolution_mail_la_CPPFLAGS = \ mailinclude_HEADERS = \ e-mail-attachment-bar.h \ + e-mail-backend.h \ e-mail-browser.h \ e-mail-display.h \ e-mail-label-action.h \ @@ -95,6 +96,7 @@ mailinclude_HEADERS = \ libevolution_mail_la_SOURCES = \ e-mail-attachment-bar.c \ + e-mail-backend.c \ e-mail-browser.c \ e-mail-display.c \ e-mail-label-action.c \ diff --git a/mail/e-mail-backend.c b/mail/e-mail-backend.c new file mode 100644 index 0000000000..aa7e149f76 --- /dev/null +++ b/mail/e-mail-backend.c @@ -0,0 +1,408 @@ +/* + * e-mail-backend.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "e-mail-backend.h" + +#include <camel/camel.h> + +#include "e-util/e-account-utils.h" +#include "e-util/e-alert-dialog.h" + +#include "shell/e-shell.h" + +#include "mail/e-mail-local.h" +#include "mail/e-mail-migrate.h" +#include "mail/e-mail-store.h" +#include "mail/em-utils.h" +#include "mail/mail-ops.h" +#include "mail/mail-session.h" +#include "mail/mail-vfolder.h" + +#define E_MAIL_BACKEND_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_MAIL_BACKEND, EMailBackendPrivate)) + +#define QUIT_POLL_INTERVAL 1 /* seconds */ + +struct _EMailBackendPrivate { + gint placeholder; /* for future expansion */ +}; + +static gpointer parent_class; + +/* FIXME Kill this thing. It's a horrible hack. */ +extern gint camel_application_is_exiting; + +/* Callback for various asynchronous CamelStore operations where + * the EActivity's reference count is used as a counting semaphore. */ +static void +mail_backend_store_operation_done_cb (CamelStore *store, + gpointer user_data) +{ + g_object_unref (E_ACTIVITY (user_data)); +} + +static void +mail_backend_notify_online_cb (EShell *shell, + GParamSpec *pspec, + EMailBackend *backend) +{ + gboolean online; + + online = e_shell_get_online (shell); + camel_session_set_online (session, online); +} + +/* Helper for mail_backend_prepare_for_offline_cb() */ +static void +mail_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_backend_store_operation_done_cb, + g_object_ref (activity)); +} + +static void +mail_backend_prepare_for_offline_cb (EShell *shell, + EActivity *activity, + EMailBackend *backend) +{ + GtkWindow *window; + gboolean synchronize = FALSE; + + window = e_shell_get_active_window (shell); + + if (e_shell_get_network_available (shell)) + synchronize = em_utils_prompt_user ( + window, NULL, "mail:ask-quick-offline", NULL); + + if (!synchronize) { + mail_cancel_all (); + camel_session_set_network_state (session, FALSE); + } + + e_mail_store_foreach ( + (GHFunc) mail_store_prepare_for_offline_cb, activity); +} + +/* Helper for mail_backend_prepare_for_online_cb() */ +static void +mail_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_backend_store_operation_done_cb, + g_object_ref (activity)); +} + +static void +mail_backend_prepare_for_online_cb (EShell *shell, + EActivity *activity, + EMailBackend *backend) +{ + camel_session_set_online (session, TRUE); + + e_mail_store_foreach ( + (GHFunc) mail_store_prepare_for_online_cb, activity); +} + +/* Helper for mail_backend_prepare_for_quit_cb() */ +static void +mail_backend_delete_junk (CamelStore *store, + gpointer unused, + EMailBackend *backend) +{ + CamelFolder *folder; + GPtrArray *uids; + guint32 flags; + guint32 mask; + guint ii; + + folder = camel_store_get_junk (store, NULL); + if (folder == NULL) + return; + + uids = camel_folder_get_uids (folder); + flags = mask = CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_SEEN; + + camel_folder_freeze (folder); + + for (ii = 0; ii < uids->len; ii++) { + const gchar *uid = uids->pdata[ii]; + camel_folder_set_message_flags (folder, uid, flags, mask); + } + + camel_folder_thaw (folder); + + camel_folder_free_uids (folder, uids); +} + +/* Helper for mail_backend_prepare_for_quit_cb() */ +static void +mail_backend_final_sync (CamelStore *store, + gpointer unused, + gpointer user_data) +{ + struct { + EActivity *activity; + gboolean empty_trash; + } *sync_data = user_data; + + /* Reffing the activity delays quitting; the reference count + * acts like a counting semaphore. */ + mail_sync_store ( + store, sync_data->empty_trash, + mail_backend_store_operation_done_cb, + g_object_ref (sync_data->activity)); +} + +/* Helper for mail_backend_prepare_for_quit_cb() */ +static gboolean +mail_backend_poll_to_quit (EActivity *activity) +{ + return mail_msg_active ((guint) -1); +} + +/* Helper for mail_backend_prepare_for_quit_cb() */ +static void +mail_backend_ready_to_quit (EActivity *activity) +{ + mail_session_shutdown (); + emu_free_mail_cache (); + + /* Do this last. It may terminate the process. */ + g_object_unref (activity); +} + +static void +mail_backend_prepare_for_quit_cb (EShell *shell, + EActivity *activity, + EMailBackend *backend) +{ + EAccountList *account_list; + gboolean delete_junk; + gboolean empty_trash; + + struct { + EActivity *activity; + gboolean empty_trash; + } sync_data; + + delete_junk = e_mail_backend_delete_junk_policy_decision (backend); + empty_trash = e_mail_backend_empty_trash_policy_decision (backend); + + camel_application_is_exiting = TRUE; + + account_list = e_get_account_list (); + e_account_list_prune_proxies (account_list); + + mail_vfolder_shutdown (); + + if (delete_junk) + e_mail_store_foreach ( + (GHFunc) mail_backend_delete_junk, backend); + + sync_data.activity = activity; + sync_data.empty_trash = empty_trash; + + e_mail_store_foreach ((GHFunc) mail_backend_final_sync, &sync_data); + + /* Cancel all activities. */ + mail_cancel_all (); + + /* Now we poll until all activities are actually cancelled. + * Reffing the activity delays quitting; the reference count + * acts like a counting semaphore. */ + if (mail_msg_active ((guint) -1)) + g_timeout_add_seconds_full ( + G_PRIORITY_DEFAULT, QUIT_POLL_INTERVAL, + (GSourceFunc) mail_backend_poll_to_quit, + g_object_ref (activity), + (GDestroyNotify) mail_backend_ready_to_quit); + else + mail_backend_ready_to_quit (g_object_ref (activity)); +} + +static void +mail_backend_quit_requested_cb (EShell *shell, + EShellBackend *shell_backend) +{ + CamelFolder *folder; + GtkWindow *window; + guint32 unsent; + gint response; + + window = e_shell_get_active_window (shell); + + /* We can quit immediately if offline. */ + if (!e_shell_get_online (shell)) + return; + + /* Check Outbox for any unsent messages. */ + + folder = e_mail_local_get_folder (E_MAIL_FOLDER_OUTBOX); + if (folder == NULL) + return; + + if (camel_object_get ( + folder, NULL, CAMEL_FOLDER_VISIBLE, &unsent, 0) != 0) + return; + + if (unsent == 0) + return; + + response = e_alert_run_dialog_for_args ( + window, "mail:exit-unsaved", NULL); + + if (response == GTK_RESPONSE_YES) + return; + + e_shell_cancel_quit (shell); +} + +static void +mail_backend_constructed (GObject *object) +{ + EShell *shell; + EShellBackend *shell_backend; + const gchar *data_dir; + + shell_backend = E_SHELL_BACKEND (object); + shell = e_shell_backend_get_shell (shell_backend); + + /* This also initializes Camel, so it needs to happen early. */ + mail_session_init (shell_backend); + + g_signal_connect ( + shell, "notify::online", + G_CALLBACK (mail_backend_notify_online_cb), + shell_backend); + + g_signal_connect ( + shell, "prepare-for-offline", + G_CALLBACK (mail_backend_prepare_for_offline_cb), + shell_backend); + + g_signal_connect ( + shell, "prepare-for-online", + G_CALLBACK (mail_backend_prepare_for_online_cb), + shell_backend); + + g_signal_connect ( + shell, "prepare-for-quit", + G_CALLBACK (mail_backend_prepare_for_quit_cb), + shell_backend); + + g_signal_connect ( + shell, "quit-requested", + G_CALLBACK (mail_backend_quit_requested_cb), + shell_backend); + + mail_config_init (); + mail_msg_init (); + + data_dir = e_shell_backend_get_data_dir (shell_backend); + e_mail_store_init (data_dir); +} + +static void +mail_backend_class_init (EMailBackendClass *class) +{ + GObjectClass *object_class; + EShellBackendClass *shell_backend_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EMailBackendPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->constructed = mail_backend_constructed; + + shell_backend_class = E_SHELL_BACKEND_CLASS (class); + shell_backend_class->migrate = e_mail_migrate; +} + +static void +mail_backend_init (EMailBackend *backend) +{ + backend->priv = E_MAIL_BACKEND_GET_PRIVATE (backend); +} + +GType +e_mail_backend_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EMailBackendClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) mail_backend_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EMailBackend), + 0, /* n_preallocs */ + (GInstanceInitFunc) mail_backend_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + E_TYPE_SHELL_BACKEND, "EMailBackend", &type_info, + G_TYPE_FLAG_ABSTRACT); + } + + return type; +} + +gboolean +e_mail_backend_delete_junk_policy_decision (EMailBackend *backend) +{ + EMailBackendClass *class; + + g_return_val_if_fail (E_IS_MAIL_BACKEND (backend), FALSE); + + class = E_MAIL_BACKEND_GET_CLASS (backend); + if (class->delete_junk_policy_decision == NULL) + return FALSE; + + return class->delete_junk_policy_decision (backend); +} + +gboolean +e_mail_backend_empty_trash_policy_decision (EMailBackend *backend) +{ + EMailBackendClass *class; + + g_return_val_if_fail (E_IS_MAIL_BACKEND (backend), FALSE); + + class = E_MAIL_BACKEND_GET_CLASS (backend); + if (class->empty_trash_policy_decision == NULL) + return FALSE; + + return class->empty_trash_policy_decision (backend); +} diff --git a/mail/e-mail-backend.h b/mail/e-mail-backend.h new file mode 100644 index 0000000000..0d2dc2d0fd --- /dev/null +++ b/mail/e-mail-backend.h @@ -0,0 +1,79 @@ +/* + * e-mail-backend.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +/* This is an abstract EShellBackend subclass that integrates + * with libevolution-mail. It serves as a common base class + * for Evolution's mail module and Anjal. */ + +#ifndef E_MAIL_BACKEND_H +#define E_MAIL_BACKEND_H + +#include <shell/e-shell-backend.h> + +/* Standard GObject macros */ +#define E_TYPE_MAIL_BACKEND \ + (e_mail_backend_get_type ()) +#define E_MAIL_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_MAIL_BACKEND, EMailBackend)) +#define E_MAIL_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_MAIL_BACKEND, EMailBackendClass)) +#define E_IS_MAIL_BACKEND(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_MAIL_BACKEND)) +#define E_IS_MAIL_BACKEND_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_MAIL_BACKEND)) +#define E_MAIL_BACKEND_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_MAIL_BACKEND, EMailBackendClass)) + +G_BEGIN_DECLS + +typedef struct _EMailBackend EMailBackend; +typedef struct _EMailBackendClass EMailBackendClass; +typedef struct _EMailBackendPrivate EMailBackendPrivate; + +struct _EMailBackend { + EShellBackend parent; + EMailBackendPrivate *priv; +}; + +struct _EMailBackendClass { + EShellBackendClass parent_class; + + /* Methods */ + gboolean (*delete_junk_policy_decision) + (EMailBackend *backend); + gboolean (*empty_trash_policy_decision) + (EMailBackend *backend); +}; + +GType e_mail_backend_get_type (void); +gboolean e_mail_backend_delete_junk_policy_decision + (EMailBackend *backend); +gboolean e_mail_backend_empty_trash_policy_decision + (EMailBackend *backend); + +G_END_DECLS + +#endif /* E_MAIL_BACKEND_H */ diff --git a/modules/mail/e-mail-shell-backend.c b/modules/mail/e-mail-shell-backend.c index 47e00b7591..b166084f5d 100644 --- a/modules/mail/e-mail-shell-backend.c +++ b/modules/mail/e-mail-shell-backend.c @@ -29,7 +29,6 @@ #include "e-util/e-account-utils.h" #include "e-util/e-binding.h" -#include "e-util/e-alert-dialog.h" #include "e-util/e-import.h" #include "e-util/e-util.h" #include "shell/e-shell.h" @@ -42,8 +41,6 @@ #include "e-mail-shell-view.h" #include "e-mail-browser.h" -#include "e-mail-local.h" -#include "e-mail-migrate.h" #include "e-mail-reader.h" #include "e-mail-store.h" #include "em-account-editor.h" @@ -71,18 +68,15 @@ ((obj), E_TYPE_MAIL_SHELL_BACKEND, EMailShellBackendPrivate)) #define BACKEND_NAME "mail" -#define QUIT_POLL_INTERVAL 1 /* seconds */ struct _EMailShellBackendPrivate { gint mail_sync_in_progress; - guint mail_sync_timeout_source_id; + guint mail_sync_source_id; }; static gpointer parent_class; static GType mail_shell_backend_type; -extern gint camel_application_is_exiting; - static void mail_shell_backend_init_importers (void) { @@ -103,7 +97,7 @@ mail_shell_backend_init_importers (void) static void mail_shell_backend_mail_icon_cb (EShellWindow *shell_window, - const gchar *icon_name) + const gchar *icon_name) { GtkAction *action; @@ -249,25 +243,29 @@ static void mail_shell_backend_sync_store_cb (CamelStore *store, EMailShellBackend *mail_shell_backend) { - if (!camel_application_is_exiting) { - mail_shell_backend->priv->mail_sync_in_progress++; - mail_sync_store ( - store, FALSE, - mail_shell_backend_sync_store_done_cb, - mail_shell_backend); - } + mail_shell_backend->priv->mail_sync_in_progress++; + + mail_sync_store ( + store, FALSE, + mail_shell_backend_sync_store_done_cb, + mail_shell_backend); } static gboolean mail_shell_backend_mail_sync (EMailShellBackend *mail_shell_backend) { - if (camel_application_is_exiting) - return FALSE; + EShell *shell; + EShellBackend *shell_backend; - if (mail_shell_backend->priv->mail_sync_in_progress) + shell_backend = E_SHELL_BACKEND (mail_shell_backend); + shell = e_shell_backend_get_shell (shell_backend); + + /* Obviously we can only sync in online mode. */ + if (!e_shell_get_online (shell)) goto exit; - if (session == NULL || !camel_session_is_online (session)) + /* If a sync is still in progress, skip this round. */ + if (mail_shell_backend->priv->mail_sync_in_progress) goto exit; e_mail_store_foreach ( @@ -275,18 +273,7 @@ mail_shell_backend_mail_sync (EMailShellBackend *mail_shell_backend) mail_shell_backend); exit: - return !camel_application_is_exiting; -} - -static void -mail_shell_backend_notify_online_cb (EShell *shell, - GParamSpec *pspec, - EShellBackend *shell_backend) -{ - gboolean online; - - online = e_shell_get_online (shell); - camel_session_set_online (session, online); + return TRUE; } static void @@ -385,309 +372,26 @@ mail_shell_backend_handle_uri_cb (EShell *shell, return handled; } -/* Helper for mail_shell_backend_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_backend_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_backend_prepare_for_offline_cb (EShell *shell, - EActivity *activity, - EMailShellBackend *mail_shell_backend) -{ - gboolean synchronize = FALSE; - - if (e_shell_get_network_available (shell)) - synchronize = em_utils_prompt_user ( - e_shell_get_active_window (shell), NULL, - "mail:ask-quick-offline", NULL); - - if (!synchronize) { - mail_cancel_all (); - camel_session_set_network_state (session, FALSE); - } - - e_mail_store_foreach ( - (GHFunc) mail_shell_store_prepare_for_offline_cb, activity); -} - -/* Helper for mail_shell_backend_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_backend_prepare_for_online_cb (EShell *shell, - EActivity *activity, - EMailShellBackend *mail_shell_backend) -{ - camel_session_set_online (session, TRUE); - - e_mail_store_foreach ( - (GHFunc) mail_shell_store_prepare_for_online_cb, activity); -} - -/* Helper for mail_shell_backend_prepare_for_quit_cb() */ -static void -mail_shell_backend_empty_junk (CamelStore *store, - gpointer opaque_store_info, - EMailShellBackend *mail_shell_backend) -{ - CamelFolder *folder; - GPtrArray *uids; - guint32 flags; - guint32 mask; - guint ii; - - folder = camel_store_get_junk (store, NULL); - if (folder == NULL) - return; - - uids = camel_folder_get_uids (folder); - flags = mask = CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_SEEN; - - camel_folder_freeze (folder); - - for (ii = 0; ii < uids->len; ii++) { - const gchar *uid = uids->pdata[ii]; - camel_folder_set_message_flags (folder, uid, flags, mask); - } - - camel_folder_thaw (folder); - - camel_folder_free_uids (folder, uids); -} - -/* Helper for mail_shell_backend_final_sync() */ -static void -mail_shell_backend_final_sync_done_cb (CamelStore *store, - gpointer user_data) -{ - g_object_unref (E_ACTIVITY (user_data)); -} - -/* Helper for mail_shell_backend_prepare_for_quit_cb() */ -static void -mail_shell_backend_final_sync (CamelStore *store, - gpointer opaque_store_info, - gpointer user_data) -{ - struct { - EActivity *activity; - gboolean empty_trash; - } *sync_data = user_data; - - /* Reffing the activity delays quitting; the reference count - * acts like a counting semaphore. */ - mail_sync_store ( - store, sync_data->empty_trash, - mail_shell_backend_final_sync_done_cb, - g_object_ref (sync_data->activity)); -} - -/* Helper for mail_shell_backend_prepare_for_quit_cb() */ -static gboolean -mail_shell_backend_poll_to_quit (EActivity *activity) -{ - return mail_msg_active ((guint) -1); -} - -/* Helper for mail_shell_backend_prepare_for_quit_cb() */ -static void -mail_shell_backend_ready_to_quit (EActivity *activity) -{ - mail_session_shutdown (); - g_object_unref (activity); - emu_free_mail_cache (); -} - static void mail_shell_backend_prepare_for_quit_cb (EShell *shell, EActivity *activity, - EMailShellBackend *mail_shell_backend) + EShellBackend *shell_backend) { - EShellSettings *shell_settings; - EAccountList *account_list; - GConfClient *client; - const gchar *key; - gboolean empty_junk; - gboolean empty_trash; - gint empty_date; - gint empty_days; - gint now; - GError *error = NULL; - - struct { - EActivity *activity; - gboolean empty_trash; - } sync_data; - - client = e_shell_get_gconf_client (shell); - shell_settings = e_shell_get_shell_settings (shell); - - camel_application_is_exiting = TRUE; - now = time (NULL) / 60 / 60 / 24; - - account_list = e_get_account_list (); - e_account_list_prune_proxies (account_list); - - mail_vfolder_shutdown (); - - empty_junk = e_shell_settings_get_boolean ( - shell_settings, "mail-empty-junk-on-exit"); - - empty_trash = e_shell_settings_get_boolean ( - shell_settings, "mail-empty-trash-on-exit"); - - /* XXX No EShellSettings properties for these keys. */ - - empty_date = empty_days = 0; - - if (empty_junk) { - key = "/apps/evolution/mail/junk/empty_on_exit_days"; - empty_days = gconf_client_get_int (client, key, &error); - if (error != NULL) { - g_warning ("%s", error->message); - g_clear_error (&error); - empty_trash = FALSE; - } - } - - if (empty_junk) { - key = "/apps/evolution/mail/junk/empty_date"; - empty_date = gconf_client_get_int (client, key, &error); - if (error != NULL) { - g_warning ("%s", error->message); - g_clear_error (&error); - empty_trash = FALSE; - } - } - - empty_junk &= (empty_days = 0) || (empty_date + empty_days <= now); - - if (empty_junk) { - e_mail_store_foreach ( - (GHFunc) mail_shell_backend_empty_junk, - mail_shell_backend); - - key = "/apps/evolution/mail/junk/empty_date"; - gconf_client_set_int (client, key, now, NULL); - } - - empty_date = empty_days = 0; - - if (empty_trash) { - key = "/apps/evolution/mail/trash/empty_on_exit_days"; - empty_days = gconf_client_get_int (client, key, &error); - if (error != NULL) { - g_warning ("%s", error->message); - g_clear_error (&error); - empty_trash = FALSE; - } - } - - if (empty_trash) { - key = "/apps/evolution/mail/trash/empty_date"; - empty_date = gconf_client_get_int (client, key, &error); - if (error != NULL) { - g_warning ("%s", error->message); - g_clear_error (&error); - empty_trash = FALSE; - } - } - - empty_trash &= (empty_days == 0) || (empty_date + empty_days <= now); - - sync_data.activity = activity; - sync_data.empty_trash = empty_trash; + EMailShellBackendPrivate *priv; - e_mail_store_foreach ( - (GHFunc) mail_shell_backend_final_sync, &sync_data); + priv = E_MAIL_SHELL_BACKEND_GET_PRIVATE (shell_backend); - if (empty_trash) { - key = "/apps/evolution/mail/trash/empty_date"; - gconf_client_set_int (client, key, now, NULL); + /* Prevent a sync from starting while trying to shutdown. */ + if (priv->mail_sync_source_id > 0) { + g_source_remove (priv->mail_sync_source_id); + priv->mail_sync_source_id = 0; } - - /* Cancel all activities. */ - mail_cancel_all (); - - /* Now we poll until all activities are actually cancelled. - * Reffing the activity delays quitting; the reference count - * acts like a counting semaphore. */ - if (mail_msg_active ((guint) -1)) - g_timeout_add_seconds_full ( - G_PRIORITY_DEFAULT, QUIT_POLL_INTERVAL, - (GSourceFunc) mail_shell_backend_poll_to_quit, - g_object_ref (activity), - (GDestroyNotify) mail_shell_backend_ready_to_quit); - else - mail_shell_backend_ready_to_quit (g_object_ref (activity)); -} - -static void -mail_shell_backend_quit_requested_cb (EShell *shell, - EShellBackend *shell_backend) -{ - CamelFolder *folder; - guint32 unsent; - gint response; - - /* We can quit immediately if offline. */ - if (!camel_session_is_online (session)) - return; - - /* Check Outbox for any unsent messages. */ - - folder = e_mail_local_get_folder (E_MAIL_FOLDER_OUTBOX); - if (folder == NULL) - return; - - if (camel_object_get ( - folder, NULL, CAMEL_FOLDER_VISIBLE, &unsent, 0) != 0) - return; - - if (unsent == 0) - return; - - response = e_alert_run_dialog_for_args (e_shell_get_active_window (shell), "mail:exit-unsaved", NULL); - - if (response == GTK_RESPONSE_YES) - return; - - e_shell_cancel_quit (shell); } static void mail_shell_backend_send_receive_cb (EShell *shell, - GtkWindow *parent, - EShellBackend *shell_backend) + GtkWindow *parent, + EShellBackend *shell_backend) { em_utils_clear_get_password_canceled_accounts_flag (); mail_send_receive (parent); @@ -695,7 +399,7 @@ mail_shell_backend_send_receive_cb (EShell *shell, static void mail_shell_backend_window_weak_notify_cb (EShell *shell, - GObject *where_the_object_was) + GObject *where_the_object_was) { g_signal_handlers_disconnect_by_func ( shell, mail_shell_backend_mail_icon_cb, @@ -704,8 +408,8 @@ mail_shell_backend_window_weak_notify_cb (EShell *shell, static void mail_shell_backend_window_created_cb (EShell *shell, - GtkWindow *window, - EShellBackend *shell_backend) + GtkWindow *window, + EShellBackend *shell_backend) { EShellSettings *shell_settings; static gboolean first_time = TRUE; @@ -838,15 +542,14 @@ mail_shell_backend_constructed (GObject *object) EMailShellBackendPrivate *priv; EShell *shell; EShellBackend *shell_backend; - const gchar *data_dir; priv = E_MAIL_SHELL_BACKEND_GET_PRIVATE (object); shell_backend = E_SHELL_BACKEND (object); shell = e_shell_backend_get_shell (shell_backend); - /* This also initializes Camel, so it needs to happen early. */ - mail_session_init (shell_backend); + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (parent_class)->constructed (object); /* Register format types for EMFormatHook. */ em_format_hook_register_type (em_format_get_type ()); @@ -859,36 +562,16 @@ mail_shell_backend_constructed (GObject *object) mail_shell_backend_init_importers (); g_signal_connect ( - shell, "notify::online", - G_CALLBACK (mail_shell_backend_notify_online_cb), - shell_backend); - - g_signal_connect ( shell, "handle-uri", G_CALLBACK (mail_shell_backend_handle_uri_cb), shell_backend); g_signal_connect ( - shell, "prepare-for-offline", - G_CALLBACK (mail_shell_backend_prepare_for_offline_cb), - shell_backend); - - g_signal_connect ( - shell, "prepare-for-online", - G_CALLBACK (mail_shell_backend_prepare_for_online_cb), - shell_backend); - - g_signal_connect ( shell, "prepare-for-quit", G_CALLBACK (mail_shell_backend_prepare_for_quit_cb), shell_backend); g_signal_connect ( - shell, "quit-requested", - G_CALLBACK (mail_shell_backend_quit_requested_cb), - shell_backend); - - g_signal_connect ( shell, "send-receive", G_CALLBACK (mail_shell_backend_send_receive_cb), shell_backend); @@ -910,12 +593,6 @@ mail_shell_backend_constructed (GObject *object) mail_folder_cache_get_default (), "folder-changed", G_CALLBACK (folder_changed_cb), shell); - mail_config_init (); - mail_msg_init (); - - data_dir = e_shell_backend_get_data_dir (shell_backend); - e_mail_store_init (data_dir); - e_mail_shell_settings_init (shell); /* Initialize preferences after the main loop starts so @@ -947,17 +624,132 @@ mail_shell_backend_start (EShellBackend *shell_backend) mail_autoreceive_init (shell_backend, session); if (g_getenv ("CAMEL_FLUSH_CHANGES") != NULL) - priv->mail_sync_timeout_source_id = g_timeout_add_seconds ( + priv->mail_sync_source_id = g_timeout_add_seconds ( mail_config_get_sync_timeout (), (GSourceFunc) mail_shell_backend_mail_sync, shell_backend); } +static gboolean +mail_shell_backend_delete_junk_policy_decision (EMailBackend *backend) +{ + EShell *shell; + EShellSettings *shell_settings; + GConfClient *client; + const gchar *key; + gboolean delete_junk; + gint empty_date; + gint empty_days; + gint now; + GError *error = NULL; + + shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend)); + + client = e_shell_get_gconf_client (shell); + shell_settings = e_shell_get_shell_settings (shell); + + now = time (NULL) / 60 / 60 / 24; + + delete_junk = e_shell_settings_get_boolean ( + shell_settings, "mail-empty-junk-on-exit"); + + /* XXX No EShellSettings properties for these keys. */ + + empty_date = empty_days = 0; + + if (delete_junk) { + key = "/apps/evolution/mail/junk/empty_on_exit_days"; + empty_days = gconf_client_get_int (client, key, &error); + if (error != NULL) { + g_warning ("%s", error->message); + g_error_free (error); + return FALSE; + } + } + + if (delete_junk) { + key = "/apps/evolution/mail/junk/empty_date"; + empty_date = gconf_client_get_int (client, key, &error); + if (error != NULL) { + g_warning ("%s", error->message); + g_error_free (error); + return FALSE; + } + } + + delete_junk &= (empty_days == 0) || (empty_date + empty_days <= now); + + if (delete_junk) { + key = "/apps/evolution/mail/junk/empty_date"; + gconf_client_set_int (client, key, now, NULL); + } + + return delete_junk; +} + +static gboolean +mail_shell_backend_empty_trash_policy_decision (EMailBackend *backend) +{ + EShell *shell; + EShellSettings *shell_settings; + GConfClient *client; + const gchar *key; + gboolean empty_trash; + gint empty_date; + gint empty_days; + gint now; + GError *error = NULL; + + shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend)); + + client = e_shell_get_gconf_client (shell); + shell_settings = e_shell_get_shell_settings (shell); + + now = time (NULL) / 60 / 60 / 24; + + empty_trash = e_shell_settings_get_boolean ( + shell_settings, "mail-empty-trash-on-exit"); + + /* XXX No EShellSettings properties for these keys. */ + + empty_date = empty_days = 0; + + if (empty_trash) { + key = "/apps/evolution/mail/trash/empty_on_exit_days"; + empty_days = gconf_client_get_int (client, key, &error); + if (error != NULL) { + g_warning ("%s", error->message); + g_error_free (error); + return FALSE; + } + } + + if (empty_trash) { + key = "/apps/evolution/mail/trash/empty_date"; + empty_date = gconf_client_get_int (client, key, &error); + if (error != NULL) { + g_warning ("%s", error->message); + g_error_free (error); + return FALSE; + } + } + + empty_trash &= (empty_days == 0) || (empty_date + empty_days <= now); + + if (empty_trash) { + key = "/apps/evolution/mail/trash/empty_date"; + gconf_client_set_int (client, key, now, NULL); + } + + return empty_trash; +} + static void mail_shell_backend_class_init (EMailShellBackendClass *class) { GObjectClass *object_class; EShellBackendClass *shell_backend_class; + EMailBackendClass *mail_backend_class; parent_class = g_type_class_peek_parent (class); g_type_class_add_private (class, sizeof (EMailShellBackendPrivate)); @@ -973,7 +765,12 @@ mail_shell_backend_class_init (EMailShellBackendClass *class) shell_backend_class->sort_order = 200; shell_backend_class->preferences_page = "mail-accounts"; shell_backend_class->start = mail_shell_backend_start; - shell_backend_class->migrate = e_mail_migrate; + + mail_backend_class = E_MAIL_BACKEND_CLASS (class); + mail_backend_class->delete_junk_policy_decision = + mail_shell_backend_delete_junk_policy_decision; + mail_backend_class->empty_trash_policy_decision = + mail_shell_backend_empty_trash_policy_decision; } static void @@ -1006,7 +803,7 @@ e_mail_shell_backend_register_type (GTypeModule *type_module) }; mail_shell_backend_type = g_type_module_register_type ( - type_module, E_TYPE_SHELL_BACKEND, + type_module, E_TYPE_MAIL_BACKEND, "EMailShellBackend", &type_info, 0); } diff --git a/modules/mail/e-mail-shell-backend.h b/modules/mail/e-mail-shell-backend.h index 73ef10e75b..36f4064e68 100644 --- a/modules/mail/e-mail-shell-backend.h +++ b/modules/mail/e-mail-shell-backend.h @@ -22,7 +22,7 @@ #ifndef E_MAIL_SHELL_BACKEND_H #define E_MAIL_SHELL_BACKEND_H -#include <shell/e-shell-backend.h> +#include <mail/e-mail-backend.h> #include <camel/camel-folder.h> #include <camel/camel-store.h> @@ -55,12 +55,12 @@ typedef struct _EMailShellBackendClass EMailShellBackendClass; typedef struct _EMailShellBackendPrivate EMailShellBackendPrivate; struct _EMailShellBackend { - EShellBackend parent; + EMailBackend parent; EMailShellBackendPrivate *priv; }; struct _EMailShellBackendClass { - EShellBackendClass parent_class; + EMailBackendClass parent_class; }; GType e_mail_shell_backend_get_type (void); |