aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mail/ChangeLog17
-rw-r--r--mail/em-format-html-display.c326
-rw-r--r--mail/em-format-html.c6
-rw-r--r--mail/em-popup.c154
-rw-r--r--mail/em-popup.h3
-rw-r--r--mail/em-utils.c71
-rw-r--r--mail/em-utils.h1
7 files changed, 542 insertions, 36 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog
index 50c3e2dfb9..24ae4b7313 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -1,3 +1,20 @@
+2005-07-25 Srinivasa Ragavan <sragavan@novell.com>
+
+ * em-format-html-display.c: (efhd_init) (efhd_finalise) ()
+ (efhd_attachment_image) (efhd_attachment_button) (efhd_format_attachment)
+ Added code to create a attachment bar.
+
+ * em-format-html.c: (efh_format_message) Added code to add bar
+ at the beginning of the message.
+
+ * em-popup.[ch]: (em_popup_target_new_attachments) (emp_part_popup_set_background)
+ (emp_standard_menu_factory) Added code to handle the popup menu inside the attachment
+ bar.
+
+ * em-utils.[ch]: (em_utils_edit_filters) (emu_get_save_filesel)
+ (em_utils_save_part) (em_utils_save_messages) Added code to handle save selected and
+ save all options of the attachment bar.
+
2005-07-21 Not Zed <NotZed@Ximian.com>
* em-folder-browser.c: reverted dobey's busted view->hide* menu
diff --git a/mail/em-format-html-display.c b/mail/em-format-html-display.c
index 25dc7622a6..a1da4532a8 100644
--- a/mail/em-format-html-display.c
+++ b/mail/em-format-html-display.c
@@ -45,6 +45,7 @@
#include <gtk/gtkmenuitem.h>
#include <gtk/gtkmain.h>
#include <gtk/gtkdnd.h>
+#include <gtk/gtktoolbutton.h>
#include <glade/glade.h>
@@ -87,6 +88,8 @@
#include "em-icon-stream.h"
#include "em-utils.h"
#include "em-popup.h"
+#include "e-attachment.h"
+#include "e-attachment-bar.h"
#define d(x)
@@ -101,6 +104,18 @@ struct _EMFormatHTMLDisplayPrivate {
GtkWidget *search_case_check;
char *search_text;
int search_wrap; /* are we doing a wrap search */
+
+ /* for Attachment bar */
+ GtkWidget *attachment_bar;
+ GtkWidget *attachment_box;
+ GtkWidget *label;
+ GtkWidget *arrow;
+ GtkWidget *forward;
+ GtkWidget *down;
+ GtkWidget *save;
+ gboolean show_bar;
+ gboolean bar_added;
+ GHashTable *files;
};
static int efhd_html_button_press_event (GtkWidget *widget, GdkEventButton *event, EMFormatHTMLDisplay *efh);
@@ -109,6 +124,8 @@ static void efhd_html_on_url (GtkHTML *html, const char *url, EMFormatHTMLDispla
static void efhd_attachment_frame(EMFormat *emf, CamelStream *stream, EMFormatPURI *puri);
static gboolean efhd_attachment_image(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject);
+static void efhd_message_add_bar(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info);
+static void efhd_attachment_bar_refresh (EMFormatHTMLDisplay *efhd);
struct _attach_puri {
EMFormatPURI puri;
@@ -128,6 +145,10 @@ struct _attach_puri {
int fit_width;
int fit_height;
GtkImage *image;
+
+ /* Signed / Encrypted */
+ camel_cipher_validity_sign_t sign;
+ camel_cipher_validity_encrypt_t encrypt;
};
@@ -254,6 +275,10 @@ efhd_init(GObject *o)
/* we want to convert url's etc */
efh->text_html_flags |= CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS | CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES;
#undef efh
+
+ efhd->priv->show_bar = FALSE;
+ efhd->priv->bar_added = FALSE;
+ efhd->priv->files = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
}
static void
@@ -263,6 +288,9 @@ efhd_finalise(GObject *o)
/* check pending stuff */
+ if (efhd->priv->files)
+ g_hash_table_destroy(efhd->priv->files);
+
g_free(efhd->priv->search_text);
g_free(efhd->priv);
@@ -959,6 +987,7 @@ static EMFormatHandler type_builtin_table[] = {
{ "image/pjpeg", (EMFormatFunc)efhd_image },
{ "x-evolution/message/prefix", (EMFormatFunc)efhd_message_prefix },
+ { "x-evolution/message/post-header", (EMFormatFunc)efhd_message_add_bar },
};
static void
@@ -1007,6 +1036,21 @@ static const EMFormatHandler *efhd_find_handler(EMFormat *emf, const char *mime_
static void efhd_format_clone(EMFormat *emf, CamelFolder *folder, const char *uid, CamelMimeMessage *msg, EMFormat *src)
{
+ EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *) emf;
+
+ if (emf != src) {
+ if (src)
+ efhd->priv->show_bar = ((EMFormatHTMLDisplay *)src)->priv->show_bar;
+ else
+ efhd->priv->show_bar = FALSE;
+ }
+
+ efhd->priv->attachment_bar = NULL;
+ efhd->priv->bar_added = FALSE;
+ if (efhd->priv->files)
+ g_hash_table_destroy(efhd->priv->files);
+ efhd->priv->files = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
((EMFormatClass *)efhd_parent)->format_clone(emf, folder, uid, msg, src);
}
@@ -1370,9 +1414,12 @@ efhd_attachment_image(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObjec
static gboolean
efhd_attachment_button(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject)
{
+ EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *)efh;
+ EAttachment *new;
struct _attach_puri *info;
GtkWidget *hbox, *w, *button, *mainbox;
- char *simple_type;
+ char *simple_type, *tmp, *new_file = NULL;
+ const char *file;
GtkTargetEntry drag_types[] = {
{ NULL, 0, 0 },
{ "text/uri-list", 0, 1 },
@@ -1386,6 +1433,47 @@ efhd_attachment_button(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObje
g_assert(info != NULL);
g_assert(info->forward == NULL);
+ file = camel_mime_part_get_filename(info->puri.part);
+
+ new = e_attachment_new_from_mime_part (info->puri.part);
+
+ if (!file) {
+ file = "attachment.dat";
+ camel_mime_part_set_filename(new->body, 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));
+ camel_mime_part_set_filename(new->body, new_file);
+
+ g_free(new_file);
+ } else {
+ g_hash_table_insert (efhd->priv->files, g_strdup(file), GUINT_TO_POINTER(1));
+ }
+
+ /* Store the status of encryption / signature on the attachment for emblem display
+ * FIXME: May not work well always
+ */
+ new->sign = info->sign;
+ new->encrypt = info->encrypt;
+
+ /* Add the attachment to the bar.*/
+ e_attachment_bar_add_attachment (E_ATTACHMENT_BAR(efhd->priv->attachment_bar), new);
+ efhd_attachment_bar_refresh (efhd);
+
mainbox = gtk_hbox_new(FALSE, 0);
button = gtk_button_new();
@@ -1644,6 +1732,237 @@ type_ok:
}
static void
+attachment_bar_arrow_clicked(GtkWidget *w, EMFormatHTMLDisplay *efhd)
+{
+
+ efhd->priv->show_bar = !efhd->priv->show_bar;
+
+ if (efhd->priv->show_bar) {
+ gtk_widget_show(efhd->priv->attachment_box);
+ gtk_widget_show(efhd->priv->down);
+ gtk_widget_hide(efhd->priv->forward);
+ } else {
+ gtk_widget_hide(efhd->priv->attachment_box);
+ gtk_widget_show(efhd->priv->forward);
+ gtk_widget_hide(efhd->priv->down);
+ }
+}
+
+static void
+attachments_save_all_clicked(GtkWidget *w, EMFormatHTMLDisplay *efhd)
+{
+ GSList *attachment_parts;
+
+ attachment_parts = e_attachment_bar_get_parts(E_ATTACHMENT_BAR(efhd->priv->attachment_bar));
+ em_utils_save_parts(w, _("Select folder to save all attachments..."), attachment_parts);
+}
+
+static void
+efhd_bar_popup_position(GtkMenu *menu, int *x, int *y, gboolean *push_in, gpointer user_data)
+{
+ EAttachmentBar *bar = user_data;
+ GnomeIconList *icon_list = user_data;
+ GList *selection;
+ GnomeCanvasPixbuf *image;
+
+ gdk_window_get_origin (((GtkWidget*) bar)->window, x, y);
+
+ selection = gnome_icon_list_get_selection (icon_list);
+ if (selection == NULL)
+ return;
+
+ image = gnome_icon_list_get_icon_pixbuf_item (icon_list, (gint)selection->data);
+ if (image == NULL)
+ return;
+
+ /* Put menu to the center of icon. */
+ *x += (int)(image->item.x1 + image->item.x2) / 2;
+ *y += (int)(image->item.y1 + image->item.y2) / 2;
+}
+
+static void
+efhd_bar_save_selected(EPopup *ep, EPopupItem *item, EMFormatHTMLDisplay *efhd)
+{
+ GSList *attachment_parts, *tmp;
+ GSList *parts = NULL;
+
+ attachment_parts = e_attachment_bar_get_selected(E_ATTACHMENT_BAR(efhd->priv->attachment_bar));
+
+ for (tmp = attachment_parts; tmp; tmp=tmp->next)
+ parts = g_slist_prepend(parts, ((EAttachment *)tmp->data)->body);
+
+ parts = g_slist_reverse(parts);
+ em_utils_save_parts(efhd->priv->attachment_bar, _("Select folder to save selected attachments..."), 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},
+};
+
+static gboolean
+efhd_bar_button_press_event(EAttachmentBar *bar, GdkEventButton *event, EMFormat *emf)
+{
+ GtkMenu *menu;
+ GSList *list=NULL;
+ EPopupTarget *target;
+ EMPopup *emp;
+ GSList *menus = NULL;
+ int i;
+
+ if (event && event->button != 3)
+ return FALSE;
+
+ /** @HookPoint-EMPopup: Attachment Bar Context Menu
+ * @Id: org.gnome.evolution.mail.attachments.popup
+ * @Class: org.gnome.evolution.mail.popup:1.0
+ * @Target: EMPopupTargetPart
+ *
+ * This is the drop-down menu shown when a user clicks on the attachment bar
+ * when attachments are selected.
+ */
+ emp = em_popup_new("org.gnome.evolution.mail.attachments.popup");
+
+ /* Add something like save-selected, foward selected attachments in a mail etc....*/
+ list = e_attachment_bar_get_selected(bar);
+
+ /* Lets not propagate any more the r-click which is intended to us*/
+ if ( g_slist_length (list) == 0)
+ return TRUE;
+
+ target = (EPopupTarget *)em_popup_target_new_attachments(emp, list);
+ for (i=0; i<2; i++)
+ menus = g_slist_prepend(menus, &efhd_bar_menu_items[i]);
+ e_popup_add_items((EPopup *)emp, menus, NULL, efhd_menu_items_free, emf);
+
+ ((EMPopupTargetPart *)target)->target.widget = (GtkWidget *)bar;
+ menu = e_popup_create_menu_once((EPopup *)emp, (EPopupTarget *)target, 0);
+ if (event)
+ gtk_menu_popup(menu, NULL, NULL, NULL, NULL, event->button, event->time);
+ else
+ gtk_menu_popup(menu, NULL, NULL, (GtkMenuPositionFunc)efhd_bar_popup_position, bar, 0, gtk_get_current_event_time());
+
+ return TRUE;
+}
+
+static gboolean
+efhd_bar_popup_menu_event (EAttachmentBar *bar, EMFormat *emf)
+{
+ return efhd_bar_button_press_event(bar, NULL, emf);
+}
+
+static void
+efhd_attachment_bar_refresh (EMFormatHTMLDisplay *efhd)
+{
+ int nattachments;
+
+ if (!efhd->priv->attachment_bar)
+ return;
+
+ nattachments = e_attachment_bar_get_num_attachments (E_ATTACHMENT_BAR(efhd->priv->attachment_bar));
+ if (nattachments) {
+ char *txt;
+
+ /* Cant i put in the number of attachments here ?*/
+ txt = g_strdup_printf(ngettext("%d Attachment", "%d Attachments", nattachments), nattachments);
+ gtk_label_set_text ((GtkLabel *)efhd->priv->label, txt);
+ g_free (txt);
+
+ /* Enable the expander button and the save all button.*/
+ gtk_widget_set_sensitive (efhd->priv->arrow, TRUE);
+ gtk_widget_set_sensitive (efhd->priv->save, TRUE);
+ }
+}
+
+static gboolean
+efhd_add_bar(EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject *pobject)
+{
+ EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *)efh;
+ struct _EMFormatHTMLDisplayPrivate *priv = efhd->priv;
+ GtkWidget *hbox1, *hbox2, *hbox3, *vbox, *txt, *image;
+ int width, height;
+
+ priv->attachment_bar = e_attachment_bar_new(NULL);
+ ((EAttachmentBar *)priv->attachment_bar)->expand = TRUE;
+
+ priv->forward = gtk_arrow_new(GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
+ priv->down = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
+ hbox3 = gtk_hbox_new (FALSE, 0);
+ gtk_box_pack_start ((GtkBox *)hbox3, priv->forward, FALSE, FALSE, 0);
+ gtk_box_pack_start ((GtkBox *)hbox3, priv->down, FALSE, FALSE, 0);
+ priv->arrow = (GtkWidget *)gtk_tool_button_new(hbox3, NULL);
+
+ priv->label = gtk_label_new(_("No Attachment"));
+ priv->save = gtk_button_new();
+ image = gtk_image_new_from_stock ("gtk-save", GTK_ICON_SIZE_BUTTON);
+ txt = gtk_label_new(_("Save All"));
+ hbox1 = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start((GtkBox *)hbox1, image, FALSE, FALSE, 2);
+ gtk_box_pack_start((GtkBox *)hbox1, txt, FALSE, FALSE, 0);
+
+ gtk_container_add((GtkContainer *)priv->save, hbox1);
+
+ gtk_widget_set_sensitive(priv->arrow, FALSE);
+ gtk_widget_set_sensitive(priv->save, FALSE);
+
+ hbox2 = gtk_hbox_new (FALSE, 0);
+ gtk_box_pack_start ((GtkBox *)hbox2, priv->arrow, FALSE, FALSE, 0);
+ gtk_box_pack_start ((GtkBox *)hbox2, priv->label, FALSE, FALSE, 2);
+ gtk_box_pack_start ((GtkBox *)hbox2, priv->save, FALSE, FALSE, 2);
+
+ priv->attachment_box = gtk_hbox_new (FALSE, 0);
+ gtk_box_pack_start ((GtkBox *)priv->attachment_box, priv->attachment_bar, TRUE, TRUE, 0);
+
+ gtk_widget_get_size_request(priv->attachment_bar, &width, &height);
+
+ /* FIXME: What if the text is more?. Should we reduce the text with appending ...?
+ * or resize the bar? How to figure out that, it needs more space? */
+ gtk_widget_set_size_request (priv->attachment_bar,
+ ((GtkWidget *)efh->html)->parent->allocation.width - /* FIXME */36,
+ 84 /* FIXME: Default show only one row, Dont hardcode size*/);
+
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_box_pack_start ((GtkBox *)vbox, hbox2, FALSE, FALSE, 2);
+ gtk_box_pack_start ((GtkBox *)vbox, priv->attachment_box, TRUE, TRUE, 2);
+
+ gtk_container_add ((GtkContainer *)eb, vbox);
+ gtk_widget_show_all ((GtkWidget *)eb);
+
+ if (priv->show_bar) {
+ gtk_widget_show(priv->down);
+ gtk_widget_hide(priv->forward);
+ } else {
+ gtk_widget_show(priv->forward);
+ gtk_widget_hide(priv->down);
+ gtk_widget_hide(priv->attachment_box);
+ }
+
+ g_signal_connect (priv->arrow, "clicked", G_CALLBACK(attachment_bar_arrow_clicked), efh);
+ g_signal_connect (priv->attachment_bar, "button_press_event", G_CALLBACK(efhd_bar_button_press_event), efhd);
+ g_signal_connect (priv->attachment_bar, "popup-menu", G_CALLBACK(efhd_bar_popup_menu_event), efhd);
+ g_signal_connect (priv->save, "clicked", G_CALLBACK(attachments_save_all_clicked), efh);
+
+ return TRUE;
+}
+
+static void
+efhd_message_add_bar(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info)
+{
+ EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *) emf;
+ const char *classid = "attachment-bar";
+
+ if (efhd->priv->bar_added)
+ return;
+
+ efhd->priv->bar_added = TRUE;
+ em_format_html_add_pobject((EMFormatHTML *)emf, sizeof(EMFormatHTMLPObject), classid, part, efhd_add_bar);
+ camel_stream_printf(stream, "<td><object classid=\"%s\"></object></td>", classid);
+}
+
+static void
efhd_format_attachment(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const char *mime_type, const EMFormatHandler *handle)
{
char *classid, *text, *html;
@@ -1656,6 +1975,11 @@ efhd_format_attachment(EMFormat *emf, CamelStream *stream, CamelMimePart *part,
info->shown = em_format_is_inline(emf, info->puri.part_id, info->puri.part, handle);
info->snoop_mime_type = emf->snoop_mime_type;
+ if (emf->valid) {
+ info->sign = emf->valid->sign.status;
+ info->encrypt = emf->valid->encrypt.status;
+ }
+
camel_stream_write_string(stream,
EM_FORMAT_HTML_VPAD
"<table cellspacing=0 cellpadding=0><tr><td>"
diff --git a/mail/em-format-html.c b/mail/em-format-html.c
index 95190101ce..5e9b2626a9 100644
--- a/mail/em-format-html.c
+++ b/mail/em-format-html.c
@@ -1830,6 +1830,8 @@ efh_format_headers(EMFormatHTML *efh, CamelStream *stream, CamelMedium *part)
static void efh_format_message(EMFormat *emf, CamelStream *stream, CamelMimePart *part, const EMFormatHandler *info)
{
+ const EMFormatHandler *handle;
+
/* TODO: make this validity stuff a method */
EMFormatHTML *efh = (EMFormatHTML *) emf;
CamelCipherValidity *save = emf->valid, *save_parent = emf->valid_parent;
@@ -1842,6 +1844,10 @@ static void efh_format_message(EMFormat *emf, CamelStream *stream, CamelMimePart
if (!efh->hide_headers)
efh_format_headers(efh, stream, (CamelMedium *)part);
+
+ handle = em_format_find_handler(emf, "x-evolution/message/post-header");
+ if (handle)
+ handle->handler(emf, stream, part, handle);
camel_stream_printf(stream, EM_FORMAT_HTML_VPAD);
em_format_part(emf, stream, part);
diff --git a/mail/em-popup.c b/mail/em-popup.c
index c419e8a1d4..965365957e 100644
--- a/mail/em-popup.c
+++ b/mail/em-popup.c
@@ -64,6 +64,7 @@
#include <gconf/gconf-client.h>
#include <e-util/e-util.h>
+#include "e-attachment.h"
static void emp_standard_menu_factory(EPopup *emp, void *data);
@@ -365,8 +366,17 @@ em_popup_target_new_attachments(EMPopup *emp, GSList *attachments)
t->attachments = attachments;
if (len > 0)
mask &= ~ EM_POPUP_ATTACHMENTS_MANY;
- if (len == 1)
+ if (len == 1 && ((EAttachment *)attachments->data)->is_available_local) {
+
+ if (camel_content_type_is(((CamelDataWrapper *) ((EAttachment *) attachments->data)->body)->mime_type, "image", "*"))
+ mask &= ~ EM_POPUP_ATTACHMENTS_IMAGE;
+ if (CAMEL_IS_MIME_MESSAGE(camel_medium_get_content_object((CamelMedium *) ((EAttachment *) attachments->data)->body)))
+ mask &= ~EM_POPUP_ATTACHMENTS_MESSAGE;
+
mask &= ~ EM_POPUP_ATTACHMENTS_ONE;
+ }
+ if (len > 1)
+ mask &= ~ EM_POPUP_ATTACHMENTS_MULTIPLE;
t->target.mask = mask;
return t;
@@ -377,26 +387,39 @@ em_popup_target_new_attachments(EMPopup *emp, GSList *attachments)
static void
emp_part_popup_saveas(EPopup *ep, EPopupItem *item, void *data)
{
- EMPopupTargetPart *t = (EMPopupTargetPart *)ep->target;
+ EPopupTarget *t = ep->target;
+ CamelMimePart *part = NULL;
- em_utils_save_part(ep->target->widget, _("Save As..."), t->part);
+ /* If it is of type EM_POPUP_TARGET_ATTACHMENTS, we can assume the length is one. */
+ if (t->type == EM_POPUP_TARGET_ATTACHMENTS)
+ part = ((EAttachment *) ((EMPopupTargetAttachments *) t)->attachments->data)->body;
+ else
+ part = ((EMPopupTargetPart *) t)->part;
+
+ em_utils_save_part(ep->target->widget, _("Save As..."), part);
}
static void
emp_part_popup_set_background(EPopup *ep, EPopupItem *item, void *data)
{
- EMPopupTargetPart *t = (EMPopupTargetPart *)ep->target;
+ EPopupTarget *t = ep->target;
GConfClient *gconf;
char *str, *filename, *path, *extension;
unsigned int i=1;
+ CamelMimePart *part = NULL;
+
+ if (t->type == EM_POPUP_TARGET_ATTACHMENTS)
+ part = ((EAttachment *) ((EMPopupTargetAttachments *) t)->attachments->data)->body;
+ else
+ part = ((EMPopupTargetPart *) t)->part;
- filename = g_strdup(camel_mime_part_get_filename(t->part));
+ filename = g_strdup(camel_mime_part_get_filename(part));
/* if filename is blank, create a default filename based on MIME type */
if (!filename || !filename[0]) {
CamelContentType *ct;
- ct = camel_mime_part_get_content_type(t->part);
+ ct = camel_mime_part_get_content_type(part);
g_free (filename);
filename = g_strdup_printf (_("untitled_image.%s"), ct->subtype);
}
@@ -420,7 +443,7 @@ emp_part_popup_set_background(EPopup *ep, EPopupItem *item, void *data)
g_free(filename);
- if (em_utils_save_part_to_file(ep->target->widget, path, t->part)) {
+ if (em_utils_save_part_to_file(ep->target->widget, path, part)) {
gconf = gconf_client_get_default();
/* if the filename hasn't changed, blank the filename before
@@ -452,41 +475,65 @@ emp_part_popup_set_background(EPopup *ep, EPopupItem *item, void *data)
static void
emp_part_popup_reply_sender(EPopup *ep, EPopupItem *item, void *data)
{
- EMPopupTargetPart *t = (EMPopupTargetPart *)ep->target;
+ EPopupTarget *t = ep->target;
CamelMimeMessage *message;
+ CamelMimePart *part;
+
+ if (t->type == EM_POPUP_TARGET_ATTACHMENTS)
+ part = ((EAttachment *) ((EMPopupTargetAttachments *) t)->attachments->data)->body;
+ else
+ part = ((EMPopupTargetPart *) t)->part;
- message = (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *)t->part);
+ message = (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *)part);
em_utils_reply_to_message(NULL, NULL, message, REPLY_MODE_SENDER, NULL);
}
static void
emp_part_popup_reply_list (EPopup *ep, EPopupItem *item, void *data)
{
- EMPopupTargetPart *t = (EMPopupTargetPart *)ep->target;
+ EPopupTarget *t = ep->target;
CamelMimeMessage *message;
-
- message = (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *)t->part);
+ CamelMimePart *part;
+
+ if (t->type == EM_POPUP_TARGET_ATTACHMENTS)
+ part = ((EAttachment *) ((EMPopupTargetAttachments *) t)->attachments->data)->body;
+ else
+ part = ((EMPopupTargetPart *) t)->part;
+
+ message = (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *)part);
em_utils_reply_to_message(NULL, NULL, message, REPLY_MODE_LIST, NULL);
}
static void
emp_part_popup_reply_all (EPopup *ep, EPopupItem *item, void *data)
{
- EMPopupTargetPart *t = (EMPopupTargetPart *)ep->target;
+ EPopupTarget *t = ep->target;
CamelMimeMessage *message;
+ CamelMimePart *part;
+
+ if (t->type == EM_POPUP_TARGET_ATTACHMENTS)
+ part = ((EAttachment *) ((EMPopupTargetAttachments *) t)->attachments->data)->body;
+ else
+ part = ((EMPopupTargetPart *) t)->part;
- message = (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *)t->part);
+ message = (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *)part);
em_utils_reply_to_message(NULL, NULL, message, REPLY_MODE_ALL, NULL);
}
static void
emp_part_popup_forward (EPopup *ep, EPopupItem *item, void *data)
{
- EMPopupTargetPart *t = (EMPopupTargetPart *)ep->target;
+ EPopupTarget *t = ep->target;
CamelMimeMessage *message;
+ CamelMimePart *part;
+
+ if (t->type == EM_POPUP_TARGET_ATTACHMENTS)
+ part = ((EAttachment *) ((EMPopupTargetAttachments *) t)->attachments->data)->body;
+ else
+ part = ((EMPopupTargetPart *) t)->part;
/* TODO: have a emfv specific override so we can get the parent folder uri */
- message = (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *) t->part);
+ message = (CamelMimeMessage *)camel_medium_get_content_object((CamelMedium *) part);
em_utils_forward_message(message, NULL);
}
@@ -501,6 +548,17 @@ static EMPopupItem emp_standard_object_popups[] = {
{ E_POPUP_ITEM, "20.part.00", N_("_Forward"), emp_part_popup_forward, NULL, "stock_mail-forward", EM_POPUP_PART_MESSAGE },
};
+static EMPopupItem emp_attachment_object_popups[] = {
+ { E_POPUP_ITEM, "00.attach.00", N_("_Save As..."), emp_part_popup_saveas, NULL, "stock_save-as", 0 },
+ { E_POPUP_ITEM, "00.attach.10", N_("Set as _Background"), emp_part_popup_set_background, NULL, NULL, EM_POPUP_ATTACHMENTS_IMAGE },
+ { E_POPUP_BAR, "05.attach", NULL, NULL, NULL, NULL, EM_POPUP_ATTACHMENTS_MESSAGE },
+ { E_POPUP_ITEM, "05.attach.00", N_("_Reply to sender"), emp_part_popup_reply_sender, NULL, "stock_mail-reply" , EM_POPUP_ATTACHMENTS_MESSAGE },
+ { E_POPUP_ITEM, "05.attach.01", N_("Reply to _List"), emp_part_popup_reply_list, NULL, NULL, EM_POPUP_ATTACHMENTS_MESSAGE},
+ { E_POPUP_ITEM, "05.attach.03", N_("Reply to _All"), emp_part_popup_reply_all, NULL, "stock_mail-reply-to-all", EM_POPUP_ATTACHMENTS_MESSAGE},
+ { E_POPUP_BAR, "05.attach.10", NULL, NULL, NULL, NULL, EM_POPUP_ATTACHMENTS_MESSAGE },
+ { E_POPUP_ITEM, "05.attach.15", N_("_Forward"), emp_part_popup_forward, NULL, "stock_mail-forward", EM_POPUP_ATTACHMENTS_MESSAGE },
+};
+
static const EPopupItem emp_standard_part_apps_bar = { E_POPUP_BAR, "99.object" };
/* ********************************************************************** */
@@ -563,9 +621,15 @@ static void
emp_apps_open_in(EPopup *ep, EPopupItem *item, void *data)
{
char *path;
- EMPopupTargetPart *target = (EMPopupTargetPart *)ep->target;
+ EPopupTarget *target = ep->target;
+ CamelMimePart *part;
- path = em_utils_temp_save_part(target->target.widget, target->part);
+ if (target->type == EM_POPUP_TARGET_ATTACHMENTS)
+ part = ((EAttachment *) ((EMPopupTargetAttachments *) target)->attachments->data)->body;
+ else
+ part = ((EMPopupTargetPart *) target)->part;
+
+ path = em_utils_temp_save_part(target->widget, part);
if (path) {
GnomeVFSMimeApplication *app = item->user_data;
char *uri;
@@ -610,6 +674,9 @@ emp_standard_menu_factory(EPopup *emp, void *data)
int i, len;
EPopupItem *items;
GSList *menus = NULL;
+ GList *apps = NULL;
+ char *mime_type = NULL;
+ const char *filename = NULL;
switch (emp->target->type) {
#if 0
@@ -627,14 +694,42 @@ emp_standard_menu_factory(EPopup *emp, void *data)
break; }
case EM_POPUP_TARGET_PART: {
EMPopupTargetPart *t = (EMPopupTargetPart *)emp->target;
- GList *apps = gnome_vfs_mime_get_all_applications(t->mime_type);
+ mime_type = g_strdup(t->mime_type);
+ filename = camel_mime_part_get_filename(t->part);
- /* FIXME: use the snoop_part stuff from em-format.c */
- if (apps == NULL && strcmp(t->mime_type, "application/octet-stream") == 0) {
- const char *filename, *name_type;
-
- filename = camel_mime_part_get_filename(t->part);
+ items = emp_standard_object_popups;
+ len = LEN(emp_standard_object_popups);
+ break; }
+ case EM_POPUP_TARGET_ATTACHMENTS: {
+ EMPopupTargetAttachments *t = (EMPopupTargetAttachments *)emp->target;
+ GSList *list = t->attachments;
+ EAttachment *attachment;
+
+ if (g_slist_length(list) != 1 || !((EAttachment *)list->data)->is_available_local) {
+ items = NULL;
+ len = 0;
+ break;
+ }
+ /* Only one attachment selected */
+ attachment = list->data;
+ mime_type = camel_data_wrapper_get_mime_type((CamelDataWrapper *)attachment->body);
+ filename = camel_mime_part_get_filename(attachment->body);
+
+ items = emp_attachment_object_popups;
+ len = LEN(emp_attachment_object_popups);
+ break; }
+ default:
+ items = NULL;
+ len = 0;
+ }
+
+ if (mime_type) {
+ apps = gnome_vfs_mime_get_all_applications(mime_type);
+
+ if (apps == NULL && strcmp(mime_type, "application/octet-stream") == 0) {
+ const char *name_type;
+
if (filename) {
/* GNOME-VFS will misidentify TNEF attachments as MPEG */
if (!strcmp (filename, "winmail.dat"))
@@ -645,6 +740,7 @@ emp_standard_menu_factory(EPopup *emp, void *data)
apps = gnome_vfs_mime_get_all_applications(name_type);
}
}
+ g_free (mime_type);
if (apps) {
GString *label = g_string_new("");
@@ -676,13 +772,6 @@ emp_standard_menu_factory(EPopup *emp, void *data)
g_string_free(label, TRUE);
g_list_free(apps);
}
-
- items = emp_standard_object_popups;
- len = LEN(emp_standard_object_popups);
- break; }
- default:
- items = NULL;
- len = 0;
}
for (i=0;i<len;i++) {
@@ -769,6 +858,9 @@ static const EPopupHookTargetMask emph_folder_masks[] = {
static const EPopupHookTargetMask emph_attachments_masks[] = {
{ "one", EM_POPUP_ATTACHMENTS_ONE },
{ "many", EM_POPUP_ATTACHMENTS_MANY },
+ { "multiple", EM_POPUP_ATTACHMENTS_MULTIPLE },
+ { "image", EM_POPUP_ATTACHMENTS_IMAGE },
+ { "message", EM_POPUP_ATTACHMENTS_MESSAGE },
{ 0 }
};
diff --git a/mail/em-popup.h b/mail/em-popup.h
index dc032f6783..6ae0623099 100644
--- a/mail/em-popup.h
+++ b/mail/em-popup.h
@@ -161,6 +161,9 @@ enum _em_popup_target_folder_t {
enum _em_popup_target_attachments_t {
EM_POPUP_ATTACHMENTS_ONE = 1<<0, /* only 1 selected */
EM_POPUP_ATTACHMENTS_MANY = 1<<1, /* one or more selected */
+ EM_POPUP_ATTACHMENTS_MULTIPLE = 1<<2, /* More than 1 selected */
+ EM_POPUP_ATTACHMENTS_IMAGE = 1<<3, /* Image selected */
+ EM_POPUP_ATTACHMENTS_MESSAGE = 1<<4 /* Message selected */
};
typedef struct _EMPopupTargetSelect EMPopupTargetSelect;
diff --git a/mail/em-utils.c b/mail/em-utils.c
index 38b89078ec..5bd70e5be3 100644
--- a/mail/em-utils.c
+++ b/mail/em-utils.c
@@ -300,7 +300,7 @@ em_utils_edit_filters (GtkWidget *parent)
/* Saving messages... */
static GtkWidget *
-emu_get_save_filesel (GtkWidget *parent, const char *title, const char *name)
+emu_get_save_filesel (GtkWidget *parent, const char *title, const char *name, GtkFileChooserAction action)
{
GtkWidget *filesel;
const char *dir;
@@ -310,7 +310,7 @@ emu_get_save_filesel (GtkWidget *parent, const char *title, const char *name)
#ifdef USE_GTKFILECHOOSER
filesel = gtk_file_chooser_dialog_new (title,
NULL,
- GTK_FILE_CHOOSER_ACTION_SAVE,
+ action,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_SAVE, GTK_RESPONSE_OK,
NULL);
@@ -439,12 +439,75 @@ em_utils_save_part(GtkWidget *parent, const char *prompt, CamelMimePart *part)
}
}
- filesel = emu_get_save_filesel(parent, prompt, name);
+ filesel = emu_get_save_filesel(parent, prompt, name, GTK_FILE_CHOOSER_ACTION_SAVE);
camel_object_ref(part);
g_signal_connect (filesel, "response", G_CALLBACK (emu_save_part_response), part);
gtk_widget_show (filesel);
}
+static void
+emu_save_parts_response (GtkWidget *filesel, int response, GSList *parts)
+{
+ char *path = NULL;
+ GSList *selected;
+ if (response == GTK_RESPONSE_OK) {
+#ifdef USE_GTKFILECHOOSER
+ path = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (filesel));
+#else
+ path = gtk_file_selection_get_filename (GTK_FILE_SELECTION (filesel));
+#endif
+
+ emu_update_save_path(path);
+
+ for ( selected = parts; selected != NULL; selected = selected->next) {
+ const char *file_name;
+ char *safe_name = NULL;
+ char *file_path;
+ CamelMimePart *part = selected->data;
+
+ file_name = camel_mime_part_get_filename(part);
+ if (file_name == NULL) {
+ if (CAMEL_IS_MIME_MESSAGE(part)) {
+ file_name = camel_mime_message_get_subject((CamelMimeMessage *)part);
+ if (file_name == NULL)
+ file_name = _("message");
+ } else {
+ file_name = _("attachment");
+ }
+ } else {
+ safe_name = g_strdup(file_name);
+ e_filename_make_safe(safe_name);
+ file_name = safe_name;
+ }
+
+ file_path = g_build_filename (path, file_name, NULL);
+ if (!g_file_test(file_path, (G_FILE_TEST_EXISTS)))
+ mail_save_part(part, file_path, NULL, NULL);
+ else
+ g_warning ("Could not save %s. File already exists", file_path);
+
+ g_free (file_path);
+ g_free (safe_name);
+ }
+
+ g_free (path);
+ }
+
+ g_slist_free (parts);
+ gtk_widget_destroy((GtkWidget *)filesel);
+}
+
+void
+em_utils_save_parts (GtkWidget *parent, const char *prompt, GSList * parts)
+{
+ GtkWidget *filesel;
+
+ filesel = emu_get_save_filesel (parent, prompt, NULL, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
+ g_signal_connect (filesel, "response", G_CALLBACK (emu_save_parts_response), parts);
+ gtk_widget_show (filesel);
+}
+
+
/**
* em_utils_save_part_to_file:
* @parent: parent window
@@ -542,7 +605,7 @@ em_utils_save_messages (GtkWidget *parent, CamelFolder *folder, GPtrArray *uids)
g_return_if_fail (CAMEL_IS_FOLDER (folder));
g_return_if_fail (uids != NULL);
- filesel = emu_get_save_filesel(parent, _("Save Message..."), NULL);
+ filesel = emu_get_save_filesel(parent, _("Save Message..."), NULL, GTK_FILE_CHOOSER_ACTION_SAVE);
camel_object_ref(folder);
data = g_malloc(sizeof(struct _save_messages_data));
diff --git a/mail/em-utils.h b/mail/em-utils.h
index 4aa0d67389..0b27628dcb 100644
--- a/mail/em-utils.h
+++ b/mail/em-utils.h
@@ -77,6 +77,7 @@ void em_utils_selection_set_urilist(struct _GtkSelectionData *data, struct _Came
void em_utils_selection_get_urilist(struct _GtkSelectionData *data, struct _CamelFolder *folder);
char *em_utils_temp_save_part(struct _GtkWidget *parent, struct _CamelMimePart *part);
+void em_utils_save_parts (struct _GtkWidget *parent, const char *prompt, GSList * parts);
gboolean em_utils_folder_is_drafts(struct _CamelFolder *folder, const char *uri);
gboolean em_utils_folder_is_sent(struct _CamelFolder *folder, const char *uri);