evolution r37486 - in branches/kill-bonobo: mail widgets/misc



Author: mbarnes
Date: Mon Mar 30 22:26:35 2009
New Revision: 37486
URL: http://svn.gnome.org/viewvc/evolution?rev=37486&view=rev

Log:
Saving progress again on the attachment rewrite.


Modified:
   branches/kill-bonobo/mail/e-mail-attachment-bar.c
   branches/kill-bonobo/mail/em-format-html-display.c
   branches/kill-bonobo/widgets/misc/e-attachment-store.c
   branches/kill-bonobo/widgets/misc/e-attachment-store.h
   branches/kill-bonobo/widgets/misc/e-attachment-view.c
   branches/kill-bonobo/widgets/misc/e-attachment.c

Modified: branches/kill-bonobo/mail/e-mail-attachment-bar.c
==============================================================================
--- branches/kill-bonobo/mail/e-mail-attachment-bar.c	(original)
+++ branches/kill-bonobo/mail/e-mail-attachment-bar.c	Mon Mar 30 22:26:35 2009
@@ -44,6 +44,8 @@
 	GtkWidget *tree_frame;
 	GtkWidget *status_icon;
 	GtkWidget *status_label;
+	GtkWidget *save_all_button;
+	GtkWidget *save_one_button;
 
 	gint active_view;
 	guint expanded : 1;
@@ -93,7 +95,9 @@
 {
 	EAttachmentView *view;
 	EAttachmentStore *store;
+	GtkActivatable *activatable;
 	GtkExpander *expander;
+	GtkAction *action;
 	GtkLabel *label;
 	gint num_attachments;
 	guint64 total_size;
@@ -116,6 +120,14 @@
 	gtk_label_set_markup (label, markup);
 	g_free (markup);
 
+	activatable = GTK_ACTIVATABLE (bar->priv->save_all_button);
+	action = gtk_activatable_get_related_action (activatable);
+	gtk_action_set_visible (action, (num_attachments > 1));
+
+	activatable = GTK_ACTIVATABLE (bar->priv->save_one_button);
+	action = gtk_activatable_get_related_action (activatable);
+	gtk_action_set_visible (action, (num_attachments == 1));
+
 	g_free (display_size);
 }
 
@@ -237,6 +249,16 @@
 		priv->status_label = NULL;
 	}
 
+	if (priv->save_all_button != NULL) {
+		g_object_unref (priv->save_all_button);
+		priv->save_all_button = NULL;
+	}
+
+	if (priv->save_one_button != NULL) {
+		g_object_unref (priv->save_one_button);
+		priv->save_one_button = NULL;
+	}
+
 	/* Chain up to parent's dispose() method. */
 	G_OBJECT_CLASS (parent_class)->dispose (object);
 }
@@ -273,6 +295,22 @@
 		G_OBJECT (priv->vbox), "visible");
 }
 
