[evolution] Kill more redundant save functions.



commit 5783bb4eb0a6e454fcebb4b87fcbd9bd11f32bdc
Author: Matthew Barnes <mbarnes redhat com>
Date:   Sat Nov 7 16:08:26 2009 -0500

    Kill more redundant save functions.

 mail/em-utils.c                         |  239 -------------------------------
 mail/em-utils.h                         |    3 -
 plugins/itip-formatter/itip-formatter.c |   42 +++++-
 plugins/mail-to-task/mail-to-task.c     |  161 ++++++++++++++-------
 4 files changed, 147 insertions(+), 298 deletions(-)
---
diff --git a/mail/em-utils.c b/mail/em-utils.c
index 0e9742d..0eab5f6 100644
--- a/mail/em-utils.c
+++ b/mail/em-utils.c
@@ -345,245 +345,6 @@ em_filename_make_safe (gchar *string)
 
 /* Saving messages... */
 
-static const gchar *
-emu_save_get_filename_for_part (CamelMimePart *part)
-{
-	const gchar *filename;
-
-	filename = camel_mime_part_get_filename (part);
-	if (filename == NULL) {
-		if (CAMEL_IS_MIME_MESSAGE (part)) {
-			filename = camel_mime_message_get_subject (
-				CAMEL_MIME_MESSAGE (part));
-			if (filename == NULL)
-				filename = _("message");
-		} else
-			filename = _("attachment");
-	}
-
-	return filename;
-}
-
-/**
- * em_utils_save_part:
- * @parent: parent window
- * @prompt: prompt string
- * @part: part to save
- *
- * Saves a mime part to disk (prompting the user for filename).
- **/
-void
-em_utils_save_part (GtkWindow *parent, const gchar *prompt, CamelMimePart *part)
-{
-	GtkWidget *file_chooser;
-	const gchar *utf8_filename;
-	gchar *uri = NULL, *filename;
-
-	g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
-
-	utf8_filename = emu_save_get_filename_for_part (part);
-	filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
-	em_filename_make_safe (filename);
-
-	file_chooser = e_file_get_save_filesel (
-		parent, prompt, filename, GTK_FILE_CHOOSER_ACTION_SAVE);
-
-	if (gtk_dialog_run (GTK_DIALOG (file_chooser)) != GTK_RESPONSE_OK)
-		goto exit;
-
-	uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (file_chooser));
-
-	/* XXX Would be nice to mention _why_ we can't save. */
-	if (!e_file_can_save (GTK_WINDOW (file_chooser), uri)) {
-		g_warning ("Unable to save %s", uri);
-		goto exit;
-	}
-
-	e_file_update_save_path (
-		gtk_file_chooser_get_current_folder_uri (
-		GTK_FILE_CHOOSER (file_chooser)), TRUE);
-
-	mail_save_part (part, uri, NULL, NULL, FALSE);
-
-exit:
-	gtk_widget_destroy (file_chooser);
-	g_free (uri);
-	g_free (filename);
-}
-
-/* It "assigns" to each part its unique file name, based on the appearance.
-   parts contains CamelMimePart, returned value contains gchar *, in same
-   order as parts; resulting list should free data and GSList itself as well.
-*/
-static GSList *
-get_unique_file_names (GSList *parts)
-{
-	GSList *iter;
-	GSList *file_names = NULL;
-
-	if (!parts)
-		return NULL;
-
-	for (iter = parts; iter != NULL; iter = iter->next) {
-		CamelMimePart *part = iter->data;
-		const gchar *utf8_filename;
-		gchar *filename;
-
-		utf8_filename = emu_save_get_filename_for_part (part);
-		filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
-		em_filename_make_safe (filename);
-
-		file_names = g_slist_prepend (file_names, filename);
-	}
-
-	if (file_names) {
-		GSList *sorted_file_names;
-		gint counter = 1;
-		const gchar *last;
-		GCompareFunc cmp_func = (GCompareFunc) strcmp;
-
-		#ifdef G_OS_WIN32
-		cmp_func = (GCompareFunc) g_ascii_strcasecmp;
-		#endif
-
-		/* we prepended, so reverse to make right order */
-		file_names = g_slist_reverse (file_names);
-
-		sorted_file_names = g_slist_sort (g_slist_copy (file_names), cmp_func);
-		last = sorted_file_names->data;
-		for (iter = sorted_file_names->next; iter; iter = iter->next) {
-			gchar *name = iter->data;
-
-			if (name && last && cmp_func (name, last) == 0) {
-				gchar *new_name;
-				gchar *p = strrchr (name, '.');
-				GSList *i2;
-
-				/* if we have an extension, then place number before it (at p is ".ext"),
-				   otherwise just append number in brackets */
-				if (p)
-					new_name = g_strdup_printf ("%.*s(%d)%s", (gint) (p - name), name, counter, p);
-				else
-					new_name = g_strdup_printf ("%s(%d)", name, counter);
-
-				/* we need to find the proper item in unsorted list and replace with new name;
-				   we should always find that item, so no check for leaks */
-				for (i2 = file_names; i2; i2 = i2->next) {
-					if (i2->data == name) {
-						g_free (name);
-						i2->data = new_name;
-						break;
-					}
-				}
-
-				counter++;
-			} else {
-				last = name;
-				counter = 1;
-			}
-		}
-
-		g_slist_free (sorted_file_names);
-	}
-
-	return file_names;
-}
-
-void
-em_utils_save_parts (GtkWindow *parent, const gchar *prompt, GSList *parts)
-{
-	GtkWidget *file_chooser;
-	gchar *path_uri;
-	GSList *iter, *file_names, *iter_file;
-
-	g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
-
-	file_chooser = e_file_get_save_filesel (
-		parent, prompt, NULL, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
-
-	if (gtk_dialog_run (GTK_DIALOG (file_chooser)) != GTK_RESPONSE_OK)
-		goto exit;
-
-	path_uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (file_chooser));
-
-	e_file_update_save_path (path_uri, FALSE);
-
-	file_names = get_unique_file_names (parts);
-
-	for (iter = parts, iter_file = file_names; iter && iter_file; iter = iter->next, iter_file = iter_file->next) {
-		CamelMimePart *part = iter->data;
-		gchar *uri, *filename;
-
-		filename = iter_file->data;
-		uri = g_build_path ("/", path_uri, filename, NULL);
-		g_free (filename);
-		iter_file->data = NULL;
-
-		/* XXX Would be nice to mention _why_ we can't save. */
-		if (e_file_can_save (GTK_WINDOW (file_chooser), uri))
-			mail_save_part (part, uri, NULL, NULL, FALSE);
-		else
-			g_warning ("Unable to save %s", uri);
-
-		g_free (uri);
-	}
-
-	g_slist_free (file_names);
-	g_free (path_uri);
-
-exit:
-	gtk_widget_destroy (file_chooser);
-}
-
-/**
- * em_utils_save_part_to_file:
- * @parent: parent window
- * @filename: filename to save to
- * @part: part to save
- *
- * Save a part's content to a specific file
- * Creates all needed directories and overwrites without prompting
- *
- * Returns %TRUE if saving succeeded, %FALSE otherwise
- **/
-gboolean
-em_utils_save_part_to_file(GtkWindow *parent, const gchar *filename, CamelMimePart *part)
-{
-	gint done;
-	gchar *dirname;
-	struct stat st;
-
-	if (filename[0] == 0)
-		return FALSE;
-
-	dirname = g_path_get_dirname(filename);
-	if (g_mkdir_with_parents(dirname, 0777) == -1) {
-		GtkWidget *w = e_error_new(parent, "mail:no-create-path", filename, g_strerror(errno), NULL);
-		g_free(dirname);
-		em_utils_show_error_silent (w);
-		return FALSE;
-	}
-	g_free(dirname);
-
-	if (g_access(filename, F_OK) == 0) {
-		if (g_access(filename, W_OK) != 0) {
-			e_error_run(parent, E_ERROR_ASK_FILE_EXISTS_OVERWRITE, filename, NULL);
-			return FALSE;
-		}
-	}
-
-	if (g_stat(filename, &st) != -1 && !S_ISREG(st.st_mode)) {
-		GtkWidget *w = e_error_new(parent, "mail:no-write-path-notfile", filename, NULL);
-		em_utils_show_error_silent (w);
-		return FALSE;
-	}
-
-	/* FIXME: This doesn't handle default charsets */
-	mail_msg_wait(mail_save_part(part, filename, emu_save_part_done, &done, FALSE));
-
-	return done;
-}
-
 struct _save_messages_data {
 	CamelFolder *folder;
 	GPtrArray *uids;
diff --git a/mail/em-utils.h b/mail/em-utils.h
index 79caba0..9bb35b1 100644
--- a/mail/em-utils.h
+++ b/mail/em-utils.h
@@ -52,8 +52,6 @@ void em_utils_edit_filters (GtkWidget *parent);
 void em_filename_make_safe (gchar *string);
 void em_utils_edit_vfolders (GtkWidget *parent);
 
-void em_utils_save_part(GtkWindow *parent, const gchar *prompt, CamelMimePart *part);
-gboolean em_utils_save_part_to_file(GtkWindow *parent, const gchar *filename, CamelMimePart *part);
 void em_utils_save_messages (GtkWindow *parent, CamelFolder *folder, GPtrArray *uids);
 
 void em_utils_flag_for_followup (EMailReader *reader, CamelFolder *folder, GPtrArray *uids);
@@ -72,7 +70,6 @@ void em_utils_selection_set_urilist(GtkSelectionData *data, CamelFolder *folder,
 void em_utils_selection_get_urilist(GtkSelectionData *data, CamelFolder *folder);
 
 gchar *em_utils_temp_save_part(GtkWidget *parent, CamelMimePart *part, gboolean mode);
-void em_utils_save_parts (GtkWindow *parent, const gchar *prompt, GSList * parts);
 
 gboolean em_utils_folder_is_drafts(CamelFolder *folder, const gchar *uri);
 gboolean em_utils_folder_is_templates(CamelFolder *folder, const gchar *uri);
diff --git a/plugins/itip-formatter/itip-formatter.c b/plugins/itip-formatter/itip-formatter.c
index 8ed7a51..658acc0 100644
--- a/plugins/itip-formatter/itip-formatter.c
+++ b/plugins/itip-formatter/itip-formatter.c
@@ -57,7 +57,9 @@
 #include <calendar/gui/itip-utils.h>
 #include <calendar/common/authentication.h>
 #include <shell/e-shell.h>
+#include <shell/e-shell-utils.h>
 #include "itip-view.h"
+#include <misc/e-attachment.h>
 
 #define CLASSID "itip://"
 #define GCONF_KEY_DELETE "/apps/evolution/itip/delete_processed"
@@ -1474,18 +1476,54 @@ get_next (icalcompiter *iter)
 }
 
 static void
+attachment_load_finish (EAttachment *attachment,
+                        GAsyncResult *result,
+                        GFile *file)
+{
+	EShell *shell;
+	GtkWindow *parent;
+
+	/* XXX Theoretically, this should never fail. */
+	e_attachment_load_finish (attachment, result, NULL);
+
+	shell = e_shell_get_default ();
+	parent = e_shell_get_active_window (shell);
+
+	e_attachment_save_async (
+		attachment, file, (GAsyncReadyCallback)
+		e_attachment_save_handle_error, parent);
+
+	g_object_unref (file);
+}
+
+static void
 save_vcalendar_cb (GtkWidget *button, struct _itip_puri *pitip)
 {
+	EAttachment *attachment;
+	EShell *shell;
+	GFile *file;
+
 	g_return_if_fail (pitip != NULL);
 	g_return_if_fail (pitip->vcalendar != NULL);
 	g_return_if_fail (pitip->part != NULL);
 
+	shell = e_shell_get_default ();
+	file = e_shell_run_save_dialog (
+		shell, _("Save Calendar"), NULL, NULL);
+	if (file == NULL)
+		return;
+
 	if (!camel_mime_part_get_filename (pitip->part)) {
-		/* To Translators: This is a default file name  when saving calendar part */
+		/* Translators: This is a default filename for a calendar. */
 		camel_mime_part_set_filename (pitip->part, _("calendar.ics"));
 	}
 
-	em_utils_save_part (GTK_WINDOW (gtk_widget_get_toplevel (button)), _("Save calendar"), pitip->part);
+	attachment = e_attachment_new ();
+	e_attachment_set_mime_part (attachment, pitip->part);
+
+	e_attachment_load_async (
+		attachment, (GAsyncReadyCallback)
+		attachment_load_finish, file);
 }
 
 static GtkWidget *
diff --git a/plugins/mail-to-task/mail-to-task.c b/plugins/mail-to-task/mail-to-task.c
index 1c8be45..5c373d8 100644
--- a/plugins/mail-to-task/mail-to-task.c
+++ b/plugins/mail-to-task/mail-to-task.c
@@ -57,6 +57,7 @@
 #include <shell/e-shell-view.h>
 #include <shell/e-shell-window-actions.h>
 #include <calendar/gui/cal-editor-utils.h>
+#include <misc/e-attachment-store.h>
 
 #define E_SHELL_WINDOW_ACTION_CONVERT_TO_EVENT(window) \
 	E_SHELL_WINDOW_ACTION ((window), "mail-convert-to-event")
@@ -72,26 +73,6 @@ gboolean	mail_browser_init		(GtkUIManager *ui_manager,
 gboolean	mail_shell_view_init		(GtkUIManager *ui_manager,
 						 EShellView *shell_view);
 
-static gchar *
-clean_name(const guchar *s)
-{
-	GString *out = g_string_new("");
-	guint32 c;
-	gchar *r;
-
-	while ((c = camel_utf8_getc ((const guchar **)&s)))
-	{
-		if (!g_unichar_isprint (c) || ( c < 0x7f && strchr (" /'\"`&();|<>$%{}!", c )))
-			c = '_';
-		g_string_append_u (out, c);
-	}
-
-	r = g_strdup (out->str);
-	g_string_free (out, TRUE);
-
-	return r;
-}
-
 static void
 set_attendees (ECalComponent *comp, CamelMimeMessage *message, const gchar *organizer)
 {
@@ -281,61 +262,133 @@ set_organizer (ECalComponent *comp)
 }
 
 static void
+attachment_load_finished (EAttachment *attachment,
+                          GAsyncResult *result,
+                          gpointer user_data)
+{
+	struct {
+		gchar **uris;
+		gboolean done;
+	} *status = user_data;
+
+	/* 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);
+
+	status->done = TRUE;
+}
+
+static void
+attachment_save_finished (EAttachmentStore *store,
+                          GAsyncResult *result,
+                          gpointer user_data)
+{
+	gchar **uris;
+
+	struct {
+		gchar **uris;
+		gboolean done;
+	} *status = user_data;
+
+	/* XXX Add some error handling here! */
+	uris = e_attachment_store_save_finish (store, result, NULL);
+
+	status->uris = uris;
+	status->done = TRUE;
+}
+
+static void
 set_attachments (ECal *client, ECalComponent *comp, CamelMimeMessage *message)
 {
-	gint parts, i;
-	GSList *list = NULL;
-	const gchar *uid;
-	const gchar *store_uri;
-	gchar *store_dir;
+	/* XXX Much of this is copied from CompEditor::get_attachment_list().
+	 *     Perhaps it should be split off as a separate utility? */
+
+	EAttachmentStore *store;
 	CamelDataWrapper *content;
+	CamelMultipart *multipart;
+	GFile *destination;
+	GSList *list = NULL;
+	const gchar *comp_uid = NULL;
+	const gchar *local_store;
+	gint ii, n_parts;
+	gchar *uri;
+
+	struct {
+		gchar **uris;
+		gboolean done;
+	} status;
 
 	content = camel_medium_get_content_object ((CamelMedium *) message);
 	if (!content || !CAMEL_IS_MULTIPART (content))
 		return;
 
-	parts = camel_multipart_get_number (CAMEL_MULTIPART (content));
-	if (parts < 1)
+	n_parts = camel_multipart_get_number (CAMEL_MULTIPART (content));
+	if (n_parts < 1)
 		return;
 
-	e_cal_component_get_uid (comp, &uid);
-	store_uri = e_cal_get_local_attachment_store (client);
-	if (!store_uri)
-		return;
-	store_dir = g_filename_from_uri (store_uri, NULL, NULL);
+	e_cal_component_get_uid (comp, &comp_uid);
+	local_store = e_cal_get_local_attachment_store (client);
+	uri = g_build_path ("/", local_store, comp_uid, NULL);
+	destination = g_file_new_for_uri (uri);
+	g_free (uri);
+
+	/* Create EAttachments from the MIME parts and add them to the
+	 * attachment store. */
 
-	for (i = 1; i < parts; i++)
-	{
-		gchar *filename, *path, *tmp;
-		const gchar *orig_filename;
+	multipart = CAMEL_MULTIPART (content);
+	store = E_ATTACHMENT_STORE (e_attachment_store_new ());
+
+	for (ii = 1; ii < n_parts; ii++) {
 		CamelMimePart *mime_part;
+		EAttachment *attachment;
 
-		mime_part = camel_multipart_get_part (CAMEL_MULTIPART (content), i);
+		status.done = FALSE;
 
-		orig_filename = camel_mime_part_get_filename (mime_part);
-		if (!orig_filename)
-			continue;
+		attachment = e_attachment_new ();
+		mime_part = camel_multipart_get_part (multipart, ii);
+		e_attachment_set_mime_part (attachment, mime_part);
 
-		tmp = clean_name ((const guchar *)orig_filename);
-		filename = g_strdup_printf ("%s-%s", uid, tmp);
-		path = g_build_filename (store_dir, filename, NULL);
+		e_attachment_load_async (
+			attachment, (GAsyncReadyCallback)
+			attachment_load_finished, &status);
 
-		if (em_utils_save_part_to_file (NULL, path, mime_part))
-		{
-			gchar *uri;
-			uri = g_filename_to_uri (path, NULL, NULL);
-			list = g_slist_append (list, g_strdup (uri));
-			g_free (uri);
-		}
+		/* 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_free (tmp);
-		g_free (filename);
-		g_free (path);
+		e_attachment_store_add_attachment (store, attachment);
+		g_object_unref (attachment);
 	}
 
-	g_free (store_dir);
+	status.uris = NULL;
+	status.done = FALSE;
+
+	e_attachment_store_save_async (
+		store, destination, (GAsyncReadyCallback)
+		attachment_save_finished, &status);
+
+	/* We can't return until we have results, so crank
+	 * the main loop until the callback gets triggered. */
+	while (!status.done)
+		gtk_main_iteration ();
+
+	g_return_if_fail (status.uris != NULL);
 
+	/* Transfer the URI strings to the GSList. */
+	for (ii = 0; status.uris[ii] != NULL; ii++) {
+		list = g_slist_prepend (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);
+
+	g_object_unref (destination);
+	g_object_unref (store);
 }
 
 static void



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