[evolution/kill-bonobo] Implement the mail backend's quit strategy.



commit d98dc0105eafd373679625df240cfdf00f8b7cac
Author: Matthew Barnes <mbarnes redhat com>
Date:   Fri Jul 17 11:44:21 2009 -0400

    Implement the mail backend's quit strategy.

 mail/mail-component.c               |  152 +--------------------------
 modules/mail/e-mail-shell-backend.c |  203 +++++++++++++++++++++++++++++++++++
 2 files changed, 204 insertions(+), 151 deletions(-)
---
diff --git a/mail/mail-component.c b/mail/mail-component.c
index 0963a81..3bb6ffb 100644
--- a/mail/mail-component.c
+++ b/mail/mail-component.c
@@ -132,36 +132,6 @@ struct _MailComponentPrivate {
 /* GObject methods.  */
 
 static void
-impl_dispose (GObject *object)
-{
-	MailComponentPrivate *priv = MAIL_COMPONENT (object)->priv;
-
-	if (priv->mail_sync_id) {
-		g_source_remove (priv->mail_sync_id);
-		priv->mail_sync_id = 0;
-	}
-
-	if (priv->activity_handler != NULL) {
-		g_object_unref (priv->activity_handler);
-		priv->activity_handler = NULL;
-	}
-
-	if (priv->search_context != NULL) {
-		g_object_unref (priv->search_context);
-		priv->search_context = NULL;
-	}
-
-	if (priv->local_store != NULL) {
-		camel_object_unref (priv->local_store);
-		priv->local_store = NULL;
-	}
-
-	priv->component_view = NULL;
-
-	(* G_OBJECT_CLASS (parent_class)->dispose) (object);
-}
-
-static void
 impl_finalize (GObject *object)
 {
 	MailComponentPrivate *priv = MAIL_COMPONENT (object)->priv;
@@ -318,124 +288,6 @@ impl_createView (PortableServer_Servant servant,
 	return BONOBO_OBJREF(component_view);
 }
 
-static CORBA_boolean
-impl_requestQuit(PortableServer_Servant servant, CORBA_Environment *ev)
-{
-	/*MailComponent *mc = MAIL_COMPONENT(bonobo_object_from_servant(servant));*/
-	CamelFolder *folder;
-	guint32 unsent;
-
-	if (!e_msg_composer_request_close_all())
-		return FALSE;
-
-	folder = mc_default_folders[MAIL_COMPONENT_FOLDER_OUTBOX].folder;
-	if (folder != NULL
-	    && camel_session_is_online(session)
-	    && camel_object_get(folder, NULL, CAMEL_FOLDER_VISIBLE, &unsent, 0) == 0
-	    && unsent > 0
-	    && e_error_run(NULL, "mail:exit-unsaved", NULL) != GTK_RESPONSE_YES)
-		return FALSE;
-
-	return TRUE;
-}
-
-static void
-mc_quit_sync_done(CamelStore *store, gpointer data)
-{
-	MailComponent *mc = data;
-
-	mc->priv->quit_count--;
-}
-
-static void
-mc_quit_sync(CamelStore *store, struct _store_info *si, MailComponent *mc)
-{
-	mc->priv->quit_count++;
-	mail_sync_store(store, mc->priv->quit_expunge, mc_quit_sync_done, mc);
-}
-
-static void
-mc_quit_delete (CamelStore *store, struct _store_info *si, MailComponent *mc)
-{
-	CamelFolder *folder = camel_store_get_junk (store, NULL);
-
-	if (folder) {
-		GPtrArray *uids;
-		gint i;
-
-		uids =  camel_folder_get_uids (folder);
-		camel_folder_freeze(folder);
-		for (i=0;i<uids->len;i++)
-			camel_folder_set_message_flags(folder, uids->pdata[i], CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_DELETED|CAMEL_MESSAGE_SEEN);
-		camel_folder_thaw(folder);
-		camel_folder_free_uids (folder, uids);
-	}
-}
-
-static CORBA_boolean
-impl_quit(PortableServer_Servant servant, CORBA_Environment *ev)
-{
-	MailComponent *mc = MAIL_COMPONENT(bonobo_object_from_servant(servant));
-	EAccountList *account_list;
-
-	if (mc->priv->quit_state == -1)
-		mc->priv->quit_state = MC_QUIT_START;
-
-	account_list = e_get_account_list ();
-	e_account_list_prune_proxies (account_list);
-
-	switch (mc->priv->quit_state) {
-	case MC_QUIT_START: {
-		gint now = time(NULL)/60/60/24, days;
-		gboolean empty_junk;
-
-		GConfClient *gconf = mail_config_get_gconf_client();
-
-		camel_application_is_exiting = TRUE;
-
-		mail_vfolder_shutdown();
-
-		mc->priv->quit_expunge = gconf_client_get_bool(gconf, "/apps/evolution/mail/trash/empty_on_exit", NULL)
-			&& ((days = gconf_client_get_int(gconf, "/apps/evolution/mail/trash/empty_on_exit_days", NULL)) == 0
-			    || (days + gconf_client_get_int(gconf, "/apps/evolution/mail/trash/empty_date", NULL)) <= now);
-
-		empty_junk = gconf_client_get_bool(gconf, "/apps/evolution/mail/junk/empty_on_exit", NULL)
-			&& ((days = gconf_client_get_int(gconf, "/apps/evolution/mail/junk/empty_on_exit_days", NULL)) == 0
-			    || (days + gconf_client_get_int(gconf, "/apps/evolution/mail/junk/empty_date", NULL)) <= now);
-
-		if (empty_junk) {
-			g_hash_table_foreach(mc->priv->store_hash, (GHFunc)mc_quit_delete, mc);
-			gconf_client_set_int(gconf, "/apps/evolution/mail/junk/empty_date", now, NULL);
-		}
-
-		g_hash_table_foreach(mc->priv->store_hash, (GHFunc)mc_quit_sync, mc);
-
-		if (mc->priv->quit_expunge)
-			gconf_client_set_int(gconf, "/apps/evolution/mail/trash/empty_date", now, NULL);
-
-		mc->priv->quit_state = MC_QUIT_SYNC;
-	}
-		/* Falls through */
-	case MC_QUIT_SYNC:
-		if (mc->priv->quit_count > 0 || mc->priv->mail_sync_in_progress > 0)
-			return FALSE;
-
-		mail_cancel_all();
-		mc->priv->quit_state = MC_QUIT_THREADS;
-
-		/* Falls through */
-	case MC_QUIT_THREADS:
-		/* should we keep cancelling? */
-		if (mail_msg_active((guint)-1))
-			return FALSE;
-
-		mail_session_shutdown ();
-		return TRUE;
-	}
-
-	return TRUE;
-}
-
 /* Initialization.  */
 
 static void
@@ -450,12 +302,10 @@ mail_component_class_init (MailComponentClass *class)
 
 	parent_class = g_type_class_peek_parent (class);
 
-	object_class->dispose  = impl_dispose;
 	object_class->finalize = impl_finalize;
 
 	epv->createView          = impl_createView;
-	epv->requestQuit = impl_requestQuit;
-	epv->quit = impl_quit;
+//	epv->quit = impl_quit;
 //	epv->_get_userCreatableItems = impl__get_userCreatableItems;
 //	epv->requestCreateItem       = impl_requestCreateItem;
 //	epv->handleURI               = impl_handleURI;
diff --git a/modules/mail/e-mail-shell-backend.c b/modules/mail/e-mail-shell-backend.c
index 43a2720..7ebfbea 100644
--- a/modules/mail/e-mail-shell-backend.c
+++ b/modules/mail/e-mail-shell-backend.c
@@ -71,6 +71,7 @@
 	((obj), E_TYPE_MAIL_SHELL_BACKEND, EMailShellBackendPrivate))
 
 #define BACKEND_NAME "mail"
+#define QUIT_POLL_INTERVAL 1  /* seconds */
 
 struct _EMailShellBackendPrivate {
 	gint mail_sync_in_progress;
@@ -472,6 +473,203 @@ mail_shell_backend_prepare_for_online_cb (EShell *shell,
 		(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);
+}
+
+static void
+mail_shell_backend_prepare_for_quit_cb (EShell *shell,
+                                        EActivity *activity,
+                                        EMailShellBackend *mail_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;
+
+	e_mail_store_foreach (
+		(GHFunc) mail_shell_backend_final_sync, &sync_data);
+
+	if (empty_trash) {
+		key = "/apps/evolution/mail/trash/empty_date";
+		gconf_client_set_int (client, key, now, NULL);
+	}
+
+	/* 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)
@@ -642,6 +840,11 @@ mail_shell_backend_constructed (GObject *object)
 		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);



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