[evolution] Composer autosave cleanups.



commit 035fbcd84177cf592a48e41ca0ca7689aaaa9d17
Author: Matthew Barnes <mbarnes redhat com>
Date:   Mon Aug 30 14:23:33 2010 -0400

    Composer autosave cleanups.
    
    This simplifies the async autosave logic and improves error handling.
    
    Hoping this will solve bug #616987 but I've yet to reproduce it myself.

 composer/e-composer-autosave.c |  133 ++++++++++++++--------------------------
 composer/e-msg-composer.c      |   34 +++++------
 composer/e-msg-composer.h      |    6 +-
 mail/em-composer-utils.c       |   49 +++++++++++++--
 plugins/templates/templates.c  |   28 ++++++++-
 5 files changed, 136 insertions(+), 114 deletions(-)
---
diff --git a/composer/e-composer-autosave.c b/composer/e-composer-autosave.c
index 8863cf8..82a44d5 100644
--- a/composer/e-composer-autosave.c
+++ b/composer/e-composer-autosave.c
@@ -99,23 +99,30 @@ composer_autosave_state_free (AutosaveState *state)
 }
 
 static gboolean
-composer_autosave_state_open (AutosaveState *state)
+composer_autosave_state_open (AutosaveState *state,
+                              GError **error)
 {
+	const gchar *user_data_dir;
 	gchar *path;
 	gint fd;
 
 	if (state->file != NULL)
 		return TRUE;
 
-	path = g_build_filename (
-		e_get_user_data_dir (), AUTOSAVE_SEED, NULL);
+	user_data_dir = e_get_user_data_dir ();
+	path = g_build_filename (user_data_dir, AUTOSAVE_SEED, NULL);
 
 	/* Since GIO doesn't have support for creating temporary files
 	 * from a template (and in a given directory), we have to use
 	 * g_mkstemp(), which brings a small risk of overwriting another
 	 * autosave file.  The risk is, however, miniscule. */
+	errno = 0;
 	fd = g_mkstemp (path);
 	if (fd == -1) {
+		g_set_error (
+			error, G_FILE_ERROR,
+			g_file_error_from_errno (errno),
+			"%s", g_strerror (errno));
 		g_free (path);
 		return FALSE;
 	}
@@ -317,72 +324,31 @@ e_composer_autosave_unregister (EMsgComposer *composer)
 	g_object_set_data (G_OBJECT (composer), "autosave", NULL);
 }
 