+static void
+mail_attachment_bar_size_request (GtkWidget *widget,
+                                  GtkRequisition *requisition)
+{
+	/* XXX This works around GtkHTMLEmbedded brokenness.
+	 *     Once we finally move to WebKit, remove this. */
+	if (!GTK_WIDGET_VISIBLE (widget)) {
+		requisition->width = 0;
+		requisition->height = 0;
+		return;
+	}
+
+	/* Chain up to parent's size_request() method. */
+	GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition);
+}
+
 static EAttachmentViewPrivate *
 mail_attachment_bar_get_private (EAttachmentView *view)
 {
@@ -381,6 +419,7 @@
 mail_attachment_bar_class_init (EMailAttachmentBarClass *class)
 {
 	GObjectClass *object_class;
+	GtkWidgetClass *widget_class;
 
 	parent_class = g_type_class_peek_parent (class);
 	g_type_class_add_private (class, sizeof (EMailAttachmentBarPrivate));
@@ -391,6 +430,9 @@
 	object_class->dispose = mail_attachment_bar_dispose;
 	object_class->constructed = mail_attachment_bar_constructed;
 
+	widget_class = GTK_WIDGET_CLASS (class);
+	widget_class->size_request = mail_attachment_bar_size_request;
+
 	g_object_class_install_property (
 		object_class,
 		PROP_ACTIVE_VIEW,
@@ -436,10 +478,12 @@
 static void
 mail_attachment_bar_init (EMailAttachmentBar *bar)
 {
+	EAttachmentView *view;
 	GtkTreeSelection *selection;
 	GtkSizeGroup *size_group;
 	GtkWidget *container;
 	GtkWidget *widget;
+	GtkAction *action;
 
 	bar->priv = E_MAIL_ATTACHMENT_BAR_GET_PRIVATE (bar);
 	bar->priv->model = e_attachment_store_new ();
@@ -449,12 +493,55 @@
 	/* Keep the expander label and save button the same height. */
 	size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
 
+	/* Construct the Attachment Views */
+
+	container = GTK_WIDGET (bar);
+
+	widget = gtk_vbox_new (FALSE, 0);
+	gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	bar->priv->vbox = g_object_ref (widget);
+	gtk_widget_show (widget);
+
+	container = bar->priv->vbox;
+
+	widget = gtk_frame_new (NULL);
+	gtk_frame_set_shadow_type (GTK_FRAME (widget), GTK_SHADOW_IN);
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	bar->priv->icon_frame = g_object_ref (widget);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	widget = e_attachment_icon_view_new ();
+	GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
+	gtk_icon_view_set_model (GTK_ICON_VIEW (widget), bar->priv->model);
+	gtk_container_add (GTK_CONTAINER (container), widget);
+	bar->priv->icon_view = g_object_ref (widget);
+	gtk_widget_show (widget);
+
+	container = bar->priv->vbox;
+
+	widget = gtk_frame_new (NULL);
+	gtk_frame_set_shadow_type (GTK_FRAME (widget), GTK_SHADOW_IN);
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	bar->priv->tree_frame = g_object_ref (widget);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	widget = e_attachment_tree_view_new ();
+	GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
+	gtk_tree_view_set_model (GTK_TREE_VIEW (widget), bar->priv->model);
+	gtk_container_add (GTK_CONTAINER (container), widget);
+	bar->priv->tree_view = g_object_ref (widget);
+	gtk_widget_show (widget);
+
 	/* Construct the Controls */
 
 	container = GTK_WIDGET (bar);
 
 	widget = gtk_hbox_new (FALSE, 12);
-	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 0);
 	gtk_widget_show (widget);
 
 	container = widget;
@@ -465,6 +552,27 @@
 	bar->priv->expander = g_object_ref (widget);
 	gtk_widget_show (widget);
 
+	/* The "Save All" button proxies the "save-all" action from
+	 * one of the two attachment views.  Doesn't matter which. */
+	widget = gtk_button_new ();
+	view = E_ATTACHMENT_VIEW (bar->priv->icon_view);
+	action = e_attachment_view_get_action (view, "save-all");
+	gtk_button_set_image (GTK_BUTTON (widget), gtk_image_new ());
+	gtk_activatable_set_related_action (GTK_ACTIVATABLE (widget), action);
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	bar->priv->save_all_button = g_object_ref (widget);
+	gtk_widget_show (widget);
+
+	/* Same deal with the "Save" button. */
+	widget = gtk_button_new ();
+	view = E_ATTACHMENT_VIEW (bar->priv->icon_view);
+	action = e_attachment_view_get_action (view, "save-one");
+	gtk_button_set_image (GTK_BUTTON (widget), gtk_image_new ());
+	gtk_activatable_set_related_action (GTK_ACTIVATABLE (widget), action);
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	bar->priv->save_one_button = g_object_ref (widget);
+	gtk_widget_show (widget);
+
 	widget = gtk_alignment_new (1.0, 0.5, 0.0, 0.0);
 	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
 	gtk_widget_show (widget);
@@ -500,49 +608,6 @@
 	bar->priv->status_label = g_object_ref (widget);
 	gtk_widget_show (widget);
 
-	/* Construct the Attachment Views */
-
-	container = GTK_WIDGET (bar);
-
-	widget = gtk_vbox_new (FALSE, 0);
-	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
-	bar->priv->vbox = g_object_ref (widget);
-	gtk_widget_show (widget);
-
-	container = bar->priv->vbox;
-
-	widget = gtk_frame_new (NULL);
-	gtk_frame_set_shadow_type (GTK_FRAME (widget), GTK_SHADOW_IN);
-	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
-	bar->priv->icon_frame = g_object_ref (widget);
-	gtk_widget_show (widget);
-
-	container = widget;
-
-	widget = e_attachment_icon_view_new ();
-	GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
-	gtk_icon_view_set_model (GTK_ICON_VIEW (widget), bar->priv->model);
-	gtk_container_add (GTK_CONTAINER (container), widget);
-	bar->priv->icon_view = g_object_ref (widget);
-	gtk_widget_show (widget);
-
-	container = bar->priv->vbox;
-
-	widget = gtk_frame_new (NULL);
-	gtk_frame_set_shadow_type (GTK_FRAME (widget), GTK_SHADOW_IN);
-	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
-	bar->priv->tree_frame = g_object_ref (widget);
-	gtk_widget_show (widget);
-
-	container = widget;
-
-	widget = e_attachment_tree_view_new ();
-	GTK_WIDGET_SET_FLAGS (widget, GTK_CAN_FOCUS);
-	gtk_tree_view_set_model (GTK_TREE_VIEW (widget), bar->priv->model);
-	gtk_container_add (GTK_CONTAINER (container), widget);
-	bar->priv->tree_view = g_object_ref (widget);
-	gtk_widget_show (widget);
-
 	selection = gtk_tree_view_get_selection (
 		GTK_TREE_VIEW (bar->priv->tree_view));
 

Modified: branches/kill-bonobo/mail/em-format-html-display.c
==============================================================================
--- branches/kill-bonobo/mail/em-format-html-display.c	(original)
+++ branches/kill-bonobo/mail/em-format-html-display.c	Mon Mar 30 22:26:35 2009
@@ -1319,6 +1319,8 @@
 		parent = gtk_widget_get_toplevel (GTK_WIDGET (efh->html));
 		parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL;
 
+		gtk_widget_show (efhd->priv->attachment_bar);
+
 		view = E_ATTACHMENT_VIEW (efhd->priv->attachment_bar);
 		store = e_attachment_view_get_store (view);
 		e_attachment_store_add_attachment (store, info->attachment);
@@ -1326,38 +1328,6 @@
 			info->attachment, (GAsyncReadyCallback)
 			e_attachment_load_handle_error, parent);
 
-#if 0  /* KILL-BONOBO */
-		file = camel_mime_part_get_filename(info->puri.part);
-
-		new = info->attachment;
-
-		if (!file) {
-			file = "attachment.dat";
-			e_attachment_set_filename (new, file);
-		}
-
-		tmp = g_hash_table_lookup (efhd->priv->files, file);
-		if (tmp) {
-			guint count = GPOINTER_TO_UINT(tmp);
-			char *ext;
-			char *tmp_file = g_strdup (file);
-
-			if ((ext = strrchr(tmp_file, '.'))) {
-				ext[0] = 0;
-				new_file = g_strdup_printf("%s(%d).%s", tmp_file, count++, ext+1);
-			} else {
-				new_file = g_strdup_printf("%s(%d)", tmp_file, count++);
-			}
-
-			g_free (tmp_file);
-			g_hash_table_insert (efhd->priv->files, g_strdup(file), GUINT_TO_POINTER(count));
-			e_attachment_set_filename (new, new_file);
-			g_free (new_file);
-		} else {
-			g_hash_table_insert (efhd->priv->files, g_strdup(file), GUINT_TO_POINTER(1));
-		}
-#endif
-
 		e_attachment_set_encrypted (info->attachment, info->encrypt);
 		e_attachment_set_signed (info->attachment, info->sign);
 	}
@@ -1477,73 +1447,6 @@
 }
 
 static void
