[evolution-patches] Patch for bug 6951 (save all attachments)



Jeff, NotZed and others,
Attached is my patch based on CVS HEAD. Finally I have some time to finish it:) Please review it when you have time. Any chances to put it into Evolution 1.4?
   Thanks!
      Harry
Index: evolution/mail/ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution/mail/ChangeLog,v
retrieving revision 1.2721
diff -u -r1.2721 ChangeLog
--- evolution/mail/ChangeLog	9 May 2003 17:11:08 -0000	1.2721
+++ evolution/mail/ChangeLog	13 May 2003 03:43:15 -0000
@@ -1,3 +1,18 @@
+2003-05-13  Harry Lu  <harry lu sun com>
+
+	**Fix for bug #6951
+
+	* mail-display.c (launch_cb): Bypass the new added menu item.
+	(save_all_data_cb): New function. Do the real save-all work.
+	(save_all_part): New function. Get the directory to save to.
+	(save_all_cb): New function. The call-back function for the new 
+	added menu item.
+	(pixmap_press): Add the new menu item "Save All Attachment...".
+	(ptr_array_free_notify): A simple wrapper function to free the
+	pointer array.
+	(do_attachment_header): Save attachment pointer in an array for 
+	"Save All Attachment" use.
+
 2003-05-08  Ettore Perazzoli  <ettore ximian com>
 
 	* mail-session.c (mail_session_set_interactive): Set the
Index: evolution/mail/mail-display.c
===================================================================
RCS file: /cvs/gnome/evolution/mail/mail-display.c,v
retrieving revision 1.276
diff -u -r1.276 mail-display.c
--- evolution/mail/mail-display.c	8 May 2003 17:01:55 -0000	1.276
+++ evolution/mail/mail-display.c	13 May 2003 03:43:27 -0000
@@ -372,9 +372,11 @@
 	
 	/* Yum. Too bad EPopupMenu doesn't allow per-item closures. */
 	children = gtk_container_get_children (GTK_CONTAINER (widget->parent));
-	g_return_if_fail (children != NULL && children->next != NULL && children->next->next != NULL);
-	
-	for (c = children->next->next, apps = handler->applications; c && apps; c = c->next, apps = apps->next) {
+	/* We need to bypass the first 2 menu items */
+	g_return_if_fail (children != NULL && children->next != NULL 
+		&& children->next->next != NULL && children->next->next->next != NULL);
+
+	for (c = children->next->next->next, apps = handler->applications; c && apps; c = c->next, apps = apps->next) {
 		if (c->data == widget)
 			break;
 	}
@@ -433,6 +435,111 @@
 }
 
 static void