-typedef struct {
-	EMsgComposer *composer;
-	GSimpleAsyncResult *simple;
-	AutosaveState *state;
-
-	/* Transient data */
-	GInputStream *input_stream;
-} AutosaveData;
-
-static void
-autosave_data_free (AutosaveData *data)
-{
-	g_object_unref (data->composer);
-	g_object_unref (data->simple);
-
-	if (data->input_stream != NULL)
-		g_object_unref (data->input_stream);
-
-	g_slice_free (AutosaveData, data);
-}
-
-static gboolean
-autosave_snapshot_check_for_error (AutosaveData *data,
-                                   GError *error)
-{
-	GSimpleAsyncResult *simple;
-
-	if (error == NULL)
-		return FALSE;
-
-	simple = data->simple;
-	g_simple_async_result_set_from_error (simple, error);
-	g_simple_async_result_set_op_res_gboolean (simple, FALSE);
-	g_simple_async_result_complete (simple);
-	g_error_free (error);
-
-	autosave_data_free (data);
-
-	return TRUE;
-}
-
 static void
 autosave_snapshot_splice_cb (GOutputStream *output_stream,
                              GAsyncResult *result,
-                             AutosaveData *data)
+                             GSimpleAsyncResult *simple)
 {
-	GSimpleAsyncResult *simple;
 	GError *error = NULL;
 
 	g_output_stream_splice_finish (output_stream, result, &error);
 
-	if (autosave_snapshot_check_for_error (data, error))
-		return;
+	if (error != NULL) {
+		g_simple_async_result_set_from_error (simple, error);
+		g_error_free (error);
+	}
 
-	simple = data->simple;
-	g_simple_async_result_set_op_res_gboolean (simple, TRUE);
 	g_simple_async_result_complete (simple);
-
-	autosave_data_free (data);
+	g_object_unref (simple);
 }
 
 static void
 autosave_snapshot_cb (GFile *file,
                       GAsyncResult *result,
-                      AutosaveData *data)
+                      GSimpleAsyncResult *simple)
 {
+	GObject *object;
+	EMsgComposer *composer;
 	CamelMimeMessage *message;
 	GFileOutputStream *output_stream;
 	GInputStream *input_stream;
@@ -390,22 +356,26 @@ autosave_snapshot_cb (GFile *file,
 	GByteArray *buffer;
 	GError *error = NULL;
 
+	object = g_async_result_get_source_object (G_ASYNC_RESULT (simple));
+
 	output_stream = g_file_replace_finish (file, result, &error);
 
-	if (autosave_snapshot_check_for_error (data, error))
+	if (error != NULL) {
+		g_simple_async_result_set_from_error (simple, error);
+		g_simple_async_result_complete (simple);
+		g_object_unref (simple);
+		g_error_free (error);
 		return;
+	}
 
 	/* Extract a MIME message from the composer. */
-	message = e_msg_composer_get_message_draft (data->composer);
-	if (message == NULL) {
-		GSimpleAsyncResult *simple;
-
-		/* FIXME Need to set a GError here. */
-		simple = data->simple;
-		g_simple_async_result_set_op_res_gboolean (simple, FALSE);
+	composer = E_MSG_COMPOSER (object);
+	message = e_msg_composer_get_message_draft (composer, &error);
+	if (error != NULL) {
+		g_simple_async_result_set_from_error (simple, error);
 		g_simple_async_result_complete (simple);
 		g_object_unref (output_stream);
-		autosave_data_free (data);
+		g_object_unref (simple);
 		return;
 	}
 
@@ -430,7 +400,6 @@ autosave_snapshot_cb (GFile *file,
 			buffer->data, (gssize) buffer->len,
 			(GDestroyNotify) g_free);
 	g_byte_array_free (buffer, FALSE);
-	data->input_stream = input_stream;
 
 	/* Splice the input and output streams */
 	g_output_stream_splice_async (
@@ -438,9 +407,10 @@ autosave_snapshot_cb (GFile *file,
 		G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
 		G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
 		G_PRIORITY_DEFAULT, NULL, (GAsyncReadyCallback)
-		autosave_snapshot_splice_cb, data);
+		autosave_snapshot_splice_cb, simple);
 
 	g_object_unref (output_stream);
+	g_object_unref (input_stream);
 }
 
 void
@@ -448,48 +418,39 @@ e_composer_autosave_snapshot_async (EMsgComposer *composer,
                                     GAsyncReadyCallback callback,
                                     gpointer user_data)
 {
-	AutosaveData *data;
 	AutosaveState *state;
 	GSimpleAsyncResult *simple;
+	GError *error = NULL;
 
 	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
 
+	state = g_object_get_data (G_OBJECT (composer), "autosave");
+	g_return_if_fail (state != NULL);
+
 	simple = g_simple_async_result_new (
 		G_OBJECT (composer), callback, user_data,
 		e_composer_autosave_snapshot_async);
 
 	/* If the contents are unchanged, exit early. */
 	if (!gtkhtml_editor_get_changed (GTKHTML_EDITOR (composer))) {
-		g_simple_async_result_set_op_res_gboolean (simple, TRUE);
 		g_simple_async_result_complete (simple);
+		g_object_unref (simple);
 		return;
 	}
 
-	state = g_object_get_data (G_OBJECT (composer), "autosave");
-	g_return_if_fail (state != NULL);
-
 	/* Open the autosave file on-demand. */
-	errno = 0;
-	if (!composer_autosave_state_open (state)) {
-		g_simple_async_result_set_error (
-			simple, G_FILE_ERROR,
-			g_file_error_from_errno (errno),
-			"%s", g_strerror (errno));
-		g_simple_async_result_set_op_res_gboolean (simple, FALSE);
+	if (!composer_autosave_state_open (state, &error)) {
+		g_simple_async_result_set_from_error (simple, error);
 		g_simple_async_result_complete (simple);
+		g_object_unref (simple);
 		return;
 	}
 
-	/* Overwrite the file */
-	data = g_slice_new (AutosaveData);
-	data->composer = g_object_ref (composer);
-	data->simple = simple;
-	data->state = state;
-
+	/* Overwrite the file. */
 	g_file_replace_async (
 		state->file, NULL, FALSE, G_FILE_CREATE_PRIVATE,
 		G_PRIORITY_DEFAULT, NULL, (GAsyncReadyCallback)
-		autosave_snapshot_cb, data);
+		autosave_snapshot_cb, simple);
 }
 
 gboolean
@@ -498,17 +459,15 @@ e_composer_autosave_snapshot_finish (EMsgComposer *composer,
                                      GError **error)
 {
 	GSimpleAsyncResult *simple;
-	gboolean success;
 
 	g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), FALSE);
 	g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE);
 	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
 	simple = G_SIMPLE_ASYNC_RESULT (result);