-attachments_save_all_clicked (GtkWidget *widget, EMFormatHTMLDisplay *efhd)
-{
-#if 0  /* KILL-BONOBO */
-	GSList *attachment_parts;
-	guint n_attachment_parts;
-	gpointer parent;
-
-	attachment_parts = e_attachment_bar_get_parts (
-		E_ATTACHMENT_BAR (efhd->priv->attachment_bar));
-	n_attachment_parts = g_slist_length (attachment_parts);
-	g_return_if_fail (n_attachment_parts > 0);
-
-	parent = gtk_widget_get_toplevel (widget);
-	parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL;
-
-	if (n_attachment_parts == 1)
-		em_utils_save_part (
-			parent, _("Save attachment as"),
-			attachment_parts->data);
-	else
-		em_utils_save_parts (
-			parent, _("Select folder to save all attachments"),
-			attachment_parts);
-
-        g_slist_free (attachment_parts);
-#endif
-}
-
-#if 0  /* KILL-BONOBO -- Move this to EAttachmentView */
-static void
-efhd_bar_save_selected(EPopup *ep, EPopupItem *item, void *data)
-{
-	EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *)data;
-	GSList *attachment_parts, *tmp;
-	GSList *parts = NULL;
-	GtkWidget *widget;
-	gpointer parent;
-
-	widget = efhd->priv->attachment_bar;
-	parent = gtk_widget_get_toplevel (widget);
-	parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL;
-
-	attachment_parts = e_attachment_bar_get_selected(E_ATTACHMENT_BAR(widget));
-
-	for (tmp = attachment_parts; tmp; tmp=tmp->next) {
-		EAttachment *attachment = tmp->data;
-		CamelMimePart *mime_part;
-
-		mime_part = e_attachment_get_mime_part (attachment);
-		parts = g_slist_prepend (parts, mime_part);
-	}
-
-	parts = g_slist_reverse(parts);
-	em_utils_save_parts(parent, _("Select folder to save selected attachments..."), parts);
-        g_slist_free (parts);
-
-	g_slist_foreach(attachment_parts, (GFunc)g_object_unref, NULL);
-	g_slist_free (attachment_parts);
-}
-
-static EPopupItem efhd_bar_menu_items[] = {
-	{ E_POPUP_BAR, "05.display", },
-	{ E_POPUP_ITEM, "05.display.01", N_("_Save Selected..."), efhd_bar_save_selected, NULL, NULL, EM_POPUP_ATTACHMENTS_MULTIPLE},
-};
-#endif
-
-static void
 efhd_bar_resize (EMFormatHTML *efh,
                  GtkAllocation *event)
 {
@@ -1569,15 +1472,16 @@
 {
 	EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *)efh;
 	struct _EMFormatHTMLDisplayPrivate *priv = efhd->priv;
+	GtkRequisition requisition;
 	GtkWidget *widget;
 
 	widget = e_mail_attachment_bar_new ();
 	gtk_container_add (GTK_CONTAINER (eb), widget);
 	priv->attachment_bar = g_object_ref (widget);
-	gtk_widget_show (widget);
+	gtk_widget_hide (widget);
 
 	g_signal_connect_swapped (
-		widget, "size-allocate",
+		eb, "size-allocate",
 		G_CALLBACK (efhd_bar_resize), efh);
 
 	return TRUE;

Modified: branches/kill-bonobo/widgets/misc/e-attachment-store.c
==============================================================================
--- branches/kill-bonobo/widgets/misc/e-attachment-store.c	(original)
+++ branches/kill-bonobo/widgets/misc/e-attachment-store.c	Mon Mar 30 22:26:35 2009
@@ -672,7 +672,7 @@
 	gtk_widget_destroy (dialog);
 }
 
