[evolution] Add e_attachment_store_load_async().



commit 28589a30975f3e68615ea9eb2086d7d251013563
Author: Matthew Barnes <mbarnes redhat com>
Date:   Thu Nov 19 19:15:37 2009 -0500

    Add e_attachment_store_load_async().
    
    This is a convenience function for adding multiple attachments to a
    store and loading them concurrently.
    
    Also included: e_attachment_store_load_finish()

 plugins/mail-to-task/mail-to-task.c |   41 ++++----
 widgets/misc/e-attachment-store.c   |  183 +++++++++++++++++++++++++++++++---
 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 5c373d8..a90731e 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 b5f659c..d3db89d 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 efe3e16..07175f1 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,



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