aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2010-08-31 02:23:33 +0800
committerMatthew Barnes <mbarnes@redhat.com>2010-08-31 02:26:00 +0800
commit035fbcd84177cf592a48e41ca0ca7689aaaa9d17 (patch)
treeff895767b9b3f55ae67fe0aa764102e526c85e41
parent680c58a7660020c614690421ff0e37ee55b2c9aa (diff)
downloadgsoc2013-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.c133
-rw-r--r--composer/e-msg-composer.c34
-rw-r--r--composer/e-msg-composer.h6
-rw-r--r--mail/em-composer-utils.c49
-rw-r--r--plugins/templates/templates.c28
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);