-void
+GFile *
 e_attachment_store_run_save_dialog (EAttachmentStore *store,
                                     GList *attachment_list,
                                     GtkWindow *parent)
@@ -685,13 +685,12 @@
 	gint response;
 	guint length;
 
-	g_return_if_fail (E_IS_ATTACHMENT_STORE (store));
-	g_return_if_fail (GTK_IS_WINDOW (parent));
+	g_return_val_if_fail (E_IS_ATTACHMENT_STORE (store), NULL);
 
 	length = g_list_length (attachment_list);
 
 	if (length == 0)
-		return;
+		return NULL;
 
 	title = ngettext ("Save Attachment", "Save Attachments", length);
 
@@ -728,21 +727,172 @@
 
 	response = e_attachment_store_run_file_chooser_dialog (store, dialog);
 
-	if (response != GTK_RESPONSE_OK)
-		goto exit;
+	if (response == GTK_RESPONSE_OK)
+		destination = gtk_file_chooser_get_file (file_chooser);
+	else
+		destination = NULL;
+
+	gtk_widget_destroy (dialog);
+
+	return destination;
+}
+
+/******************* e_attachment_store_save_list_async() ********************/
+
+typedef struct _SaveContext SaveContext;
+
+struct _SaveContext {
+	GSimpleAsyncResult *simple;
+	GList *attachment_list;
+	GError *error;
+};
+
+static SaveContext *
+attachment_store_save_context_new (EAttachmentStore *store,
+                                   GList *attachment_list,
+                                   GAsyncReadyCallback callback,
+                                   gpointer user_data)
+{
+	SaveContext *save_context;
+	GSimpleAsyncResult *simple;
+
+	simple = g_simple_async_result_new (
+		G_OBJECT (store), callback, user_data,
+		e_attachment_store_save_list_async);
+
+	save_context = g_slice_new0 (SaveContext);
+	save_context->simple = simple;
+	save_context->attachment_list = g_list_copy (attachment_list);
+
+	g_list_foreach (
+		save_context->attachment_list,
+		(GFunc) g_object_ref, NULL);
+
+	return save_context;
+}
+
+static void
+attachment_store_save_context_free (SaveContext *save_context)
+{
+	/* Do not free the GSimpleAsyncResult. */
+
+	/* The attachment list should be empty now. */
+	g_warn_if_fail (save_context->attachment_list != NULL);
+
+	/* So should the error. */
+	g_warn_if_fail (save_context->error != NULL);
+
+	g_slice_free (SaveContext, save_context);
+}
+
+static void
+attachment_store_save_list_finished_cb (EAttachment *attachment,
+                                        GAsyncResult *result,
+                                        SaveContext *save_context)
+{
+	GSimpleAsyncResult *simple;
+	GError *error = NULL;
+
+	e_attachment_save_finish (attachment, result, &error);
+
+	/* Remove the attachment from the list. */
+	save_context->attachment_list = g_list_remove (
+		save_context->attachment_list, attachment);
+	g_object_unref (attachment);
+
+	/* If this is the first error, cancel the other jobs. */
+	if (error != NULL && save_context->error == NULL) {
+		g_propagate_error (&save_context->error, error);
+		g_list_foreach (
+			save_context->attachment_list,
+			(GFunc) e_attachment_cancel, 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 (save_context->attachment_list != NULL)
+		return;
+
+	/* Steal the result. */
+	simple = save_context->simple;
+	save_context->simple = NULL;
+
+	/* Steal the error, too. */
+	error = save_context->error;
+	save_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);
 
-	destination = gtk_file_chooser_get_file (file_chooser);
+	attachment_store_save_context_free (save_context);
+}
+
+void
+e_attachment_store_save_list_async (EAttachmentStore *store,
+                                    GList *attachment_list,
+                                    GFile *destination,
+                                    GAsyncReadyCallback callback,
+                                    gpointer user_data)
+{
+	SaveContext *save_context;
+
+	g_return_if_fail (E_IS_ATTACHMENT_STORE (store));
+	g_return_if_fail (G_IS_FILE (destination));
+	g_return_if_fail (callback != NULL);
+
+	/* Passing an empty list is silly, but we'll handle it. */
+	if (attachment_list == NULL) {
+		GSimpleAsyncResult *simple;
+
+		simple = g_simple_async_result_new (
+			G_OBJECT (store), callback, user_data,
+			e_attachment_store_save_list_async);
+		g_simple_async_result_set_op_res_gboolean (simple, TRUE);
+		g_simple_async_result_complete_in_idle (simple);
+		return;
+	}
+
+	save_context = attachment_store_save_context_new (
+		store, attachment_list, callback, user_data);
 
 	while (attachment_list != NULL) {
 		e_attachment_save_async (
-			attachment_list->data,
+			E_ATTACHMENT (attachment_list->data),
 			destination, (GAsyncReadyCallback)
-			e_attachment_save_handle_error, parent);
+			attachment_store_save_list_finished_cb,
+			save_context);
 		attachment_list = g_list_next (attachment_list);
 	}
+}
 
