diff options
Diffstat (limited to 'composer/e-msg-composer.c')
-rw-r--r-- | composer/e-msg-composer.c | 1184 |
1 files changed, 320 insertions, 864 deletions
diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c index b509a97ce8..dde9ff40aa 100644 --- a/composer/e-msg-composer.c +++ b/composer/e-msg-composer.c @@ -23,17 +23,6 @@ * */ -/* - - TODO - - - Somehow users should be able to see if any file (s) are attached even when - the attachment bar is not shown. - - Should use EventSources to keep track of global changes made to configuration - values. Right now it ignores the problem olympically. Miguel. -*/ - #ifdef HAVE_CONFIG_H #include <config.h> #endif @@ -62,49 +51,40 @@ #include "misc/e-charset-picker.h" #include "misc/e-expander.h" #include "e-util/e-error.h" +#include "e-util/e-mktemp.h" #include "e-util/e-plugin-ui.h" #include "e-util/e-util-private.h" -#include "e-util/e-util.h" -#include "e-util/e-mktemp.h" -#include <mail/em-event.h> +#include "e-util/e-account-utils.h" +#include "e-util/e-signature-utils.h" #include "e-signature-combo-box.h" +#include "shell/e-shell.h" -#include <camel/camel-session.h> #include <camel/camel-charset-map.h> +#include <camel/camel-cipher-context.h> +#include <camel/camel-folder.h> +#include <camel/camel-gpg-context.h> #include <camel/camel-iconv.h> -#include <camel/camel-stream-filter.h> #include <camel/camel-mime-filter-charset.h> -#include <camel/camel-stream-mem.h> -#include <camel/camel-stream-fs.h> #include <camel/camel-mime-filter-tohtml.h> -#include <camel/camel-multipart-signed.h> #include <camel/camel-multipart-encrypted.h> +#include <camel/camel-multipart-signed.h> +#include <camel/camel-stream-filter.h> +#include <camel/camel-stream-fs.h> +#include <camel/camel-stream-mem.h> #include <camel/camel-string-utils.h> -#include <camel/camel-cipher-context.h> #if defined (HAVE_NSS) #include <camel/camel-smime-context.h> #endif #include "mail/em-utils.h" -#include "mail/em-composer-utils.h" -#include "mail/mail-config.h" -#include "mail/mail-crypto.h" #include "mail/mail-tools.h" -#include "mail/mail-ops.h" -#include "mail/mail-mt.h" -#include "mail/mail-session.h" -#include "mail/em-popup.h" -#include "mail/em-menu.h" #include "e-msg-composer.h" #include "e-attachment.h" -#include "e-attachment-bar.h" #include "e-composer-autosave.h" #include "e-composer-private.h" #include "e-composer-header-table.h" -#include "evolution-shell-component-utils.h" - #ifdef HAVE_XFREE #include <X11/XF86keysym.h> #endif @@ -149,42 +129,10 @@ typedef enum { enum { SEND, SAVE_DRAFT, + PRINT, LAST_SIGNAL }; -enum { - DND_TYPE_MESSAGE_RFC822, - DND_TYPE_X_UID_LIST, - DND_TYPE_TEXT_URI_LIST, - DND_TYPE_NETSCAPE_URL, - DND_TYPE_TEXT_VCARD, - DND_TYPE_TEXT_CALENDAR -}; - -static GtkTargetEntry drop_types[] = { - { "message/rfc822", 0, DND_TYPE_MESSAGE_RFC822 }, - { "x-uid-list", 0, DND_TYPE_X_UID_LIST }, - { "text/uri-list", 0, DND_TYPE_TEXT_URI_LIST }, - { "_NETSCAPE_URL", 0, DND_TYPE_NETSCAPE_URL }, - { "text/x-vcard", 0, DND_TYPE_TEXT_VCARD }, - { "text/calendar", 0, DND_TYPE_TEXT_CALENDAR } -}; - -static struct { - gchar *target; - GdkAtom atom; - guint32 actions; -} drag_info[] = { - { "message/rfc822", NULL, GDK_ACTION_COPY }, - { "x-uid-list", NULL, GDK_ACTION_ASK | - GDK_ACTION_MOVE | - GDK_ACTION_COPY }, - { "text/uri-list", NULL, GDK_ACTION_COPY }, - { "_NETSCAPE_URL", NULL, GDK_ACTION_COPY }, - { "text/x-vcard", NULL, GDK_ACTION_COPY }, - { "text/calendar", NULL, GDK_ACTION_COPY } -}; - static gpointer parent_class; static guint signals[LAST_SIGNAL]; @@ -195,7 +143,6 @@ static GSList *all_composers = NULL; static GList *add_recipients (GList *list, const gchar *recips); static void handle_mailto (EMsgComposer *composer, const gchar *mailto); -static void handle_uri (EMsgComposer *composer, const gchar *uri, gboolean html_dnd); /* used by e_msg_composer_add_message_attachments () */ static void add_attachments_from_multipart (EMsgComposer *composer, CamelMultipart *multipart, @@ -527,7 +474,8 @@ build_message (EMsgComposer *composer, GtkhtmlEditor *editor; EMsgComposerPrivate *p = composer->priv; - EAttachmentBar *attachment_bar; + EAttachmentView *view; + EAttachmentStore *store; EComposerHeaderTable *table; GtkToggleAction *action; CamelDataWrapper *plain, *html, *current; @@ -537,6 +485,7 @@ build_message (EMsgComposer *composer, CamelMultipart *body = NULL; CamelContentType *type; CamelMimeMessage *new; + CamelSession *session; CamelStream *stream; CamelMimePart *part; CamelException ex; @@ -554,7 +503,9 @@ build_message (EMsgComposer *composer, editor = GTKHTML_EDITOR (composer); table = e_msg_composer_get_header_table (composer); account = e_composer_header_table_get_account (table); - attachment_bar = E_ATTACHMENT_BAR (p->attachment_bar); + view = e_msg_composer_get_attachment_view (composer); + store = e_attachment_view_get_store (view); + session = e_msg_composer_get_session (composer); /* evil kludgy hack for Redirect */ if (p->redirect) { @@ -714,7 +665,7 @@ build_message (EMsgComposer *composer, } else current = plain; - if (e_attachment_bar_get_num_attachments (attachment_bar)) { + if (e_attachment_store_get_num_attachments (store) > 0) { CamelMultipart *multipart = camel_multipart_new (); if (p->is_alternative) { @@ -733,7 +684,8 @@ build_message (EMsgComposer *composer, camel_multipart_add_part (multipart, part); camel_object_unref (part); - e_attachment_bar_to_multipart (attachment_bar, multipart, p->charset); + e_attachment_store_add_to_multipart ( + store, multipart, p->charset); if (p->is_alternative) { for (i = camel_multipart_get_number (multipart); i > 1; i--) { @@ -805,8 +757,14 @@ build_message (EMsgComposer *composer, if (pgp_sign) { CamelMimePart *npart = camel_mime_part_new (); - cipher = mail_crypto_get_pgp_cipher_context (account); - camel_cipher_sign (cipher, pgp_userid, CAMEL_CIPHER_HASH_SHA1, part, npart, &ex); + cipher = camel_gpg_context_new (session); + if (account != NULL) + camel_gpg_context_set_always_trust ( + CAMEL_GPG_CONTEXT (cipher), + account->pgp_always_trust); + camel_cipher_sign ( + cipher, pgp_userid, CAMEL_CIPHER_HASH_SHA1, + part, npart, &ex); camel_object_unref (cipher); if (camel_exception_is_set (&ex)) { @@ -825,8 +783,14 @@ build_message (EMsgComposer *composer, if (account && account->pgp_encrypt_to_self && pgp_userid) g_ptr_array_add (recipients, g_strdup (pgp_userid)); - cipher = mail_crypto_get_pgp_cipher_context (account); - camel_cipher_encrypt (cipher, pgp_userid, recipients, part, npart, &ex); + cipher = camel_gpg_context_new (session); + if (account != NULL) + camel_gpg_context_set_always_trust ( + CAMEL_GPG_CONTEXT (cipher), + account->pgp_always_trust); + camel_cipher_encrypt ( + cipher, pgp_userid, recipients, + part, npart, &ex); camel_object_unref (cipher); if (account && account->pgp_encrypt_to_self && pgp_userid) @@ -900,6 +864,7 @@ build_message (EMsgComposer *composer, } if (smime_encrypt) { + /* check to see if we should encrypt to self, NB removed after use */ if (account->smime_encrypt_to_self) g_ptr_array_add (recipients, g_strdup (account->smime_encrypt_key)); @@ -976,207 +941,9 @@ skip_content: return NULL; } -/* Attachment Bar */ - -static void -emcab_add (EPopup *ep, EPopupItem *item, gpointer data) -{ - GtkWidget *widget = data; - GtkWidget *composer; - - composer = gtk_widget_get_toplevel (widget); - gtk_action_activate (ACTION (ATTACH)); -} - -static void -emcab_properties (EPopup *ep, EPopupItem *item, gpointer data) -{ - EAttachmentBar *attachment_bar = data; - - e_attachment_bar_edit_selected (attachment_bar); -} - -static void -emcab_remove (EPopup *ep, EPopupItem *item, gpointer data) -{ - EAttachmentBar *attachment_bar = data; - - e_attachment_bar_remove_selected (attachment_bar); -} - -static void -emcab_popup_position (GtkMenu *menu, int *x, int *y, gboolean *push_in, gpointer user_data) -{ - GtkWidget *widget = user_data; - GnomeIconList *icon_list = user_data; - GList *selection; - GnomeCanvasPixbuf *image; - - gdk_window_get_origin (widget->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, GPOINTER_TO_INT(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 -emcab_popups_free (EPopup *ep, GSList *list, gpointer data) -{ - g_slist_free (list); -} - -/* Popup menu handling. */ -static EPopupItem emcab_popups[] = { - { E_POPUP_ITEM, "10.attach", N_("_Remove"), emcab_remove, NULL, GTK_STOCK_REMOVE, EM_POPUP_ATTACHMENTS_MANY }, - { E_POPUP_ITEM, "20.attach", N_("_Properties"), emcab_properties, NULL, GTK_STOCK_PROPERTIES, EM_POPUP_ATTACHMENTS_ONE }, - { E_POPUP_BAR, "30.attach.00", NULL, NULL, NULL, NULL, EM_POPUP_ATTACHMENTS_MANY|EM_POPUP_ATTACHMENTS_ONE }, - { E_POPUP_ITEM, "30.attach.01", N_("_Add attachment..."), emcab_add, NULL, GTK_STOCK_ADD, 0 }, -}; - -/* if id != -1, then use it as an index for target of the popup */ - -static void -emcab_popup (EAttachmentBar *bar, GdkEventButton *event, int id) -{ - GSList *attachments = NULL, *menus = NULL; - int i; - EMPopup *emp; - EMPopupTargetAttachments *t; - GtkMenu *menu; - - attachments = e_attachment_bar_get_attachment (bar, id); - - for (i=0;i<sizeof (emcab_popups)/sizeof (emcab_popups[0]);i++) - menus = g_slist_prepend (menus, &emcab_popups[i]); - - /** @HookPoint-EMPopup: Composer Attachment Bar Context Menu - * @Id: org.gnome.evolution.mail.composer.attachmentbar.popup - * @Class: org.gnome.evolution.mail.popup:1.0 - * @Target: EMPopupTargetAttachments - * - * This is the context menu on the composer attachment bar. - */ - emp = em_popup_new ("org.gnome.evolution.mail.composer.attachmentbar.popup"); - e_popup_add_items ((EPopup *)emp, menus, NULL, emcab_popups_free, bar); - t = em_popup_target_new_attachments (emp, attachments); - t->target.widget = (GtkWidget *)bar; - menu = e_popup_create_menu_once ((EPopup *)emp, (EPopupTarget *)t, 0); - - if (event == NULL) - gtk_menu_popup (menu, NULL, NULL, emcab_popup_position, bar, 0, gtk_get_current_event_time ()); - else - gtk_menu_popup (menu, NULL, NULL, NULL, NULL, event->button, event->time); -} - /* Signatures */ static gchar * -get_file_content (EMsgComposer *composer, - const gchar *filename, - gboolean want_html, - guint flags, - gboolean warn) -{ - CamelStreamFilter *filtered_stream; - CamelStreamMem *memstream; - CamelMimeFilter *html, *charenc; - CamelStream *stream; - GByteArray *buffer; - gchar *charset; - gchar *content; - gint fd; - - fd = g_open (filename, O_RDONLY, 0); - if (fd == -1) { - if (warn) - e_error_run ((GtkWindow *)composer, "mail-composer:no-sig-file", - filename, g_strerror (errno), NULL); - return g_strdup (""); - } - - stream = camel_stream_fs_new_with_fd (fd); - - if (want_html) { - filtered_stream = camel_stream_filter_new_with_stream (stream); - camel_object_unref (stream); - - html = camel_mime_filter_tohtml_new (flags, 0); - camel_stream_filter_add (filtered_stream, html); - camel_object_unref (html); - - stream = (CamelStream *) filtered_stream; - } - - memstream = (CamelStreamMem *) camel_stream_mem_new (); - buffer = g_byte_array_new (); - camel_stream_mem_set_byte_array (memstream, buffer); - - camel_stream_write_to_stream (stream, (CamelStream *) memstream); - camel_object_unref (stream); - - /* The newer signature UI saves signatures in UTF-8, but we still need to check that - the signature is valid UTF-8 because it is possible that the user imported a - signature file that is in his/her locale charset. If it's not in UTF-8 and not in - the charset the composer is in (or their default mail charset) then - there's nothing we can do. */ - if (buffer->len && !g_utf8_validate ((const gchar *)buffer->data, buffer->len, NULL)) { - stream = (CamelStream *) memstream; - memstream = (CamelStreamMem *) camel_stream_mem_new (); - camel_stream_mem_set_byte_array (memstream, g_byte_array_new ()); - - filtered_stream = camel_stream_filter_new_with_stream (stream); - camel_object_unref (stream); - - charset = composer && composer->priv->charset ? composer->priv->charset : NULL; - charset = charset ? g_strdup (charset) : e_composer_get_default_charset (); - if ((charenc = (CamelMimeFilter *) camel_mime_filter_charset_new_convert (charset, "UTF-8"))) { - camel_stream_filter_add (filtered_stream, charenc); - camel_object_unref (charenc); - } - - g_free (charset); - - camel_stream_write_to_stream ((CamelStream *) filtered_stream, (CamelStream *) memstream); - camel_object_unref (filtered_stream); - g_byte_array_free (buffer, TRUE); - - buffer = memstream->buffer; - } - - camel_object_unref (memstream); - - g_byte_array_append (buffer, (const guint8 *)"", 1); - content = (char*)buffer->data; - g_byte_array_free (buffer, FALSE); - - return content; -} - -gchar * -e_msg_composer_get_sig_file_content (const gchar *sigfile, gboolean in_html) -{ - if (!sigfile || !*sigfile) { - return NULL; - } - - return get_file_content (NULL, sigfile, !in_html, - CAMEL_MIME_FILTER_TOHTML_PRESERVE_8BIT | - CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS | - CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES | - CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES, - FALSE); -} - -static gchar * encode_signature_name (const gchar *name) { const gchar *s; @@ -1266,19 +1033,6 @@ decode_signature_name (const gchar *name) return dname; } -static gboolean -add_signature_delim (void) -{ - gboolean res; - GConfClient *client = gconf_client_get_default (); - - res = !gconf_client_get_bool (client, COMPOSER_GCONF_NO_SIGNATURE_DELIM_KEY, NULL); - - g_object_unref (client); - - return res; -} - #define CONVERT_SPACES CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES static gchar * @@ -1287,7 +1041,7 @@ get_signature_html (EMsgComposer *composer) EComposerHeaderTable *table; gchar *text = NULL, *html = NULL; ESignature *signature; - gboolean format_html, add_delim; + gboolean format_html; table = e_msg_composer_get_header_table (composer); signature = e_composer_header_table_get_signature (table); @@ -1295,19 +1049,18 @@ get_signature_html (EMsgComposer *composer) if (!signature) return NULL; - add_delim = add_signature_delim (); - if (!signature->autogen) { if (!signature->filename) return NULL; format_html = signature->html; - if (signature->script) { - text = mail_config_signature_run_script (signature->filename); - } else { - text = e_msg_composer_get_sig_file_content (signature->filename, format_html); - } + if (signature->script) + text = e_run_signature_script ( + signature->filename); + else + text = e_read_signature_file ( + signature, TRUE, NULL); } else { EAccount *account; EAccountIdentity *id; @@ -1324,8 +1077,7 @@ get_signature_html (EMsgComposer *composer) name = id->name ? camel_text_to_html (id->name, CONVERT_SPACES, 0) : NULL; organization = id->organization ? camel_text_to_html (id->organization, CONVERT_SPACES, 0) : NULL; - text = g_strdup_printf ("%s%s%s%s%s%s%s%s%s", - add_delim ? "-- <BR>" : "", + text = g_strdup_printf ("-- <BR>%s%s%s%s%s%s%s%s", name ? name : "", (address && *address) ? " <<A HREF=\"mailto:" : "", address ? address : "", @@ -1358,7 +1110,7 @@ get_signature_html (EMsgComposer *composer) "</TD></TR></TABLE>", encoded_uid ? encoded_uid : "", format_html ? "" : "<PRE>\n", - format_html || !add_delim || (!strncmp ("-- \n", text, 4) || strstr (text, "\n-- \n")) ? "" : "-- \n", + format_html || (!strncmp ("-- \n", text, 4) || strstr (text, "\n-- \n")) ? "" : "-- \n", text, format_html ? "" : "</PRE>\n"); g_free (text); @@ -1374,14 +1126,16 @@ set_editor_text (EMsgComposer *composer, const gchar *text, gboolean set_signature) { + EShell *shell; + EShellSettings *shell_settings; gboolean reply_signature_on_top; gchar *body = NULL, *html = NULL; - GConfClient *gconf; g_return_if_fail (E_IS_MSG_COMPOSER (composer)); g_return_if_fail (text != NULL); - gconf = gconf_client_get_default (); + shell = e_shell_get_default (); + shell_settings = e_shell_get_shell_settings (shell); /* @@ -1397,16 +1151,15 @@ set_editor_text (EMsgComposer *composer, */ - reply_signature_on_top = gconf_client_get_bool (gconf, COMPOSER_GCONF_TOP_SIGNATURE_KEY, NULL); - - g_object_unref (gconf); + reply_signature_on_top = e_shell_settings_get_boolean ( + shell_settings, "composer-top-signature"); if (set_signature && reply_signature_on_top) { gchar *tmp = NULL; tmp = get_signature_html (composer); if (tmp) { /* Minimizing the damage. Make it just a part of the body instead of a signature */ - html = add_signature_delim () ? strstr (tmp, "-- \n") : NULL; + html = strstr (tmp, "-- \n"); if (html) { /* That two consecutive - symbols followed by a space */ *(html+1) = ' '; @@ -1457,14 +1210,6 @@ autosave_load_draft (const gchar *filename) if (e_composer_autosave_snapshot (composer)) g_unlink (filename); - g_signal_connect ( - composer, "send", - G_CALLBACK (em_utils_composer_send_cb), NULL); - - g_signal_connect ( - composer, "save-draft", - G_CALLBACK (em_utils_composer_save_draft_cb), NULL); - gtk_widget_show (GTK_WIDGET (composer)); } @@ -1473,108 +1218,17 @@ autosave_load_draft (const gchar *filename) /* Miscellaneous callbacks. */ -static gint -attachment_bar_button_press_event_cb (EAttachmentBar *attachment_bar, - GdkEventButton *event) -{ - GnomeIconList *icon_list; - gint icon_number; - - if (event->button != 3) - return FALSE; - - icon_list = GNOME_ICON_LIST (attachment_bar); - icon_number = gnome_icon_list_get_icon_at ( - icon_list, event->x, event->y); - if (icon_number >= 0) { - gnome_icon_list_unselect_all (icon_list); - gnome_icon_list_select_icon (icon_list, icon_number); - } - - emcab_popup (attachment_bar, event, icon_number); - - return TRUE; -} - static void -attachment_bar_changed_cb (EAttachmentBar *attachment_bar, - EMsgComposer *composer) +attachment_store_changed_cb (EMsgComposer *composer) { GtkhtmlEditor *editor; - GtkWidget *widget; - guint attachment_num; - - editor = GTKHTML_EDITOR (composer); - attachment_num = e_attachment_bar_get_num_attachments (attachment_bar); - - if (attachment_num > 0) { - gchar *markup; - - markup = g_strdup_printf ( - "<b>%d</b> %s", attachment_num, ngettext ( - "Attachment", "Attachments", attachment_num)); - widget = composer->priv->attachment_expander_num; - gtk_label_set_markup (GTK_LABEL (widget), markup); - g_free (markup); - - gtk_widget_show (composer->priv->attachment_expander_icon); - - widget = composer->priv->attachment_expander; - gtk_expander_set_expanded (GTK_EXPANDER (widget), TRUE); - } else { - widget = composer->priv->attachment_expander_num; - gtk_label_set_text (GTK_LABEL (widget), ""); - - gtk_widget_hide (composer->priv->attachment_expander_icon); - - widget = composer->priv->attachment_expander; - gtk_expander_set_expanded (GTK_EXPANDER (widget), FALSE); - } /* Mark the editor as changed so it prompts about unsaved changes on close. */ + editor = GTKHTML_EDITOR (composer); gtkhtml_editor_set_changed (editor, TRUE); } -static gint -attachment_bar_key_press_event_cb (EAttachmentBar *attachment_bar, - GdkEventKey *event) -{ - if (event->keyval == GDK_Delete) { - e_attachment_bar_remove_selected (attachment_bar); - return TRUE; - } - - return FALSE; -} - -static gboolean -attachment_bar_popup_menu_cb (EAttachmentBar *attachment_bar) -{ - emcab_popup (attachment_bar, NULL, -1); - - return TRUE; -} - -static void -attachment_expander_notify_cb (GtkExpander *expander, - GParamSpec *pspec, - EMsgComposer *composer) -{ - GtkLabel *label; - const gchar *text; - - label = GTK_LABEL (composer->priv->attachment_expander_label); - - /* Update the expander label */ - if (gtk_expander_get_expanded (expander)) - text = _("Hide _Attachment Bar"); - else - text = _("Show _Attachment Bar"); - - gtk_label_set_text_with_mnemonic (label, text); -} - static void msg_composer_subject_changed_cb (EMsgComposer *composer) { @@ -1714,7 +1368,7 @@ msg_composer_account_changed_cb (EMsgComposer *composer) bcc_addrs = account->bcc_addrs; uid = account->id->sig_uid; - signature = uid ? mail_config_get_signature_by_uid (uid) : NULL; + signature = uid ? e_get_signature_by_uid (uid) : NULL; e_composer_header_table_set_signature (table, signature); /* XXX This should be done more generically. The composer @@ -1770,75 +1424,6 @@ msg_composer_account_list_changed_cb (EMsgComposer *composer) g_object_unref (iterator); } -static void -msg_composer_attach_message (EMsgComposer *composer, - CamelMimeMessage *msg) -{ - CamelMimePart *mime_part; - GString *description; - const gchar *subject; - EMsgComposerPrivate *p = composer->priv; - - mime_part = camel_mime_part_new (); - camel_mime_part_set_disposition (mime_part, "inline"); - subject = camel_mime_message_get_subject (msg); - - description = g_string_new (_("Attached message")); - if (subject != NULL) - g_string_append_printf (description, " - %s", subject); - camel_mime_part_set_description (mime_part, description->str); - g_string_free (description, TRUE); - - camel_medium_set_content_object ( - (CamelMedium *) mime_part, (CamelDataWrapper *) msg); - camel_mime_part_set_content_type (mime_part, "message/rfc822"); - - e_attachment_bar_attach_mime_part ( - E_ATTACHMENT_BAR (p->attachment_bar), mime_part); - - camel_object_unref (mime_part); -} - -static void -msg_composer_update_preferences (GConfClient *client, - guint cnxn_id, - GConfEntry *entry, - EMsgComposer *composer) -{ - GtkhtmlEditor *editor; - gboolean enable; - GError *error = NULL; - - editor = GTKHTML_EDITOR (composer); - - enable = gconf_client_get_bool ( - client, COMPOSER_GCONF_INLINE_SPELLING_KEY, &error); - if (error == NULL) - gtkhtml_editor_set_inline_spelling (editor, enable); - else { - g_warning ("%s", error->message); - g_clear_error (&error); - } - - enable = gconf_client_get_bool ( - client, COMPOSER_GCONF_MAGIC_LINKS_KEY, &error); - if (error == NULL) - gtkhtml_editor_set_magic_links (editor, enable); - else { - g_warning ("%s", error->message); - g_clear_error (&error); - } - - enable = gconf_client_get_bool ( - client, COMPOSER_GCONF_MAGIC_SMILEYS_KEY, &error); - if (error == NULL) - gtkhtml_editor_set_magic_smileys (editor, enable); - else { - g_warning ("%s", error->message); - g_clear_error (&error); - } -} - struct _drop_data { EMsgComposer *composer; @@ -1849,23 +1434,9 @@ struct _drop_data { guint32 action; guint info; guint time; - - unsigned int move:1; - unsigned int moved:1; - unsigned int aborted:1; }; -int -e_msg_composer_get_remote_download_count (EMsgComposer *composer) -{ - EAttachmentBar *attachment_bar; - - g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), 0); - - attachment_bar = E_ATTACHMENT_BAR (composer->priv->attachment_bar); - return e_attachment_bar_get_download_count (attachment_bar); -} - +#if 0 /* KILL-BONOBO */ static void drop_action (EMsgComposer *composer, GdkDragContext *context, @@ -1875,77 +1446,12 @@ drop_action (EMsgComposer *composer, guint time, gboolean html_dnd) { - char *tmp, *str, **urls; CamelMimePart *mime_part; - CamelStream *stream; CamelMimeMessage *msg; - char *content_type; int i, success = FALSE, delete = FALSE; EMsgComposerPrivate *p = composer->priv; switch (info) { - case DND_TYPE_MESSAGE_RFC822: - d (printf ("dropping a message/rfc822\n")); - /* write the message (s) out to a CamelStream so we can use it */ - stream = camel_stream_mem_new (); - camel_stream_write (stream, (const gchar *)selection->data, selection->length); - camel_stream_reset (stream); - - msg = camel_mime_message_new (); - if (camel_data_wrapper_construct_from_stream ((CamelDataWrapper *)msg, stream) != -1) { - msg_composer_attach_message (composer, msg); - success = TRUE; - delete = action == GDK_ACTION_MOVE; - } - - camel_object_unref (msg); - camel_object_unref (stream); - break; - case DND_TYPE_NETSCAPE_URL: - d (printf ("dropping a _NETSCAPE_URL\n")); - tmp = g_strndup ((const gchar *) selection->data, selection->length); - urls = g_strsplit (tmp, "\n", 2); - g_free (tmp); - - /* _NETSCAPE_URL is represented as "URI\nTITLE" */ - handle_uri (composer, urls[0], html_dnd); - - g_strfreev (urls); - success = TRUE; - break; - case DND_TYPE_TEXT_URI_LIST: - d (printf ("dropping a text/uri-list\n")); - tmp = g_strndup ((const gchar *) selection->data, selection->length); - urls = g_strsplit (tmp, "\n", 0); - g_free (tmp); - - for (i = 0; urls[i] != NULL; i++) { - str = g_strstrip (urls[i]); - if (str[0] == '#' || str[0] == '\0') - continue; - - handle_uri (composer, str, html_dnd); - } - - g_strfreev (urls); - success = TRUE; - break; - case DND_TYPE_TEXT_VCARD: - case DND_TYPE_TEXT_CALENDAR: - content_type = gdk_atom_name (selection->type); - d (printf ("dropping a %s\n", content_type)); - - mime_part = camel_mime_part_new (); - camel_mime_part_set_content (mime_part, (const gchar *)selection->data, selection->length, content_type); - camel_mime_part_set_disposition (mime_part, "inline"); - - e_attachment_bar_attach_mime_part (E_ATTACHMENT_BAR (p->attachment_bar), mime_part); - - camel_object_unref (mime_part); - g_free (content_type); - - success = TRUE; - break; case DND_TYPE_X_UID_LIST: { GPtrArray *uids; char *inptr, *inend; @@ -2039,55 +1545,7 @@ drop_action (EMsgComposer *composer, gtk_drag_finish (context, success, delete, time); } - -static void -drop_popup_copy (EPopup *ep, EPopupItem *item, gpointer data) -{ - struct _drop_data *m = data; - - drop_action ( - m->composer, m->context, GDK_ACTION_COPY, - m->selection, m->info, m->time, FALSE); -} - -static void -drop_popup_move (EPopup *ep, EPopupItem *item, gpointer data) -{ - struct _drop_data *m = data; - - drop_action ( - m->composer, m->context, GDK_ACTION_MOVE, - m->selection, m->info, m->time, FALSE); -} - -static void -drop_popup_cancel (EPopup *ep, EPopupItem *item, gpointer data) -{ - struct _drop_data *m = data; - - gtk_drag_finish (m->context, FALSE, FALSE, m->time); -} - -static EPopupItem drop_popup_menu[] = { - { E_POPUP_ITEM, "00.emc.02", N_("_Copy"), drop_popup_copy, NULL, "mail-copy", 0 }, - { E_POPUP_ITEM, "00.emc.03", N_("_Move"), drop_popup_move, NULL, "mail-move", 0 }, - { E_POPUP_BAR, "10.emc" }, - { E_POPUP_ITEM, "99.emc.00", N_("Cancel _Drag"), drop_popup_cancel, NULL, NULL, 0 }, -}; - -static void -drop_popup_free (EPopup *ep, GSList *items, gpointer data) -{ - struct _drop_data *m = data; - - g_slist_free (items); - - g_object_unref (m->context); - g_object_unref (m->composer); - g_free (m->selection->data); - g_free (m->selection); - g_free (m); -} +#endif static void msg_composer_notify_header_cb (EMsgComposer *composer) @@ -2103,11 +1561,11 @@ msg_composer_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { + EShell *shell; + EShellSettings *shell_settings; GObject *object; EMsgComposer *composer; GtkToggleAction *action; - GList *spell_languages; - GConfClient *client; GArray *array; gboolean active; guint binding_id; @@ -2117,9 +1575,11 @@ msg_composer_constructor (GType type, type, n_construct_properties, construct_properties); composer = E_MSG_COMPOSER (object); - client = gconf_client_get_default (); array = composer->priv->gconf_bridge_binding_ids; + shell = e_shell_get_default (); + shell_settings = e_shell_get_shell_settings (shell); + /* Restore Persistent State */ binding_id = gconf_bridge_bind_property ( @@ -2166,29 +1626,16 @@ msg_composer_constructor (GType type, /* Honor User Preferences */ - active = gconf_client_get_bool ( - client, COMPOSER_GCONF_SEND_HTML_KEY, NULL); + active = e_shell_settings_get_boolean ( + shell_settings, "composer-format-html"); gtkhtml_editor_set_html_mode (GTKHTML_EDITOR (composer), active); action = GTK_TOGGLE_ACTION (ACTION (REQUEST_READ_RECEIPT)); - active = gconf_client_get_bool ( - client, COMPOSER_GCONF_REQUEST_RECEIPT_KEY, NULL); + active = e_shell_settings_get_boolean ( + shell_settings, "composer-request-receipt"); gtk_toggle_action_set_active (action, active); - spell_languages = e_load_spell_languages (); - gtkhtml_editor_set_spell_languages ( - GTKHTML_EDITOR (composer), spell_languages); - g_list_free (spell_languages); - - gconf_client_add_dir ( - client, COMPOSER_GCONF_PREFIX, - GCONF_CLIENT_PRELOAD_ONELEVEL, NULL); - composer->priv->notify_id = gconf_client_notify_add ( - client, COMPOSER_GCONF_PREFIX, (GConfClientNotifyFunc) - msg_composer_update_preferences, composer, NULL, NULL); - msg_composer_update_preferences (client, 0, NULL, composer); - - g_object_unref (client); + e_shell_watch_window (shell, GTK_WINDOW (object)); return object; } @@ -2235,15 +1682,6 @@ msg_composer_destroy (GtkObject *object) composer->priv->address_dialog = NULL; } - if (composer->priv->notify_id) { - GConfClient *client; - - client = gconf_client_get_default (); - gconf_client_notify_remove (client, composer->priv->notify_id); - composer->priv->notify_id = 0; - g_object_unref (client); - } - /* Chain up to parent's destroy() method. */ GTK_OBJECT_CLASS (parent_class)->destroy (object); } @@ -2347,33 +1785,14 @@ msg_composer_drag_motion (GtkWidget *widget, gint y, guint time) { - GList *targets; - GdkDragAction actions = 0; - GdkDragAction chosen_action; - - targets = context->targets; - while (targets != NULL) { - gint ii; - - for (ii = 0; ii < G_N_ELEMENTS (drag_info); ii++) - if (targets->data == (gpointer) drag_info[ii].atom) - actions |= drag_info[ii].actions; - - targets = g_list_next (targets); - } - - actions &= context->actions; - chosen_action = context->suggested_action; - - /* we default to copy */ - if (chosen_action == GDK_ACTION_ASK && - (actions & (GDK_ACTION_MOVE|GDK_ACTION_COPY)) != - (GDK_ACTION_MOVE|GDK_ACTION_COPY)) - chosen_action = GDK_ACTION_COPY; + EMsgComposer *composer; + EAttachmentView *view; - gdk_drag_status (context, chosen_action, time); + /* Widget may be EMsgComposer or GtkHTML. */ + composer = E_MSG_COMPOSER (gtk_widget_get_toplevel (widget)); + view = e_msg_composer_get_attachment_view (composer); - return (chosen_action != 0); + return e_attachment_view_drag_motion (view, context, x, y, time); } static void @@ -2386,46 +1805,19 @@ msg_composer_drag_data_received (GtkWidget *widget, guint time) { EMsgComposer *composer; + EAttachmentView *view; /* Widget may be EMsgComposer or GtkHTML. */ composer = E_MSG_COMPOSER (gtk_widget_get_toplevel (widget)); - - if (selection->data == NULL) - return; - - if (selection->length == -1) - return; - - if (context->action == GDK_ACTION_ASK) { - EMPopup *emp; - GSList *menus = NULL; - GtkMenu *menu; - gint ii; - struct _drop_data *m; - - m = g_malloc0(sizeof (*m)); - m->context = g_object_ref (context); - m->composer = g_object_ref (composer); - m->action = context->action; - m->info = info; - m->time = time; - m->selection = g_malloc0(sizeof (*m->selection)); - m->selection->data = g_malloc (selection->length); - memcpy (m->selection->data, selection->data, selection->length); - m->selection->length = selection->length; - - emp = em_popup_new ("org.gnome.evolution.mail.composer.popup.drop"); - for (ii = 0; ii < G_N_ELEMENTS (drop_popup_menu); ii++) - menus = g_slist_append (menus, &drop_popup_menu[ii]); - - e_popup_add_items ((EPopup *)emp, menus, NULL, drop_popup_free, m); - menu = e_popup_create_menu_once ((EPopup *)emp, NULL, 0); - gtk_menu_popup (menu, NULL, NULL, NULL, NULL, 0, time); - } else { - drop_action ( - composer, context, context->action, selection, - info, time, !GTK_WIDGET_TOPLEVEL (widget)); - } + view = e_msg_composer_get_attachment_view (composer); + + /* Forward the data to the attachment view. Note that calling + * e_attachment_view_drag_data_received() will not work because + * that function only handles the case where all the other drag + * handlers have failed. */ + e_attachment_paned_drag_data_received ( + E_ATTACHMENT_PANED (view), + context, x, y, selection, info, time); } static void @@ -2472,11 +1864,20 @@ static void msg_composer_paste_clipboard (GtkhtmlEditor *editor) { EMsgComposer *composer; + EAttachmentView *view; + EAttachmentStore *store; + GtkClipboard *clipboard; + GdkPixbuf *pixbuf; GtkWidget *parent; GtkWidget *widget; - GtkClipboard *clipboard; + gchar *filename; + gchar *uri; + GError *error = NULL; composer = E_MSG_COMPOSER (editor); + view = e_msg_composer_get_attachment_view (composer); + store = e_attachment_view_get_store (view); + widget = gtk_window_get_focus (GTK_WINDOW (editor)); parent = gtk_widget_get_parent (widget); @@ -2486,36 +1887,63 @@ msg_composer_paste_clipboard (GtkhtmlEditor *editor) } clipboard = gtk_widget_get_clipboard (widget, GDK_SELECTION_CLIPBOARD); - if (clipboard && gtk_clipboard_wait_is_image_available (clipboard)) { - GdkPixbuf *pixbuf; - - pixbuf = gtk_clipboard_wait_for_image (clipboard); - if (pixbuf) { - char *tmpl = g_strconcat (_("Image"), "-XXXXXX", NULL); - char *filename = e_mktemp (tmpl); - - g_free (tmpl); - - if (filename && gdk_pixbuf_save (pixbuf, filename, "png", NULL, NULL)) { - if (gtkhtml_editor_get_html_mode (editor)) { - char *uri = g_strconcat ("file://", filename, NULL); - /* this loads image async, thus cannot remove file from this */ - gtkhtml_editor_insert_image (editor, uri); - g_free (uri); - } else { - /* this loads image immediately, remove file from cache to free up disk space */ - e_attachment_bar_attach (E_ATTACHMENT_BAR (composer->priv->attachment_bar), filename, "image/png"); - g_remove (filename); - } - } - g_free (filename); - g_object_unref (pixbuf); - } - } else { - /* Chain up to parent's paste_clipboard() method. */ - GTKHTML_EDITOR_CLASS (parent_class)->paste_clipboard (editor); + /* Assume the clipboard has an image. The return + * value will be NULL if we assumed wrong. */ + pixbuf = gtk_clipboard_wait_for_image (clipboard); + if (!GDK_IS_PIXBUF (pixbuf)) + goto chainup; + + /* Reserve a temporary file. */ + filename = e_mktemp (NULL); + if (filename == NULL) { + g_warning ("%s", g_strerror (errno)); + g_object_unref (pixbuf); + g_error_free (error); + return; + } + + /* Save the pixbuf as a temporary file in image/png format. */ + if (!gdk_pixbuf_save (pixbuf, filename, "png", &error, NULL)) { + g_warning ("%s", error->message); + g_object_unref (pixbuf); + g_error_free (error); + g_free (filename); + return; + } + + /* Convert the filename to a URI. */ + uri = g_filename_to_uri (filename, NULL, &error); + if (error != NULL) { + g_warning ("%s", error->message); + g_object_unref (pixbuf); + g_error_free (error); + g_free (filename); + return; + } + + if (gtkhtml_editor_get_html_mode (editor)) + gtkhtml_editor_insert_image (editor, uri); + else { + EAttachment *attachment; + + attachment = e_attachment_new_for_uri (uri); + e_attachment_store_add_attachment (store, attachment); + e_attachment_load_async ( + attachment, (GAsyncReadyCallback) + e_attachment_load_handle_error, composer); + g_object_unref (attachment); } + + g_object_unref (pixbuf); + g_free (filename); + g_free (uri); + + return; + +chainup: + /* Chain up to parent's paste_clipboard() method. */ + GTKHTML_EDITOR_CLASS (parent_class)->paste_clipboard (editor); } static void @@ -2739,11 +2167,6 @@ msg_composer_class_init (EMsgComposerClass *class) GtkObjectClass *gtk_object_class; GtkWidgetClass *widget_class; GtkhtmlEditorClass *editor_class; - gint ii; - - for (ii = 0; ii < G_N_ELEMENTS (drag_info); ii++) - drag_info[ii].atom = - gdk_atom_intern (drag_info[ii].target, FALSE); parent_class = g_type_class_peek_parent (class); g_type_class_add_private (class, sizeof (EMsgComposerPrivate)); @@ -2777,7 +2200,7 @@ msg_composer_class_init (EMsgComposerClass *class) signals[SEND] = g_signal_new ( "send", - E_TYPE_MSG_COMPOSER, + G_OBJECT_CLASS_TYPE (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, @@ -2785,20 +2208,36 @@ msg_composer_class_init (EMsgComposerClass *class) signals[SAVE_DRAFT] = g_signal_new ( "save-draft", - E_TYPE_MSG_COMPOSER, + G_OBJECT_CLASS_TYPE (class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + signals[PRINT] = g_signal_new ( + "print", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__ENUM, + G_TYPE_NONE, 1, + GTK_TYPE_PRINT_OPERATION_ACTION); } static void msg_composer_init (EMsgComposer *composer) { + EAttachmentView *view; + EAttachmentStore *store; EComposerHeaderTable *table; + GdkDragAction drag_actions; + GtkTargetList *target_list; + GtkTargetEntry *targets; GtkUIManager *manager; GtkhtmlEditor *editor; GtkHTML *html; + const gchar *id; + gint n_targets; composer->priv = E_MSG_COMPOSER_GET_PRIVATE (composer); @@ -2807,6 +2246,7 @@ msg_composer_init (EMsgComposer *composer) editor = GTKHTML_EDITOR (composer); html = gtkhtml_editor_get_html (editor); manager = gtkhtml_editor_get_ui_manager (editor); + view = e_msg_composer_get_attachment_view (composer); all_composers = g_slist_prepend (all_composers, composer); table = E_COMPOSER_HEADER_TABLE (composer->priv->header_table); @@ -2815,42 +2255,27 @@ msg_composer_init (EMsgComposer *composer) /* Drag-and-Drop Support */ - gtk_drag_dest_set ( - GTK_WIDGET (composer), GTK_DEST_DEFAULT_ALL, - drop_types, G_N_ELEMENTS (drop_types), - GDK_ACTION_COPY | GDK_ACTION_ASK | GDK_ACTION_MOVE); + target_list = e_attachment_view_get_target_list (view); + drag_actions = e_attachment_view_get_drag_actions (view); - /* XXX I'm not sure why we have to explicitly configure the - * attachment bar as a drag destination when CompEditor - * doesn't and previous Evolution releases (2.22 and - * prior) don't, but this is the only way I could figure - * out how to get drag-and-drop to the attachment bar - * working again. I'm probably overlooking something - * simple... */ + targets = gtk_target_table_new_from_list (target_list, &n_targets); gtk_drag_dest_set ( - composer->priv->attachment_bar, GTK_DEST_DEFAULT_ALL, - drop_types, G_N_ELEMENTS (drop_types), - GDK_ACTION_COPY | GDK_ACTION_ASK | GDK_ACTION_MOVE); - - g_signal_connect ( - composer->priv->attachment_bar, "drag-motion", - G_CALLBACK (msg_composer_drag_motion), NULL); - - g_signal_connect ( - composer->priv->attachment_bar, "drag-data-received", - G_CALLBACK (msg_composer_drag_data_received), NULL); + GTK_WIDGET (composer), GTK_DEST_DEFAULT_ALL, + targets, n_targets, drag_actions); g_signal_connect ( html, "drag-data-received", G_CALLBACK (msg_composer_drag_data_received), NULL); + gtk_target_table_free (targets, n_targets); + /* Configure Headers */ e_composer_header_table_set_account_list ( - table, mail_config_get_accounts ()); + table, e_get_account_list ()); e_composer_header_table_set_signature_list ( - table, mail_config_get_signatures ()); + table, e_get_signature_list ()); g_signal_connect_swapped ( table, "notify::account", @@ -2883,31 +2308,26 @@ msg_composer_init (EMsgComposer *composer) msg_composer_account_changed_cb (composer); msg_composer_account_list_changed_cb (composer); - /* Attachment Bar */ + /* Attachments */ - g_signal_connect ( - composer->priv->attachment_bar, "button_press_event", - G_CALLBACK (attachment_bar_button_press_event_cb), NULL); - g_signal_connect ( - composer->priv->attachment_bar, "key_press_event", - G_CALLBACK (attachment_bar_key_press_event_cb), NULL); - g_signal_connect ( - composer->priv->attachment_bar, "popup-menu", - G_CALLBACK (attachment_bar_popup_menu_cb), NULL); - g_signal_connect ( - composer->priv->attachment_bar, "changed", - G_CALLBACK (attachment_bar_changed_cb), composer); - g_signal_connect_after ( - composer->priv->attachment_expander, "notify::expanded", - G_CALLBACK (attachment_expander_notify_cb), composer); + store = e_attachment_view_get_store (view); + + g_signal_connect_swapped ( + store, "row-deleted", + G_CALLBACK (attachment_store_changed_cb), composer); + + g_signal_connect_swapped ( + store, "row-inserted", + G_CALLBACK (attachment_store_changed_cb), composer); e_composer_autosave_register (composer); /* Initialization may have tripped the "changed" state. */ gtkhtml_editor_set_changed (editor, FALSE); - e_plugin_ui_register_manager ( - "org.gnome.evolution.composer", manager, composer); + id = "org.gnome.evolution.composer"; + e_plugin_ui_register_manager (manager, id, composer); + e_plugin_ui_enable_manager (manager, id); } GType @@ -2983,6 +2403,7 @@ create_composer (gint visible_mask) /** * e_msg_composer_new_with_type: + * @type: the type of composer to create * * Create a new message composer widget. The type can be * E_MSG_COMPOSER_MAIL, E_MSG_COMPOSER_POST or E_MSG_COMPOSER_MAIL_POST. @@ -2991,7 +2412,7 @@ create_composer (gint visible_mask) **/ EMsgComposer * -e_msg_composer_new_with_type (int type) +e_msg_composer_new_with_type (gint type) { EMsgComposer *composer; gint visible_mask; @@ -3032,6 +2453,24 @@ e_msg_composer_new (void) return e_msg_composer_new_with_type (E_MSG_COMPOSER_MAIL); } +static gboolean +is_special_header (const gchar *hdr_name) +{ + /* Note: a header is a "special header" if it has any meaning: + 1. it's not a X-* header or + 2. it's an X-Evolution* header + */ + if (g_ascii_strncasecmp (hdr_name, "X-", 2)) + return TRUE; + + if (!g_ascii_strncasecmp (hdr_name, "X-Evolution", 11)) + return TRUE; + + /* we can keep all other X-* headers */ + + return FALSE; +} + static void e_msg_composer_set_pending_body (EMsgComposer *composer, gchar *text, @@ -3222,6 +2661,7 @@ handle_multipart_encrypted (EMsgComposer *composer, CamelCipherContext *cipher; CamelDataWrapper *content; CamelMimePart *mime_part; + CamelSession *session; CamelException ex; CamelCipherValidity *valid; GtkToggleAction *action; @@ -3231,7 +2671,8 @@ handle_multipart_encrypted (EMsgComposer *composer, gtk_toggle_action_set_active (action, TRUE); camel_exception_init (&ex); - cipher = mail_crypto_get_pgp_cipher_context (NULL); + session = e_msg_composer_get_session (composer); + cipher = camel_gpg_context_new (session); mime_part = camel_mime_part_new (); valid = camel_cipher_decrypt (cipher, multipart, mime_part, &ex); camel_object_unref (cipher); @@ -3416,11 +2857,11 @@ set_signature_gui (EMsgComposer *composer) data = gtkhtml_editor_get_paragraph_data (editor, "signature_name"); if (g_str_has_prefix (data, "uid:")) { decoded = decode_signature_name (data + 4); - signature = mail_config_get_signature_by_uid (decoded); + signature = e_get_signature_by_uid (decoded); g_free (decoded); } else if (g_str_has_prefix (data, "name:")) { decoded = decode_signature_name (data + 5); - signature = mail_config_get_signature_by_name (decoded); + signature = e_get_signature_by_name (decoded); g_free (decoded); } @@ -3489,10 +2930,12 @@ e_msg_composer_new_with_message (CamelMimeMessage *message) account_name = g_strdup (account_name); g_strstrip (account_name); - if ((account = mail_config_get_account_by_uid (account_name)) == NULL) - /* 'old' setting */ - account = mail_config_get_account_by_name (account_name); - if (account) { + account = e_get_account_by_uid (account_name); + if (account == NULL) + /* XXX Backwards compatibility */ + account = e_get_account_by_name (account_name); + + if (account != NULL) { g_free (account_name); account_name = g_strdup (account->name); } @@ -3675,8 +3118,9 @@ e_msg_composer_new_with_message (CamelMimeMessage *message) /* set extra headers */ headers = CAMEL_MIME_PART (message)->headers; while (headers) { - if (g_ascii_strcasecmp (headers->name, "References") == 0 || - g_ascii_strcasecmp (headers->name, "In-Reply-To") == 0) { + if (!is_special_header (headers->name) || + !g_ascii_strcasecmp (headers->name, "References") || + !g_ascii_strcasecmp (headers->name, "In-Reply-To")) { g_ptr_array_add (p->extra_hdr_names, g_strdup (headers->name)); g_ptr_array_add (p->extra_hdr_values, g_strdup (headers->value)); } @@ -3744,7 +3188,7 @@ disable_editor (EMsgComposer *composer) action = GTKHTML_EDITOR_ACTION_INSERT_MENU (composer); gtk_action_set_sensitive (action, FALSE); - gtk_widget_set_sensitive (composer->priv->attachment_bar, FALSE); + gtk_widget_set_sensitive (composer->priv->attachment_paned, FALSE); } /** @@ -3782,6 +3226,35 @@ e_msg_composer_new_redirect (CamelMimeMessage *message, } /** + * e_msg_composer_get_session: + * @composer: an #EMsgComposer + * + * Returns the mail module's global #CamelSession instance. Calling + * this function will load the mail module if it isn't already loaded. + * + * Returns: the mail module's #CamelSession + **/ +CamelSession * +e_msg_composer_get_session (EMsgComposer *composer) +{ + EShell *shell; + EShellSettings *shell_settings; + CamelSession *session; + + /* FIXME EMsgComposer should own a reference to EShell. */ + + g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL); + + shell = e_shell_get_default (); + shell_settings = e_shell_get_shell_settings (shell); + + session = e_shell_settings_get_pointer (shell_settings, "mail-session"); + g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL); + + return session; +} + +/** * e_msg_composer_send: * @composer: an #EMsgComposer * @@ -3817,6 +3290,22 @@ e_msg_composer_save_draft (EMsgComposer *composer) e_composer_autosave_set_saved (composer, FALSE); } +/** + * e_msg_composer_print: + * @composer: an #EMsgComposer + * @action: the print action to start + * + * Print the message in @composer. + **/ +void +e_msg_composer_print (EMsgComposer *composer, + GtkPrintOperationAction action) +{ + g_return_if_fail (E_IS_MSG_COMPOSER (composer)); + + g_signal_emit (composer, signals[PRINT], 0, action); +} + static GList * add_recipients (GList *list, const gchar *recips) { @@ -3843,7 +3332,8 @@ add_recipients (GList *list, const gchar *recips) static void handle_mailto (EMsgComposer *composer, const gchar *mailto) { - EMsgComposerPrivate *priv = composer->priv; + EAttachmentView *view; + EAttachmentStore *store; EComposerHeaderTable *table; GList *to = NULL, *cc = NULL, *bcc = NULL; EDestination **tov, **ccv, **bccv; @@ -3852,9 +3342,10 @@ handle_mailto (EMsgComposer *composer, const gchar *mailto) gsize nread, nwritten; const gchar *p; gint len, clen; - CamelURL *url; table = e_msg_composer_get_header_table (composer); + view = e_msg_composer_get_attachment_view (composer); + store = e_attachment_view_get_store (view); buf = g_strdup (mailto); @@ -3926,20 +3417,18 @@ handle_mailto (EMsgComposer *composer, const gchar *mailto) } } else if (!g_ascii_strcasecmp (header, "attach") || !g_ascii_strcasecmp (header, "attachment")) { - /* Change file url to absolute path */ - if (!g_ascii_strncasecmp (content, "file:", 5)) { - url = camel_url_new (content, NULL); - e_attachment_bar_attach (E_ATTACHMENT_BAR (priv->attachment_bar), - url->path, - "attachment"); - camel_url_free (url); - } else { - e_attachment_bar_attach (E_ATTACHMENT_BAR (priv->attachment_bar), - content, - "attachment"); - } - gtk_widget_show (priv->attachment_expander); - gtk_widget_show (priv->attachment_scrolled_window); + EAttachment *attachment; + + camel_url_decode (content); + if (g_ascii_strncasecmp (content, "file:", 5) == 0) + attachment = e_attachment_new_for_uri (content); + else + attachment = e_attachment_new_for_path (content); + e_attachment_store_add_attachment (store, attachment); + e_attachment_load_async ( + attachment, (GAsyncReadyCallback) + e_attachment_load_handle_error, composer); + g_object_unref (attachment); } else if (!g_ascii_strcasecmp (header, "from")) { /* Ignore */ } else if (!g_ascii_strcasecmp (header, "reply-to")) { @@ -3991,45 +3480,6 @@ handle_mailto (EMsgComposer *composer, const gchar *mailto) } } -static void -handle_uri (EMsgComposer *composer, - const gchar *uri, - gboolean html_dnd) -{ - EMsgComposerPrivate *p = composer->priv; - GtkhtmlEditor *editor; - gboolean html_content; - - editor = GTKHTML_EDITOR (composer); - html_content = gtkhtml_editor_get_html_mode (editor); - - if (!g_ascii_strncasecmp (uri, "mailto:", 7)) { - handle_mailto (composer, uri); - } else { - CamelURL *url = camel_url_new (uri, NULL); - gchar *type; - - if (!url) - return; - - if (!g_ascii_strcasecmp (url->protocol, "file")) { - type = e_util_guess_mime_type (uri + strlen ("file://"), TRUE); - if (!type) - return; - - if (strncmp (type, "image", 5) || !html_dnd || (!html_content && !strncmp (type, "image", 5))) { - e_attachment_bar_attach (E_ATTACHMENT_BAR (p->attachment_bar), - url->path, "attachment"); - } - g_free (type); - } else { - e_attachment_bar_attach_remote_file (E_ATTACHMENT_BAR (p->attachment_bar), - uri, "attachment"); - } - camel_url_free (url); - } -} - /** * e_msg_composer_new_from_url: * @url: a mailto URL @@ -4193,21 +3643,31 @@ e_msg_composer_remove_header (EMsgComposer *composer, /** * e_msg_composer_attach: * @composer: a composer object - * @attachment: the CamelMimePart to attach + * @mime_part: the #CamelMimePart to attach * * Attaches @attachment to the message being composed in the composer. **/ void -e_msg_composer_attach (EMsgComposer *composer, CamelMimePart *attachment) +e_msg_composer_attach (EMsgComposer *composer, + CamelMimePart *mime_part) { - EAttachmentBar *bar; - EMsgComposerPrivate *p = composer->priv; + EAttachmentView *view; + EAttachmentStore *store; + EAttachment *attachment; g_return_if_fail (E_IS_MSG_COMPOSER (composer)); - g_return_if_fail (CAMEL_IS_MIME_PART (attachment)); - - bar = E_ATTACHMENT_BAR (p->attachment_bar); - e_attachment_bar_attach_mime_part (bar, attachment); + g_return_if_fail (CAMEL_IS_MIME_PART (mime_part)); + + view = e_msg_composer_get_attachment_view (composer); + store = e_attachment_view_get_store (view); + + attachment = e_attachment_new (); + e_attachment_set_mime_part (attachment, mime_part); + e_attachment_store_add_attachment (store, attachment); + e_attachment_load_async ( + attachment, (GAsyncReadyCallback) + e_attachment_load_handle_error, composer); + g_object_unref (attachment); } /** @@ -4321,12 +3781,17 @@ CamelMimeMessage * e_msg_composer_get_message (EMsgComposer *composer, gboolean save_html_object_data) { + EAttachmentView *view; + EAttachmentStore *store; GtkhtmlEditor *editor; gboolean html_content; g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL); - if (e_msg_composer_get_remote_download_count (composer) != 0) { + view = e_msg_composer_get_attachment_view (composer); + store = e_attachment_view_get_store (view); + + if (e_attachment_store_get_num_loading (store) > 0) { if (!em_utils_prompt_user (GTK_WINDOW (composer), NULL, "mail-composer:ask-send-message-pending-download", NULL)) { return NULL; @@ -4621,14 +4086,6 @@ e_msg_composer_get_raw_message_text (EMsgComposer *composer) return array; } -EAttachmentBar * -e_msg_composer_get_attachment_bar (EMsgComposer *composer) -{ - g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL); - - return E_ATTACHMENT_BAR (composer->priv->attachment_bar); -} - void e_msg_composer_set_enable_autosave (EMsgComposer *composer, gboolean enabled) @@ -4691,17 +4148,8 @@ e_msg_composer_load_from_file (const gchar *filename) camel_object_unref (stream); composer = e_msg_composer_new_with_message (msg); - if (composer != NULL) { - g_signal_connect ( - composer, "send", - G_CALLBACK (em_utils_composer_send_cb), NULL); - - g_signal_connect ( - composer, "save-draft", - G_CALLBACK (em_utils_composer_save_draft_cb), NULL); - + if (composer != NULL) gtk_widget_show (GTK_WIDGET (composer)); - } return composer; } @@ -4792,6 +4240,14 @@ e_msg_composer_get_header_table (EMsgComposer *composer) return E_COMPOSER_HEADER_TABLE (composer->priv->header_table); } +EAttachmentView * +e_msg_composer_get_attachment_view (EMsgComposer *composer) +{ + g_return_val_if_fail (E_IS_MSG_COMPOSER (composer), NULL); + + return E_ATTACHMENT_VIEW (composer->priv->attachment_paned); +} + void e_msg_composer_set_send_options (EMsgComposer *composer, gboolean send_enable) |