-	success = g_simple_async_result_get_op_res_gboolean (simple);
-	g_simple_async_result_propagate_error (simple, error);
 
-	return success;
+	/* Success is assumed in the absense of a GError. */
+	return !g_simple_async_result_propagate_error (simple, error);
 }
 
 gchar *
diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c
index 9c80a19..6552367 100644
--- a/composer/e-msg-composer.c
+++ b/composer/e-msg-composer.c
@@ -596,7 +596,8 @@ account_hash_algo_to_camel_hash (const gchar *hash_algo)
 static CamelMimeMessage *
 build_message (EMsgComposer *composer,
                gboolean html_content,
-               gboolean save_html_object_data)
+               gboolean save_html_object_data,
+               GError **error)
 {
 	GtkhtmlEditor *editor;
 	EMsgComposerPrivate *p = composer->priv;
@@ -1149,20 +1150,14 @@ exception:
 
 	g_object_unref (new);
 
-	if (!g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
-		e_alert_run_dialog_for_args (
-			(GtkWindow *) composer,
-			"mail-composer:no-build-message",
-			local_error->message, NULL);
-
-	g_error_free (local_error);
-
 	if (recipients) {
 		for (i=0; i<recipients->len; i++)
 			g_free (recipients->pdata[i]);
 		g_ptr_array_free (recipients, TRUE);
 	}
 
+	g_propagate_error (error, local_error);
+
 	return NULL;
 }
 
@@ -3781,7 +3776,8 @@ e_msg_composer_add_inline_image_from_mime_part (EMsgComposer  *composer,
  **/
 CamelMimeMessage *
 e_msg_composer_get_message (EMsgComposer *composer,
-                            gboolean save_html_object_data)
+                            gboolean save_html_object_data,
+                            GError **error)
 {
 	EAttachmentView *view;
 	EAttachmentStore *store;
@@ -3803,7 +3799,9 @@ e_msg_composer_get_message (EMsgComposer *composer,
 	editor = GTKHTML_EDITOR (composer);
 	html_content = gtkhtml_editor_get_html_mode (editor);
 
-	return build_message (composer, html_content, save_html_object_data);
+	return build_message (
+		composer, html_content,
+		save_html_object_data, error);
 }
 
 static gchar *
@@ -3859,7 +3857,8 @@ e_msg_composer_get_message_print (EMsgComposer *composer,
 	editor = GTKHTML_EDITOR (composer);
 	html_content = gtkhtml_editor_get_html_mode (editor);
 
-	msg = build_message (composer, html_content, save_html_object_data);
+	msg = build_message (
+		composer, html_content, save_html_object_data, NULL);
 	if (msg == NULL)
 		return NULL;
 
@@ -3871,7 +3870,8 @@ e_msg_composer_get_message_print (EMsgComposer *composer,
 	flags = msg_composer_get_message_print_helper (
 		temp_composer, html_content);
 
-	msg = build_message (temp_composer, TRUE, save_html_object_data);
+	msg = build_message (
+		temp_composer, TRUE, save_html_object_data, NULL);
 	if (msg != NULL)
 		camel_medium_set_header (
 			CAMEL_MEDIUM (msg), "X-Evolution-Format", flags);
@@ -3883,7 +3883,8 @@ e_msg_composer_get_message_print (EMsgComposer *composer,
 }
 
 CamelMimeMessage *
-e_msg_composer_get_message_draft (EMsgComposer *composer)
+e_msg_composer_get_message_draft (EMsgComposer *composer,
+                                  GError **error)
 {
 	GtkhtmlEditor *editor;
 	EComposerHeaderTable *table;
@@ -3917,7 +3918,7 @@ e_msg_composer_get_message_draft (EMsgComposer *composer)
 	smime_encrypt = gtk_toggle_action_get_active (action);
 	gtk_toggle_action_set_active (action, FALSE);
 
-	msg = build_message (composer, TRUE, TRUE);
+	msg = build_message (composer, TRUE, TRUE, error);
 	if (msg == NULL)
 		return NULL;
 
@@ -3933,9 +3934,6 @@ e_msg_composer_get_message_draft (EMsgComposer *composer)
 	action = GTK_TOGGLE_ACTION (ACTION (SMIME_ENCRYPT));
 	gtk_toggle_action_set_active (action, smime_encrypt);
 
-	if (msg == NULL)
-		return NULL;
-
 	/* Attach account info to the draft. */
 	account = e_composer_header_table_get_account (table);
 	if (account && account->name)
diff --git a/composer/e-msg-composer.h b/composer/e-msg-composer.h
index 5b44e74..4c51929 100644
--- a/composer/e-msg-composer.h
+++ b/composer/e-msg-composer.h
@@ -114,14 +114,16 @@ void		e_msg_composer_add_inline_image_from_mime_part
 						 CamelMimePart *part);
 CamelMimeMessage *
 		e_msg_composer_get_message	(EMsgComposer *composer,
-						 gboolean save_html_object_data);
+						 gboolean save_html_object_data,
+						 GError **error);
 CamelMimeMessage *
 		e_msg_composer_get_message_print
 						(EMsgComposer *composer,
 						 gboolean save_html_object_data);
 CamelMimeMessage *
 		e_msg_composer_get_message_draft
-						(EMsgComposer *composer);
+						(EMsgComposer *composer,
+						 GError **error);
 void		e_msg_composer_show_sig_file	(EMsgComposer *composer);
 
 CamelInternetAddress *
diff --git a/mail/em-composer-utils.c b/mail/em-composer-utils.c
index 137b246..aa2a550 100644
--- a/mail/em-composer-utils.c
+++ b/mail/em-composer-utils.c
@@ -299,6 +299,7 @@ composer_get_message (EMsgComposer *composer, gboolean save_html_object_data)
 	EComposerHeaderTable *table;
 	EComposerHeader *post_to_header;
 	GString *invalid_addrs = NULL;
+	GError *error = NULL;
 
 	gconf = mail_config_get_gconf_client ();
 	table = e_msg_composer_get_header_table (composer);
@@ -469,9 +470,27 @@ composer_get_message (EMsgComposer *composer, gboolean save_html_object_data)
 		goto finished;
 
 	/* actually get the message now, this will sign/encrypt etc */
-	message = e_msg_composer_get_message (composer, save_html_object_data);
-	if (message == NULL)
+	message = e_msg_composer_get_message (
+		composer, save_html_object_data, &error);
+
+	/* Ignore cancellations. */
+	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+		g_warn_if_fail (message == NULL);
+		g_error_free (error);
+		goto finished;
+	}
+
+	if (error != NULL) {
+		g_warn_if_fail (message == NULL);
+		e_alert_run_dialog_for_args (
+			GTK_WINDOW (composer),
+			"mail-composer:no-build-message",
+			error->message, NULL);
+		g_error_free (error);
 		goto finished;
+	}
+
+	g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
 
 	/* Add info about the sending account */
 	account = e_composer_header_table_get_account (table);
@@ -636,6 +655,7 @@ em_utils_composer_save_draft_cb (EMsgComposer *composer)
 	CamelMimeMessage *msg;
 	CamelMessageInfo *info;
 	EAccount *account;
+	GError *error = NULL;
 
 	/* need to get stuff from the composer here, since it could
 	 * get destroyed while we're in mail_msg_wait() a little lower
@@ -646,13 +666,32 @@ em_utils_composer_save_draft_cb (EMsgComposer *composer)
 	local_drafts_folder_uri =
 		e_mail_local_get_folder_uri (E_MAIL_FOLDER_DRAFTS);
 
-	g_object_ref (composer);
-	msg = e_msg_composer_get_message_draft (composer);
+	msg = e_msg_composer_get_message_draft (composer, &error);
+
+	/* Ignore cancellations. */
+	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+		g_warn_if_fail (msg == NULL);
+		g_error_free (error);
+		return;
+	}
+
+	if (error != NULL) {
+		g_warn_if_fail (msg == NULL);
+		e_alert_run_dialog_for_args (
+			GTK_WINDOW (composer),
+			"mail-composer:no-build-message",
+			error->message, NULL);
+		g_error_free (error);
+		return;
+	}
+
+	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (msg));
+
 	table = e_msg_composer_get_header_table (composer);
 	account = e_composer_header_table_get_account (table);
 
 	sdi = g_malloc (sizeof(struct _save_draft_info));