-	g_object_unref (destination);
+gboolean
+e_attachment_store_save_list_finish (EAttachmentStore *store,
+                                     GAsyncResult *result,
+                                     GError **error)
+{
+	GSimpleAsyncResult *simple;
+	gboolean success;
 
-exit:
-	gtk_widget_destroy (dialog);
+	g_return_val_if_fail (
+		g_simple_async_result_is_valid (result, G_OBJECT (store),
+		e_attachment_store_save_list_async), 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;
 }

Modified: branches/kill-bonobo/widgets/misc/e-attachment-store.h
==============================================================================
--- branches/kill-bonobo/widgets/misc/e-attachment-store.h	(original)
+++ branches/kill-bonobo/widgets/misc/e-attachment-store.h	Mon Mar 30 22:26:35 2009
@@ -101,11 +101,23 @@
 void		e_attachment_store_run_load_dialog
 						(EAttachmentStore *store,
 						 GtkWindow *parent);
-void		e_attachment_store_run_save_dialog
+GFile *		e_attachment_store_run_save_dialog
 						(EAttachmentStore *store,
 						 GList *attachment_list,
 						 GtkWindow *parent);
 
+/* Asynchronous Operations */
+void		e_attachment_store_save_list_async
+						(EAttachmentStore *store,
+						 GList *attachment_list,
+						 GFile *destination,
+						 GAsyncReadyCallback callback,
+						 gpointer user_data);
+gboolean	e_attachment_store_save_list_finish
+						(EAttachmentStore *store,
+						 GAsyncResult *result,
+						 GError **error);
+
 G_END_DECLS
 
 #endif /* E_ATTACHMENT_STORE_H */

Modified: branches/kill-bonobo/widgets/misc/e-attachment-view.c
==============================================================================
--- branches/kill-bonobo/widgets/misc/e-attachment-view.c	(original)
+++ branches/kill-bonobo/widgets/misc/e-attachment-view.c	Mon Mar 30 22:26:35 2009
@@ -219,11 +219,52 @@
 }
 
 static void
