diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2010-08-31 02:23:33 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2010-08-31 02:26:00 +0800 |
commit | 035fbcd84177cf592a48e41ca0ca7689aaaa9d17 (patch) | |
tree | ff895767b9b3f55ae67fe0aa764102e526c85e41 | |
parent | 680c58a7660020c614690421ff0e37ee55b2c9aa (diff) | |
download | gsoc2013-evolution-035fbcd84177cf592a48e41ca0ca7689aaaa9d17.tar gsoc2013-evolution-035fbcd84177cf592a48e41ca0ca7689aaaa9d17.tar.gz gsoc2013-evolution-035fbcd84177cf592a48e41ca0ca7689aaaa9d17.tar.bz2 gsoc2013-evolution-035fbcd84177cf592a48e41ca0ca7689aaaa9d17.tar.lz gsoc2013-evolution-035fbcd84177cf592a48e41ca0ca7689aaaa9d17.tar.xz gsoc2013-evolution-035fbcd84177cf592a48e41ca0ca7689aaaa9d17.tar.zst gsoc2013-evolution-035fbcd84177cf592a48e41ca0ca7689aaaa9d17.zip |
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.
-rw-r--r-- | composer/e-composer-autosave.c | 133 | ||||
-rw-r--r-- | composer/e-msg-composer.c | 34 | ||||
-rw-r--r-- | composer/e-msg-composer.h | 6 | ||||
-rw-r--r-- | mail/em-composer-utils.c | 49 | ||||
-rw-r--r-- | 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 8863cf8d2a..82a44d570a 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 9c80a193b9..65523677e9 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 5b44e74ca2..4c51929f06 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 137b246259..aa2a550197 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 04ac8a5748..483d9400eb 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); |