+save_all_data_cb (GtkWidget *widget, gpointer user_data)
+{
+	GtkFileSelection *dir_select = (GtkFileSelection *) 
+		gtk_widget_get_ancestor (widget, GTK_TYPE_FILE_SELECTION);
+	const char *filename;
+	char *save_filename, *dir;
+	struct stat st;
+	int i;
+	GPtrArray *attachment_array;
+	CamelMimePart *part;
+	GConfClient *gconf;
+
+	gtk_widget_hide (GTK_WIDGET (dir_select));
+
+	/* Get the selected directory name */
+	filename = gtk_file_selection_get_filename (dir_select);
+	if (stat (filename, &st) == -1) {
+		GtkWidget *dialog;
+
+		dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+			_("%s is not a valid directory name."), filename);
+
+		/* FIXME: this should be async */
+		gtk_dialog_run ((GtkDialog *) dialog);
+		gtk_widget_destroy (dialog);
+		gtk_widget_destroy (GTK_WIDGET (dir_select));
+		return;
+	} else if (S_ISDIR (st.st_mode)) {
+		dir = g_strdup (filename);
+	} else {
+		dir = g_path_get_dirname (filename);
+	}
+						
+	/* Now save the attachment one by one */
+	attachment_array = (GPtrArray *)user_data;
+	for (i = 0; i < attachment_array->len; i++) {
+		part = g_ptr_array_index (attachment_array, i);
+		save_filename = make_safe_filename (dir, part);
+		write_data_to_file (part, save_filename, FALSE);
+		g_free (save_filename);
+	}
+							
+	/* preserve the pathname */
+	gconf = gconf_client_get_default ();
+	gconf_client_set_string (gconf, "/apps/evolution/mail/save_dir", dir, NULL);
+	g_free (dir);
+							
+	gtk_widget_destroy (GTK_WIDGET (dir_select));
+}
+
+static void 
+save_all_part (GPtrArray *attachment_array)
+{
+	GtkFileSelection *dir_select;
+	char *dir, *home, *p, *dir2;
+	GConfClient *gconf;
+
+	g_return_if_fail (attachment_array!= NULL);
+
+	home = getenv ("HOME");
+	gconf = gconf_client_get_default ();
+	dir = gconf_client_get_string (gconf, "/apps/evolution/mail/save_dir", NULL);
+	dir = dir ? dir : (home ? g_strdup (home) : g_strdup (""));
+
+	/* Make sure dir2 has a '/' as its tail */
+	p = dir + strlen(dir);
+	if (*p == '/')
+		dir2 = g_strdup (dir);
+	else
+		dir2 = g_strdup_printf ("%s/", dir);
+
+	dir_select = GTK_FILE_SELECTION (
+		gtk_file_selection_new (_("Select a Directory to Save All Attachment")));
+	gtk_file_selection_set_filename (dir_select, dir2);
+	gtk_widget_set_sensitive (GTK_WIDGET(dir_select->file_list), FALSE);
+	g_free (dir);
+	g_free (dir2);
+
+	g_signal_connect (dir_select->ok_button, "clicked", 
+		G_CALLBACK (save_all_data_cb), attachment_array);
+	g_signal_connect_swapped (dir_select->cancel_button,
+		"clicked",
+		G_CALLBACK (gtk_widget_destroy),
+		dir_select);
+
+	gtk_widget_show (GTK_WIDGET (dir_select));
+}
+		
+static void
+save_all_cb (GtkWidget *widget, gpointer user_data)
+{
+	MailDisplay *md = g_object_get_data (user_data, "MailDisplay");
+	GPtrArray *attachment_array;
+			
+	if (md == NULL) {
+		g_warning ("No MailDisplay!");
+		return;
+	}
+
+	attachment_array = g_datalist_get_data (md->data, "attachment_array");
+	save_all_part (attachment_array);
+}
+
+
+static void
 button_press (GtkWidget *widget, CamelMimePart *part)
 {
 	MailDisplay *md;
@@ -452,12 +559,14 @@
 {
 	EPopupMenu *menu;
 	EPopupMenu save_item = E_POPUP_ITEM (N_("Save Attachment..."), G_CALLBACK (save_cb), 0);
+	EPopupMenu save_all_item = E_POPUP_ITEM (N_("Save All Attachment..."), G_CALLBACK (save_all_cb), 0);
 	EPopupMenu view_item = E_POPUP_ITEM (N_("View Inline"), G_CALLBACK (inline_cb), 2);
 	EPopupMenu open_item = E_POPUP_ITEM (N_("Open in %s..."), G_CALLBACK (launch_cb), 1);
 	MailDisplay *md;
 	CamelMimePart *part;
 	MailMimeHandler *handler;
 	int mask = 0, i, nitems;
+	int current_item = 0;
 	
 #ifdef USE_OLD_DISPLAY_STYLE
 	if (event->button != 3) {
@@ -481,17 +590,23 @@
 	handler = mail_lookup_handler (g_object_get_data ((GObject *) widget, "mime_type"));
 	
 	if (handler && handler->applications)
-		nitems = g_list_length (handler->applications) + 2;
+		nitems = g_list_length (handler->applications) + 3;
 	else
-		nitems = 3;
+		nitems = 4;
 	menu = g_new0 (EPopupMenu, nitems + 1);
 	
 	/* Save item */
-	memcpy (&menu[0], &save_item, sizeof (menu[0]));
-	menu[0].name = _(menu[0].name);
-	
+	memcpy (&menu[current_item], &save_item, sizeof (menu[current_item]));
+	menu[current_item].name = g_strdup (_(menu[current_item].name));
+	current_item++;
+
+	/* Save All item */
+	memcpy (&menu[current_item], &save_all_item, sizeof (menu[current_item]));
+	menu[current_item].name = g_strdup (_(menu[current_item].name));
+	current_item++;
+	 
 	/* Inline view item */
-	memcpy (&menu[1], &view_item, sizeof (menu[1]));
+	memcpy (&menu[current_item], &view_item, sizeof (menu[current_item]));
 	if (handler && handler->builtin) {
 		md = g_object_get_data ((GObject *) widget, "MailDisplay");
 		
@@ -509,15 +624,16 @@
 					name = prop->v._u.value_string;
 				else
 					name = "bonobo";
-				menu[1].name = g_strdup_printf (_("View Inline (via %s)"), name);
+				menu[current_item].name = g_strdup_printf (_("View Inline (via %s)"), name);
 			} else
-				menu[1].name = g_strdup (_(menu[1].name));
+				menu[current_item].name = g_strdup (_(menu[current_item].name));
 		} else
-			menu[1].name = g_strdup (_("Hide"));
+			menu[current_item].name = g_strdup (_("Hide"));
 	} else {
-		menu[1].name = g_strdup (_(menu[1].name));
+		menu[current_item].name = g_strdup (_(menu[current_item].name));
 		mask |= 2;
 	}
+	current_item++;
 	
 	/* External views */
 	if (handler && handler->applications) {
@@ -526,14 +642,15 @@
 		int i;
 		
 		apps = handler->applications;
-		for (i = 2; i < nitems; i++, apps = apps->next) {
+		for (i = current_item; i < nitems; i++, apps = apps->next) {
 			app = apps->data;
 			memcpy (&menu[i], &open_item, sizeof (menu[i]));
 			menu[i].name = g_strdup_printf (_(menu[i].name), app->name);
+			current_item++;
 		}
 	} else {
-		memcpy (&menu[2], &open_item, sizeof (menu[2]));
-		menu[2].name = g_strdup_printf (_(menu[2].name), _("External Viewer"));
+		memcpy (&menu[current_item], &open_item, sizeof (menu[current_item]));
+		menu[current_item].name = g_strdup_printf (_(menu[current_item].name), _("External Viewer"));
 		mask |= 1;
 	}
 	
@@ -1004,6 +1121,12 @@
 	}
 }
 