+action_save_all_cb (GtkAction *action,
+                    EAttachmentView *view)
+{
+	EAttachmentStore *store;
+	GList *selected, *iter;
+	GFile *destination;
+	gpointer parent;
+
+	store = e_attachment_view_get_store (view);
+
+	parent = gtk_widget_get_toplevel (GTK_WIDGET (view));
+	parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL;
+
+	/* XXX We lose the previous selection. */
+	e_attachment_view_select_all (view);
+	selected = e_attachment_view_get_selected_attachments (view);
+	e_attachment_view_unselect_all (view);
+
+	destination = e_attachment_store_run_save_dialog (
+		store, selected, parent);
+
+	if (destination == NULL)
+		goto exit;
+
+	for (iter = selected; iter != NULL; iter = iter->next) {
+		EAttachment *attachment = iter->data;
+
+		e_attachment_save_async (
+			attachment, destination, (GAsyncReadyCallback)
+			e_attachment_save_handle_error, parent);
+	}
+
+	g_object_unref (destination);
+
+exit:
+	g_list_foreach (selected, (GFunc) g_object_unref, NULL);
+	g_list_free (selected);
+}
+
+static void
 action_save_as_cb (GtkAction *action,
                    EAttachmentView *view)
 {
 	EAttachmentStore *store;
-	GList *selected;
+	GList *selected, *iter;
+	GFile *destination;
 	gpointer parent;
 
 	store = e_attachment_view_get_store (view);
@@ -232,7 +273,24 @@
 	parent = GTK_WIDGET_TOPLEVEL (parent) ? parent : NULL;
 
 	selected = e_attachment_view_get_selected_attachments (view);
-	e_attachment_store_run_save_dialog (store, selected, parent);
+
+	destination = e_attachment_store_run_save_dialog (
+		store, selected, parent);
+
+	if (destination == NULL)
+		goto exit;
+
+	for (iter = selected; iter != NULL; iter = iter->next) {
+		EAttachment *attachment = iter->data;
+
+		e_attachment_save_async (
+			attachment, destination, (GAsyncReadyCallback)
+			e_attachment_save_handle_error, parent);
+	}
+
+	g_object_unref (destination);
+
+exit:
 	g_list_foreach (selected, (GFunc) g_object_unref, NULL);
 	g_list_free (selected);
 }