-	sdi->composer = composer;
+	sdi->composer = g_object_ref (composer);
 	sdi->emcs = g_object_get_data (G_OBJECT (composer), "emcs");
 	if (sdi->emcs)
 		emcs_ref (sdi->emcs);
diff --git a/plugins/templates/templates.c b/plugins/templates/templates.c
index 04ac8a5..483d940 100644
--- a/plugins/templates/templates.c
+++ b/plugins/templates/templates.c
@@ -38,6 +38,7 @@
 #include <mail/mail-session.h>
 #include <mail/mail-ops.h>
 #include <mail/message-list.h>
+#include <e-util/e-alert-dialog.h>
 #include <e-util/e-plugin.h>
 #include <e-util/e-util.h>
 #include <shell/e-shell-view.h>
@@ -670,14 +671,37 @@ action_template_cb (GtkAction *action,
 	CamelMessageInfo *info;
 	CamelMimeMessage *msg;
 	CamelFolder *folder;
+	GError *error = NULL;
 
 	/* Get the templates folder and all UIDs of the messages there. */
 	folder = e_mail_local_get_folder (E_MAIL_FOLDER_TEMPLATES);
 
-	msg = e_msg_composer_get_message_draft (composer);
+	msg = e_msg_composer_get_message_draft (composer, &error);
+
+	/* Ignore cancellations. */
+	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+		g_warn_if_fail (msg == NULL);
+		g_error_free (error);
+		return;
+	}
+
+	if (error != NULL) {
+		g_warn_if_fail (msg == NULL);
+		e_alert_run_dialog_for_args (
+			GTK_WINDOW (composer),
+			"mail-composer:no-build-message",
+			error->message, NULL);
+		g_error_free (error);
+		return;
+	}
+
+	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (msg));
+
 	info = camel_message_info_new (NULL);
 
-	/* FIXME: what's the ~0 for? :) */
+	/* The last argument is a bit mask which tells the function
+	 * which flags to modify.  In this case, ~0 means all flags.
+	 * So it clears all the flags and then sets SEEN and DRAFT. */
 	camel_message_info_set_flags (
 		info, CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_DRAFT, ~0);
 



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