diff options
author | Matthew Barnes <mbarnes@src.gnome.org> | 2009-03-31 06:26:35 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@src.gnome.org> | 2009-03-31 06:26:35 +0800 |
commit | 04cc4a2cb1bf87417f82d1094ddde611019c0ab8 (patch) | |
tree | feb70083426a3cefcd2a5d2fe5718addb97619a0 | |
parent | 8a1f639a670696e71daac8305ae0823668d29a14 (diff) | |
download | gsoc2013-evolution-04cc4a2cb1bf87417f82d1094ddde611019c0ab8.tar gsoc2013-evolution-04cc4a2cb1bf87417f82d1094ddde611019c0ab8.tar.gz gsoc2013-evolution-04cc4a2cb1bf87417f82d1094ddde611019c0ab8.tar.bz2 gsoc2013-evolution-04cc4a2cb1bf87417f82d1094ddde611019c0ab8.tar.lz gsoc2013-evolution-04cc4a2cb1bf87417f82d1094ddde611019c0ab8.tar.xz gsoc2013-evolution-04cc4a2cb1bf87417f82d1094ddde611019c0ab8.tar.zst gsoc2013-evolution-04cc4a2cb1bf87417f82d1094ddde611019c0ab8.zip |
Saving progress again on the attachment rewrite.
svn path=/branches/kill-bonobo/; revision=37486
-rw-r--r-- | mail/e-mail-attachment-bar.c | 153 | ||||
-rw-r--r-- | mail/em-format-html-display.c | 106 | ||||
-rw-r--r-- | widgets/misc/e-attachment-store.c | 174 | ||||
-rw-r--r-- | widgets/misc/e-attachment-store.h | 14 | ||||
-rw-r--r-- | widgets/misc/e-attachment-view.c | 96 | ||||
-rw-r--r-- | widgets/misc/e-attachment.c | 30 |
6 files changed, 401 insertions, 172 deletions
diff --git a/mail/e-mail-attachment-bar.c b/mail/e-mail-attachment-bar.c index 97f5a7fb00..0043dc383f 100644 --- a/mail/e-mail-attachment-bar.c +++ b/mail/e-mail-attachment-bar.c @@ -44,6 +44,8 @@ struct _EMailAttachmentBarPrivate { 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 @@ mail_attachment_bar_update_status (EMailAttachmentBar *bar) { EAttachmentView *view; EAttachmentStore *store; + GtkActivatable *activatable; GtkExpander *expander; + GtkAction *action; GtkLabel *label; gint num_attachments; guint64 total_size; @@ -116,6 +120,14 @@ mail_attachment_bar_update_status (EMailAttachmentBar *bar) 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 @@ mail_attachment_bar_dispose (GObject *object) 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 @@ mail_attachment_bar_constructed (GObject *object) 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 @@ static void 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 @@ mail_attachment_bar_class_init (EMailAttachmentBarClass *class) 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 @@ mail_attachment_bar_iface_init (EAttachmentViewIface *iface) 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 @@ mail_attachment_bar_init (EMailAttachmentBar *bar) /* 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 @@ mail_attachment_bar_init (EMailAttachmentBar *bar) 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 @@ mail_attachment_bar_init (EMailAttachmentBar *bar) 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)); diff --git a/mail/em-format-html-display.c b/mail/em-format-html-display.c index 1bbe282394..346efff92a 100644 --- a/mail/em-format-html-display.c +++ b/mail/em-format-html-display.c @@ -1319,6 +1319,8 @@ efhd_attachment_button(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObje 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 @@ efhd_attachment_button(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObje 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 @@ efhd_attachment_frame(EMFormat *emf, CamelStream *stream, EMFormatPURI *puri) } 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 @@ efhd_add_bar (EMFormatHTML *efh, { 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; diff --git a/widgets/misc/e-attachment-store.c b/widgets/misc/e-attachment-store.c index 0187d2a8c8..1eb429b41e 100644 --- a/widgets/misc/e-attachment-store.c +++ b/widgets/misc/e-attachment-store.c @@ -672,7 +672,7 @@ exit: gtk_widget_destroy (dialog); } -void +GFile * e_attachment_store_run_save_dialog (EAttachmentStore *store, GList *attachment_list, GtkWindow *parent) @@ -685,13 +685,12 @@ e_attachment_store_run_save_dialog (EAttachmentStore *store, 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 @@ e_attachment_store_run_save_dialog (EAttachmentStore *store, 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; } diff --git a/widgets/misc/e-attachment-store.h b/widgets/misc/e-attachment-store.h index 88b2823313..c672cb3c34 100644 --- a/widgets/misc/e-attachment-store.h +++ b/widgets/misc/e-attachment-store.h @@ -101,11 +101,23 @@ gint e_attachment_store_run_file_chooser_dialog 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 */ diff --git a/widgets/misc/e-attachment-view.c b/widgets/misc/e-attachment-view.c index e9e546e449..6d6079df21 100644 --- a/widgets/misc/e-attachment-view.c +++ b/widgets/misc/e-attachment-view.c @@ -219,11 +219,52 @@ action_remove_cb (GtkAction *action, } 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 @@ action_save_as_cb (GtkAction *action, 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 @@ static GtkActionEntry standard_entries[] = { 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 @@ static GtkActionEntry standard_entries[] = { 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 @@ e_attachment_view_button_press_event (EAttachmentView *view, 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_button_press_event (EAttachmentView *view, 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 @@ e_attachment_view_button_press_event (EAttachmentView *view, } 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; diff --git a/widgets/misc/e-attachment.c b/widgets/misc/e-attachment.c index d06e49dc30..52a3d928f6 100644 --- a/widgets/misc/e-attachment.c +++ b/widgets/misc/e-attachment.c @@ -1189,6 +1189,8 @@ e_attachment_is_image (EAttachment *attachment) { 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 @@ e_attachment_is_image (EAttachment *attachment) 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 @@ e_attachment_is_rfc822 (EAttachment *attachment) { 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 @@ e_attachment_is_rfc822 (EAttachment *attachment) 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 @@ attachment_load_check_for_error (LoadContext *load_context, if (error == NULL) return FALSE; - /* Steal the reference. */ + /* Steal the result. */ simple = load_context->simple; load_context->simple = NULL; @@ -1359,7 +1371,7 @@ attachment_load_finish (LoadContext *load_context) gpointer data; gsize size; - /* Steal the reference. */ + /* Steal the result. */ simple = load_context->simple; load_context->simple = NULL; @@ -1633,7 +1645,7 @@ attachment_load_from_mime_part (LoadContext *load_context) 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 @@ attachment_open_check_for_error (OpenContext *open_context, if (error == NULL) return FALSE; - /* Steal the reference. */ + /* Steal the result. */ simple = open_context->simple; open_context->simple = NULL; @@ -1861,7 +1873,7 @@ attachment_open_file (OpenContext *open_context) gboolean success; GError *error = NULL; - /* Steal the reference. */ + /* Steal the result. */ simple = open_context->simple; open_context->simple = NULL; @@ -2121,7 +2133,7 @@ attachment_save_check_for_error (SaveContext *save_context, if (error == NULL) return FALSE; - /* Steal the reference. */ + /* Steal the result. */ simple = save_context->simple; save_context->simple = NULL; @@ -2248,7 +2260,7 @@ attachment_save_read_cb (GInputStream *input_stream, if (bytes_read == 0) { GSimpleAsyncResult *simple; - /* Steal the reference. */ + /* Steal the result. */ simple = save_context->simple; save_context->simple = NULL; |