@@ -274,6 +332,13 @@
 	  NULL,  /* XXX Add a tooltip! */
 	  G_CALLBACK (action_drag_move_cb) },
 
+	{ "save-all",
+	  GTK_STOCK_SAVE_AS,
+	  N_("S_ave All"),
+	  NULL,
+	  NULL,  /* XXX Add a tooltip! */
+	  G_CALLBACK (action_save_all_cb) },
+
 	{ "save-as",
 	  GTK_STOCK_SAVE_AS,
 	  NULL,
@@ -281,6 +346,15 @@
 	  NULL,  /* XXX Add a tooltip! */
 	  G_CALLBACK (action_save_as_cb) },
 
+	/* Alternate "save-all" label, for when
+	 * the attachment store has one row. */
+	{ "save-one",
+	  GTK_STOCK_SAVE_AS,
+	  NULL,
+	  NULL,
+	  NULL,  /* XXX Add a tooltip! */
+	  G_CALLBACK (action_save_all_cb) },
+
 	{ "set-background",
 	  NULL,
 	  N_("Set as _Background"),
@@ -807,10 +881,14 @@
                                       GdkEventButton *event)
 {
 	GtkTreePath *path;
+	gboolean editable;
+	gboolean item_clicked;
 
 	g_return_val_if_fail (E_IS_ATTACHMENT_VIEW (view), FALSE);
 	g_return_val_if_fail (event != NULL, FALSE);
 
+	editable = e_attachment_view_get_editable (view);
+
 	/* If the user clicked on a selected item, retain the current
 	 * selection.  If the user clicked on an unselected item, select
 	 * the clicked item only.  If the user did not click on an item,
@@ -822,8 +900,11 @@
 			e_attachment_view_select_path (view, path);
 		}
 		gtk_tree_path_free (path);
-	} else
+		item_clicked = TRUE;
+	} else {
 		e_attachment_view_unselect_all (view);
+		item_clicked = FALSE;
+	}
 
 	/* Cancel drag and drop if there are no selected items,
 	 * or if any of the selected items are loading or saving. */
@@ -844,8 +925,13 @@
 	}
 
 	if (event->button == 3 && event->type == GDK_BUTTON_PRESS) {
-		e_attachment_view_show_popup_menu (view, event);
-		return TRUE;
+		/* Non-editable attachment views should only show a
+		 * popup menu when right-clicking on an attachment,
+		 * but editable views can show the menu any time. */
+		if (item_clicked || editable) {
+			e_attachment_view_show_popup_menu (view, event);
+			return TRUE;
+		}
 	}
 
 	return FALSE;

