diff options
-rw-r--r-- | plugins/mail-to-task/mail-to-task.c | 41 | ||||
-rw-r--r-- | widgets/misc/e-attachment-store.c | 183 | ||||
-rw-r--r-- | widgets/misc/e-attachment-store.h | 12 |
3 files changed, 193 insertions, 43 deletions
diff --git a/plugins/mail-to-task/mail-to-task.c b/plugins/mail-to-task/mail-to-task.c index 5c373d86c1..a90731e2fc 100644 --- a/plugins/mail-to-task/mail-to-task.c +++ b/plugins/mail-to-task/mail-to-task.c @@ -262,7 +262,7 @@ set_organizer (ECalComponent *comp) } static void -attachment_load_finished (EAttachment *attachment, +attachment_load_finished (EAttachmentStore *store, GAsyncResult *result, gpointer user_data) { @@ -273,7 +273,7 @@ attachment_load_finished (EAttachment *attachment, /* XXX Should be no need to check for error here. * This is just to reset state in the EAttachment. */ - e_attachment_load_finish (attachment, result, NULL); + e_attachment_store_load_finish (store, result, NULL); status->done = TRUE; } @@ -307,7 +307,8 @@ set_attachments (ECal *client, ECalComponent *comp, CamelMimeMessage *message) CamelDataWrapper *content; CamelMultipart *multipart; GFile *destination; - GSList *list = NULL; + GList *attachment_list = NULL; + GSList *uri_list = NULL; const gchar *comp_uid = NULL; const gchar *local_store; gint ii, n_parts; @@ -339,28 +340,30 @@ set_attachments (ECal *client, ECalComponent *comp, CamelMimeMessage *message) store = E_ATTACHMENT_STORE (e_attachment_store_new ()); for (ii = 1; ii < n_parts; ii++) { - CamelMimePart *mime_part; EAttachment *attachment; - - status.done = FALSE; + CamelMimePart *mime_part; attachment = e_attachment_new (); mime_part = camel_multipart_get_part (multipart, ii); e_attachment_set_mime_part (attachment, mime_part); - e_attachment_load_async ( - attachment, (GAsyncReadyCallback) - attachment_load_finished, &status); + attachment_list = g_list_append (attachment_list, attachment); + } + + status.done = FALSE; - /* Loading should be instantaneous since we already have - * the full content, but we still have to crank the main - * loop until the callback gets triggered. */ - while (!status.done) - gtk_main_iteration (); + e_attachment_store_load_async ( + store, attachment_list, (GAsyncReadyCallback) + attachment_load_finished, &status); - e_attachment_store_add_attachment (store, attachment); - g_object_unref (attachment); - } + /* Loading should be instantaneous since we already have + * the full content, but we still have to crank the main + * loop until the callback gets triggered. */ + while (!status.done) + gtk_main_iteration (); + + g_list_foreach (attachment_list, (GFunc) g_object_unref, NULL); + g_list_free (attachment_list); status.uris = NULL; status.done = FALSE; @@ -378,14 +381,14 @@ set_attachments (ECal *client, ECalComponent *comp, CamelMimeMessage *message) /* Transfer the URI strings to the GSList. */ for (ii = 0; status.uris[ii] != NULL; ii++) { - list = g_slist_prepend (list, status.uris[ii]); + uri_list = g_slist_prepend (uri_list, status.uris[ii]); status.uris[ii] = NULL; } g_free (status.uris); /* XXX Does this take ownership of the list? */ - e_cal_component_set_attachment_list (comp, list); + e_cal_component_set_attachment_list (comp, uri_list); g_object_unref (destination); g_object_unref (store); diff --git a/widgets/misc/e-attachment-store.c b/widgets/misc/e-attachment-store.c index b5f659cd33..d3db89daf8 100644 --- a/widgets/misc/e-attachment-store.c +++ b/widgets/misc/e-attachment-store.c @@ -649,23 +649,6 @@ e_attachment_store_run_save_dialog (EAttachmentStore *store, return destination; } -/***************** e_attachment_store_add_mime_parts_async() *****************/ - -void -e_attachment_store_add_mime_parts_async (EAttachmentStore *store, - GList *mime_parts, - GAsyncReadyCallback callback, - gpointer user_data) -{ -} - -gboolean -e_attachment_store_add_mime_parts_finish (EAttachmentStore *store, - GAsyncResult *result, - GError **error) -{ -} - /******************** e_attachment_store_get_uris_async() ********************/ typedef struct _UriContext UriContext; @@ -921,6 +904,172 @@ e_attachment_store_get_uris_finish (EAttachmentStore *store, return uris; } +/********************** e_attachment_store_load_async() **********************/ + +typedef struct _LoadContext LoadContext; + +struct _LoadContext { + GSimpleAsyncResult *simple; + GList *attachment_list; + GError *error; +}; + +static LoadContext * +attachment_store_load_context_new (EAttachmentStore *store, + GList *attachment_list, + GAsyncReadyCallback callback, + gpointer user_data) +{ + LoadContext *load_context; + GSimpleAsyncResult *simple; + + simple = g_simple_async_result_new ( + G_OBJECT (store), callback, user_data, + e_attachment_store_load_async); + + load_context = g_slice_new0 (LoadContext); + load_context->simple = simple; + load_context->attachment_list = g_list_copy (attachment_list); + + g_list_foreach ( + load_context->attachment_list, + (GFunc) g_object_ref, NULL); + + return load_context; +} + +static void +attachment_store_load_context_free (LoadContext *load_context) +{ + /* Do not free the GSimpleAsyncResult. */ + + /* The attachment list should be empty now. */ + g_warn_if_fail (load_context->attachment_list == NULL); + + /* So should the error. */ + g_warn_if_fail (load_context->error == NULL); + + g_slice_free (LoadContext, load_context); +} + +static void +attachment_store_load_ready_cb (EAttachment *attachment, + GAsyncResult *result, + LoadContext *load_context) +{ + GSimpleAsyncResult *simple; + GError *error = NULL; + + e_attachment_load_finish (attachment, result, &error); + + /* Remove the attachment from the list. */ + load_context->attachment_list = g_list_remove ( + load_context->attachment_list, attachment); + g_object_unref (attachment); + + if (error != NULL) { + /* If this is the first error, cancel the other jobs. */ + if (load_context->error == NULL) { + g_propagate_error (&load_context->error, error); + g_list_foreach ( + load_context->attachment_list, + (GFunc) e_attachment_cancel, NULL); + error = NULL; + + /* Otherwise, we can only report back one error. So if + * this is something other than cancellation, dump it to + * the terminal. */ + } else if (!g_error_matches ( + error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning ("%s", error->message); + } + + if (error != NULL) + g_error_free (error); + + /* If there's still jobs running, let them finish. */ + if (load_context->attachment_list != NULL) + return; + + /* Steal the result. */ + simple = load_context->simple; + load_context->simple = NULL; + + /* And the error. */ + error = load_context->error; + load_context->error = NULL; + + if (error == NULL) + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + else { + g_simple_async_result_set_from_error (simple, error); + g_error_free (error); + } + + g_simple_async_result_complete (simple); + + attachment_store_load_context_free (load_context); +} + +void +e_attachment_store_load_async (EAttachmentStore *store, + GList *attachment_list, + GAsyncReadyCallback callback, + gpointer user_data) +{ + LoadContext *load_context; + GList *iter; + + g_return_if_fail (E_IS_ATTACHMENT_STORE (store)); + g_return_if_fail (callback != NULL); + + load_context = attachment_store_load_context_new ( + store, attachment_list, callback, user_data); + + if (attachment_list == NULL) { + GSimpleAsyncResult *simple; + + /* Steal the result. */ + simple = load_context->simple; + load_context->simple = NULL; + + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + g_simple_async_result_complete (simple); + attachment_store_load_context_free (load_context); + return; + } + + for (iter = attachment_list; iter != NULL; iter = iter->next) { + EAttachment *attachment = E_ATTACHMENT (iter->data); + + e_attachment_store_add_attachment (store, attachment); + + e_attachment_load_async ( + attachment, (GAsyncReadyCallback) + attachment_store_load_ready_cb, + load_context); + } +} + +gboolean +e_attachment_store_load_finish (EAttachmentStore *store, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + gboolean success; + + g_return_val_if_fail (E_IS_ATTACHMENT_STORE (store), FALSE); + g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), 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); + g_object_unref (simple); + + return success; +} + /********************** e_attachment_store_save_async() **********************/ typedef struct _SaveContext SaveContext; diff --git a/widgets/misc/e-attachment-store.h b/widgets/misc/e-attachment-store.h index efe3e16610..07175f151c 100644 --- a/widgets/misc/e-attachment-store.h +++ b/widgets/misc/e-attachment-store.h @@ -109,22 +109,20 @@ GFile * e_attachment_store_run_save_dialog GtkWindow *parent); /* Asynchronous Operations */ -void e_attachment_store_add_mime_parts_async +void e_attachment_store_get_uris_async (EAttachmentStore *store, - GList *mime_parts, + GList *attachment_list, GAsyncReadyCallback callback, gpointer user_data); -gboolean e_attachment_store_add_mime_parts_finish +gchar ** e_attachment_store_get_uris_finish (EAttachmentStore *store, GAsyncResult *result, GError **error); -void e_attachment_store_get_uris_async - (EAttachmentStore *store, +void e_attachment_store_load_async (EAttachmentStore *store, GList *attachment_list, GAsyncReadyCallback callback, gpointer user_data); -gchar ** e_attachment_store_get_uris_finish - (EAttachmentStore *store, +gboolean e_attachment_store_load_finish (EAttachmentStore *store, GAsyncResult *result, GError **error); void e_attachment_store_save_async (EAttachmentStore *store, |