+/* This is a wrapper function */
+void ptr_array_free_notify (gpointer array)
+{
+	g_ptr_array_free ((GPtrArray *) array, TRUE);
+}
+
 static gboolean
 do_attachment_header (GtkHTML *html, GtkHTMLEmbedded *eb,
 		      CamelMimePart *part, MailDisplay *md)
@@ -1011,6 +1134,7 @@
 	GtkWidget *button, *mainbox, *hbox, *arrow, *popup;
 	MailMimeHandler *handler;
 	struct _PixbufLoader *pbl;
+	GPtrArray *attachment_array;
 	
 	pbl = g_new0 (struct _PixbufLoader, 1);
 	if (strncasecmp (eb->type, "image/", 6) == 0) {
@@ -1077,6 +1201,19 @@
 	g_object_set_data ((GObject *) popup, "MailDisplay", md);
 	g_object_set_data ((GObject *) popup, "CamelMimePart", part);
 	g_object_set_data_full ((GObject *) popup, "mime_type", g_strdup (eb->type), (GDestroyNotify) g_free);
+
+	/* Save attachment pointer in an array for "save all attachment" use */	
+	attachment_array= g_datalist_get_data (md->data, "attachment_array");
+	if (!attachment_array) {
+		attachment_array = g_ptr_array_new();
+		g_datalist_set_data_full (md->data, "attachment_array", 
+			attachment_array, (GDestroyNotify)ptr_array_free_notify);
+	}
+	/* Since the attachment pointer might have been added to the array before,
+	remove it first anyway to avoide duplication */
+	g_ptr_array_remove (attachment_array, (gpointer)part);
+	g_ptr_array_add (attachment_array, (gpointer)part);
+		 
 	
 	g_signal_connect (popup, "button_press_event", G_CALLBACK (pixmap_press), md->scroll);
 	


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