Modified: branches/kill-bonobo/widgets/misc/e-attachment.c
==============================================================================
--- branches/kill-bonobo/widgets/misc/e-attachment.c	(original)
+++ branches/kill-bonobo/widgets/misc/e-attachment.c	Mon Mar 30 22:26:35 2009
@@ -1189,6 +1189,8 @@
 {
 	GFileInfo *file_info;
 	const gchar *content_type;
+	gchar *mime_type;
+	gboolean is_image;
 
 	g_return_val_if_fail (E_IS_ATTACHMENT (attachment), FALSE);
 
@@ -1200,7 +1202,11 @@
 	if (content_type == NULL)
 		return FALSE;
 
-	return g_content_type_is_a (content_type, "image");
+	mime_type = g_content_type_get_mime_type (content_type);
+	is_image = (g_ascii_strncasecmp (mime_type, "image/", 6) == 0);
+	g_free (mime_type);
+
+	return is_image;
 }
 
 gboolean
@@ -1208,6 +1214,8 @@
 {
 	GFileInfo *file_info;
 	const gchar *content_type;
+	gchar *mime_type;
+	gboolean is_rfc822;
 
 	g_return_val_if_fail (E_IS_ATTACHMENT (attachment), FALSE);
 
@@ -1219,7 +1227,11 @@
 	if (content_type == NULL)
 		return FALSE;
 
-	return g_content_type_equals (content_type, "message/rfc822");
+	mime_type = g_content_type_get_mime_type (content_type);
+	is_rfc822 = (g_ascii_strcasecmp (mime_type, "message/rfc822") == 0);
+	g_free (mime_type);
+
+	return is_rfc822;
 }
 
 GList *
@@ -1327,7 +1339,7 @@
 	if (error == NULL)
 		return FALSE;
 
-	/* Steal the reference. */
+	/* Steal the result. */
 	simple = load_context->simple;
 	load_context->simple = NULL;
 
@@ -1359,7 +1371,7 @@
 	gpointer data;
 	gsize size;
 
-	/* Steal the reference. */
+	/* Steal the result. */
 	simple = load_context->simple;
 	load_context->simple = NULL;
 
@@ -1633,7 +1645,7 @@
 
 	attachment_set_file_info (attachment, file_info);
 
-	/* Steal the reference. */
+	/* Steal the result. */
 	simple = load_context->simple;
 	load_context->simple = NULL;
 
@@ -1839,7 +1851,7 @@
 	if (error == NULL)
 		return FALSE;
 
-	/* Steal the reference. */
+	/* Steal the result. */
 	simple = open_context->simple;
 	open_context->simple = NULL;
 
@@ -1861,7 +1873,7 @@
 	gboolean success;
 	GError *error = NULL;
 
-	/* Steal the reference. */
+	/* Steal the result. */
 	simple = open_context->simple;
 	open_context->simple = NULL;
 
@@ -2121,7 +2133,7 @@
 	if (error == NULL)
 		return FALSE;
 
-	/* Steal the reference. */
+	/* Steal the result. */
 	simple = save_context->simple;
 	save_context->simple = NULL;
 
@@ -2248,7 +2260,7 @@
 	if (bytes_read == 0) {
 		GSimpleAsyncResult *simple;
 
-		/* Steal the reference. */
+		/* Steal the result. */
 		simple = save_context->simple;
 		save_context->simple = NULL;
 



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