/* * e-mail-reader.c * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with the program; if not, see * * * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * */ #include "e-mail-reader.h" #include #include #include #include #ifdef HAVE_XFREE #include #endif #include "e-util/e-binding.h" #include "e-util/e-charset.h" #include "e-util/e-util.h" #include "e-util/gconf-bridge.h" #include "shell/e-shell.h" #include "widgets/misc/e-popup-action.h" #include "mail/e-mail-browser.h" #include "mail/e-mail-display.h" #include "mail/e-mail-reader-utils.h" #include "mail/em-composer-utils.h" #include "mail/em-event.h" #include "mail/em-folder-selector.h" #include "mail/em-folder-tree.h" #include "mail/em-utils.h" #include "mail/mail-autofilter.h" #include "mail/mail-config.h" #include "mail/mail-ops.h" #include "mail/mail-vfolder.h" enum { CHANGED, FOLDER_LOADED, SHOW_SEARCH_BAR, LAST_SIGNAL }; /* Remembers the previously selected folder when transferring messages. */ static gchar *default_xfer_messages_uri; static guint signals[LAST_SIGNAL]; static void action_mail_add_sender_cb (GtkAction *action, EMailReader *reader) { MessageList *message_list; CamelMessageInfo *info; CamelFolder *folder; GtkWindow *window; GPtrArray *uids; const gchar *address; message_list = e_mail_reader_get_message_list (reader); window = e_mail_reader_get_window (reader); folder = message_list->folder; uids = message_list_get_selected (message_list); if (uids->len != 1) goto exit; info = camel_folder_get_message_info (folder, uids->pdata[0]); if (info == NULL) goto exit; address = camel_message_info_from (info); if (address == NULL || *address == '\0') goto exit; em_utils_add_address (window, address); exit: em_utils_uids_free (uids); } static void action_mail_charset_cb (GtkRadioAction *action, GtkRadioAction *current, EMailReader *reader) { EMFormatHTMLDisplay *html_display; const gchar *charset; if (action != current) return; html_display = e_mail_reader_get_html_display (reader); charset = g_object_get_data (G_OBJECT (action), "charset"); /* Charset for "Default" action will be NULL. */ em_format_set_charset (EM_FORMAT (html_display), charset); } static void action_mail_check_for_junk_cb (GtkAction *action, EMailReader *reader) { MessageList *message_list; CamelFolder *folder; GPtrArray *uids; message_list = e_mail_reader_get_message_list (reader); folder = message_list->folder; uids = message_list_get_selected (message_list); mail_filter_junk (folder, uids); } static void action_mail_clipboard_copy_cb (GtkAction *action, EMailReader *reader) { EMFormatHTMLDisplay *html_display; GtkHTML *html; html_display = e_mail_reader_get_html_display (reader); html = EM_FORMAT_HTML (html_display)->html; gtk_html_copy (html); } static void action_mail_copy_cb (GtkAction *action, EMailReader *reader) { MessageList *message_list; CamelFolder *folder; GtkWidget *folder_tree; GtkWidget *dialog; GPtrArray *selected; const gchar *uri; message_list = e_mail_reader_get_message_list (reader); folder_tree = em_folder_tree_new (); selected = message_list_get_selected (message_list); folder = message_list->folder; em_folder_tree_set_excluded ( EM_FOLDER_TREE (folder_tree), EMFT_EXCLUDE_NOSELECT | EMFT_EXCLUDE_VIRTUAL | EMFT_EXCLUDE_VTRASH); dialog = em_folder_selector_new ( EM_FOLDER_TREE (folder_tree), EM_FOLDER_SELECTOR_CAN_CREATE, _("Select Folder"), NULL, _("C_opy")); if (default_xfer_messages_uri != NULL) em_folder_selector_set_selected ( EM_FOLDER_SELECTOR (dialog), default_xfer_messages_uri); if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK) goto exit; uri = em_folder_selector_get_selected_uri ( EM_FOLDER_SELECTOR (dialog)); g_free (default_xfer_messages_uri); default_xfer_messages_uri = g_strdup (uri); if (uri != NULL) { mail_transfer_messages ( folder, selected, FALSE, uri, 0, NULL, NULL); selected = NULL; } exit: if (selected != NULL) em_utils_uids_free (selected); gtk_widget_destroy (dialog); } static void action_mail_delete_cb (GtkAction *action, EMailReader *reader) { guint32 mask = CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_DELETED; guint32 set = CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_DELETED; if (!e_mail_reader_confirm_delete (reader)) return; /* FIXME Verify all selected messages are deletable. * But handle it by disabling this action. */ if (e_mail_reader_mark_selected (reader, mask, set) == 1) e_mail_reader_select_next_message (reader, FALSE); } static void action_mail_filter_on_mailing_list_cb (GtkAction *action, EMailReader *reader) { e_mail_reader_create_filter_from_selected (reader, AUTO_MLIST); } static void action_mail_filter_on_recipients_cb (GtkAction *action, EMailReader *reader) { e_mail_reader_create_filter_from_selected (reader, AUTO_TO); } static void action_mail_filter_on_sender_cb (GtkAction *action, EMailReader *reader) { e_mail_reader_create_filter_from_selected (reader, AUTO_FROM); } static void action_mail_filter_on_subject_cb (GtkAction *action, EMailReader *reader) { e_mail_reader_create_filter_from_selected (reader, AUTO_SUBJECT); } static void action_mail_filters_apply_cb (GtkAction *action, EMailReader *reader) { MessageList *message_list; CamelFolder *folder; GPtrArray *uids; message_list = e_mail_reader_get_message_list (reader); folder = message_list->folder; uids = message_list_get_selected (message_list); mail_filter_on_demand (folder, uids); } static void action_mail_find_cb (GtkAction *action, EMailReader *reader) { e_mail_reader_show_search_bar (reader); } static void action_mail_flag_clear_cb (GtkAction *action, EMailReader *reader) { EMFormatHTMLDisplay *html_display; MessageList *message_list; CamelFolder *folder; GtkWindow *window; GPtrArray *uids; html_display = e_mail_reader_get_html_display (reader); message_list = e_mail_reader_get_message_list (reader); window = e_mail_reader_get_window (reader); folder = message_list->folder; uids = message_list_get_selected (message_list); em_utils_flag_for_followup_clear (window, folder, uids); em_format_redraw (EM_FORMAT (html_display)); } static void action_mail_flag_completed_cb (GtkAction *action, EMailReader *reader) { EMFormatHTMLDisplay *html_display; MessageList *message_list; CamelFolder *folder; GtkWindow *window; GPtrArray *uids; html_display = e_mail_reader_get_html_display (reader); message_list = e_mail_reader_get_message_list (reader); window = e_mail_reader_get_window (reader); folder = message_list->folder; uids = message_list_get_selected (message_list); em_utils_flag_for_followup_completed (window, folder, uids); em_format_redraw (EM_FORMAT (html_display)); } static void action_mail_flag_for_followup_cb (GtkAction *action, EMailReader *reader) { MessageList *message_list; CamelFolder *folder; GtkWindow *window; GPtrArray *uids; message_list = e_mail_reader_get_message_list (reader); window = e_mail_reader_get_window (reader); folder = message_list->folder; uids = message_list_get_selected (message_list); em_utils_flag_for_followup (reader, folder, uids); } static void action_mail_forward_cb (GtkAction *action, EMailReader *reader) { MessageList *message_list; CamelFolder *folder; GtkWindow *window; GPtrArray *uids; const gchar *folder_uri; message_list = e_mail_reader_get_message_list (reader); window = e_mail_reader_get_window (reader); folder = message_list->folder; folder_uri = message_list->folder_uri; uids = message_list_get_selected (message_list); em_utils_forward_messages (folder, uids, folder_uri); } static void action_mail_forward_attached_cb (GtkAction *action, EMailReader *reader) { MessageList *message_list; CamelFolder *folder; GtkWindow *window; GPtrArray *uids; const gchar *folder_uri; message_list = e_mail_reader_get_message_list (reader); window = e_mail_reader_get_window (reader); folder = message_list->folder; folder_uri = message_list->folder_uri; uids = message_list_get_selected (message_list); em_utils_forward_attached (folder, uids, folder_uri); } static void action_mail_forward_inline_cb (GtkAction *action, EMailReader *reader) { MessageList *message_list; CamelFolder *folder; GtkWindow *window; GPtrArray *uids; const gchar *folder_uri; message_list = e_mail_reader_get_message_list (reader); window = e_mail_reader_get_window (reader); folder = message_list->folder; folder_uri = message_list->folder_uri; uids = message_list_get_selected (message_list); em_utils_forward_inline (folder, uids, folder_uri); } static void action_mail_forward_quoted_cb (GtkAction *action, EMailReader *reader) { MessageList *message_list; CamelFolder *folder; GtkWindow *window; GPtrArray *uids; const gchar *folder_uri; message_list = e_mail_reader_get_message_list (reader); window = e_mail_reader_get_window (reader); folder = message_list->folder; folder_uri = message_list->folder_uri; uids = message_list_get_selected (message_list); em_utils_forward_quoted (folder, uids, folder_uri); } static void action_mail_load_images_cb (GtkAction *action, EMailReader *reader) { EMFormatHTMLDisplay *html_display; html_display = e_mail_reader_get_html_display (reader); em_format_html_load_images (EM_FORMAT_HTML (html_display)); } static void action_mail_mark_important_cb (GtkAction *action, EMailReader *reader) { guint32 mask = CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_DELETED; guint32 set = CAMEL_MESSAGE_FLAGGED; e_mail_reader_mark_selected (reader, mask, set); } static void action_mail_mark_junk_cb (GtkAction *action, EMailReader *reader) { guint32 mask = CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_JUNK | CAMEL_MESSAGE_NOTJUNK | CAMEL_MESSAGE_JUNK_LEARN; guint32 set = CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_JUNK | CAMEL_MESSAGE_JUNK_LEARN; if (e_mail_reader_mark_selected (reader, mask, set) == 1) e_mail_reader_select_next_message (reader, TRUE); } static void action_mail_mark_notjunk_cb (GtkAction *action, EMailReader *reader) { guint32 mask = CAMEL_MESSAGE_JUNK | CAMEL_MESSAGE_NOTJUNK | CAMEL_MESSAGE_JUNK_LEARN; guint32 set = CAMEL_MESSAGE_NOTJUNK | CAMEL_MESSAGE_JUNK_LEARN; if (e_mail_reader_mark_selected (reader, mask, set) == 1) e_mail_reader_select_next_message (reader, TRUE); } static void action_mail_mark_read_cb (GtkAction *action, EMailReader *reader) { guint32 mask = CAMEL_MESSAGE_SEEN; guint32 set = CAMEL_MESSAGE_SEEN; e_mail_reader_mark_selected (reader, mask, set); } static void action_mail_mark_unimportant_cb (GtkAction *action, EMailReader *reader) { guint32 mask = CAMEL_MESSAGE_FLAGGED; guint32 set = 0; e_mail_reader_mark_selected (reader, mask, set); } static void action_mail_mark_unread_cb (GtkAction *action, EMailReader *reader) { MessageList *message_list; guint32 mask = CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_DELETED; guint32 set = 0; message_list = e_mail_reader_get_message_list (reader); e_mail_reader_mark_selected (reader, mask, set); if (message_list->seen_id != 0) { g_source_remove (message_list->seen_id); message_list->seen_id = 0; } } static void action_mail_message_edit_cb (GtkAction *action, EMailReader *reader) { MessageList *message_list; CamelFolder *folder; GtkWindow *window; GPtrArray *uids; window = e_mail_reader_get_window (reader); message_list = e_mail_reader_get_message_list (reader); folder = message_list->folder; uids = message_list_get_selected (message_list); em_utils_edit_messages (folder, uids, FALSE); } static void action_mail_message_new_cb (GtkAction *action, EMailReader *reader) { MessageList *message_list; GtkWindow *window; message_list = e_mail_reader_get_message_list (reader); window = e_mail_reader_get_window (reader); em_utils_compose_new_message (message_list->folder_uri); } static void action_mail_message_open_cb (GtkAction *action, EMailReader *reader) { e_mail_reader_open_selected (reader); } static void action_mail_move_cb (GtkAction *action, EMailReader *reader) { MessageList *message_list; CamelFolder *folder; GtkWidget *folder_tree; GtkWidget *dialog; GPtrArray *selected; const gchar *uri; message_list = e_mail_reader_get_message_list (reader); folder_tree = em_folder_tree_new (); selected = message_list_get_selected (message_list); folder = message_list->folder; em_folder_tree_set_excluded ( EM_FOLDER_TREE (folder_tree), EMFT_EXCLUDE_NOSELECT | EMFT_EXCLUDE_VIRTUAL | EMFT_EXCLUDE_VTRASH); dialog = em_folder_selector_new ( EM_FOLDER_TREE (folder_tree), EM_FOLDER_SELECTOR_CAN_CREATE, _("Select Folder"), NULL, _("_Move")); if (default_xfer_messages_uri != NULL) em_folder_selector_set_selected ( EM_FOLDER_SELECTOR (dialog), default_xfer_messages_uri); if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK) goto exit; uri = em_folder_selector_get_selected_uri ( EM_FOLDER_SELECTOR (dialog)); g_free (default_xfer_messages_uri); default_xfer_messages_uri = g_strdup (uri); if (uri != NULL) { mail_transfer_messages ( folder, selected, TRUE, uri, 0, NULL, NULL); selected = NULL; } exit: if (selected != NULL) em_utils_uids_free (selected); gtk_widget_destroy (dialog); } static void action_mail_next_cb (GtkAction *action, EMailReader *reader) { MessageList *message_list; MessageListSelectDirection direction; guint32 flags, mask; direction = MESSAGE_LIST_SELECT_NEXT; flags = 0; mask = 0; message_list = e_mail_reader_get_message_list (reader); message_list_select (message_list, direction, flags, mask); } static void action_mail_next_important_cb (GtkAction *action, EMailReader *reader) { MessageList *message_list; MessageListSelectDirection direction; guint32 flags, mask; direction = MESSAGE_LIST_SELECT_NEXT | MESSAGE_LIST_SELECT_WRAP; flags = CAMEL_MESSAGE_FLAGGED; mask = CAMEL_MESSAGE_FLAGGED; message_list = e_mail_reader_get_message_list (reader); message_list_select (message_list, direction, flags, mask); } static void action_mail_next_thread_cb (GtkAction *action, EMailReader *reader) { MessageList *message_list; message_list = e_mail_reader_get_message_list (reader); message_list_select_next_thread (message_list); } static void action_mail_next_unread_cb (GtkAction *action, EMailReader *reader) { MessageList *message_list; MessageListSelectDirection direction; guint32 flags, mask; direction = MESSAGE_LIST_SELECT_NEXT | MESSAGE_LIST_SELECT_WRAP; flags = 0; mask = CAMEL_MESSAGE_SEEN; message_list = e_mail_reader_get_message_list (reader); message_list_select (message_list, direction, flags, mask); } static void action_mail_previous_cb (GtkAction *action, EMailReader *reader) { MessageList *message_list; MessageListSelectDirection direction; guint32 flags, mask; direction = MESSAGE_LIST_SELECT_PREVIOUS; flags = 0; mask = 0; message_list = e_mail_reader_get_message_list (reader); message_list_select (message_list, direction, flags, mask); } static void action_mail_previous_important_cb (GtkAction *action, EMailReader *reader) { MessageList *message_list; MessageListSelectDirection direction; guint32 flags, mask; direction = MESSAGE_LIST_SELECT_PREVIOUS | MESSAGE_LIST_SELECT_WRAP; flags = CAMEL_MESSAGE_FLAGGED; mask = CAMEL_MESSAGE_FLAGGED; message_list = e_mail_reader_get_message_list (reader); message_list_select (message_list, direction, flags, mask); } static void action_mail_previous_unread_cb (GtkAction *action, EMailReader *reader) { MessageList *message_list; MessageListSelectDirection direction; guint32 flags, mask; direction = MESSAGE_LIST_SELECT_PREVIOUS | MESSAGE_LIST_SELECT_WRAP; flags = 0; mask = CAMEL_MESSAGE_SEEN; message_list = e_mail_reader_get_message_list (reader); message_list_select (message_list, direction, flags, mask); } static void action_mail_print_cb (GtkAction *action, EMailReader *reader) { GtkPrintOperationAction print_action; print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; e_mail_reader_print (reader, print_action); } static void action_mail_print_preview_cb (GtkAction *action, EMailReader *reader) { GtkPrintOperationAction print_action; print_action = GTK_PRINT_OPERATION_ACTION_PREVIEW; e_mail_reader_print (reader, print_action); } static void action_mail_redirect_cb (GtkAction *action, EMailReader *reader) { MessageList *message_list; CamelFolder *folder; GtkWindow *window; const gchar *uid; message_list = e_mail_reader_get_message_list (reader); window = e_mail_reader_get_window (reader); folder = message_list->folder; uid = message_list->cursor_uid; g_return_if_fail (uid != NULL); em_utils_redirect_message_by_uid (folder, uid); } static void action_mail_reply_all_cb (GtkAction *action, EMailReader *reader) { e_mail_reader_reply_to_message (reader, REPLY_MODE_ALL); } static void action_mail_reply_list_cb (GtkAction *action, EMailReader *reader) { e_mail_reader_reply_to_message (reader, REPLY_MODE_LIST); } static void action_mail_reply_sender_cb (GtkAction *action, EMailReader *reader) { e_mail_reader_reply_to_message (reader, REPLY_MODE_SENDER); } static void action_mail_save_as_cb (GtkAction *action, EMailReader *reader) { MessageList *message_list; CamelFolder *folder; GtkWindow *window; GPtrArray *uids; message_list = e_mail_reader_get_message_list (reader); window = e_mail_reader_get_window (reader); folder = message_list->folder; uids = message_list_get_selected (message_list); em_utils_save_messages (window, folder, uids); } static void action_mail_search_folder_from_mailing_list_cb (GtkAction *action, EMailReader *reader) { e_mail_reader_create_vfolder_from_selected (reader, AUTO_MLIST); } static void action_mail_search_folder_from_recipients_cb (GtkAction *action, EMailReader *reader) { e_mail_reader_create_vfolder_from_selected (reader, AUTO_TO); } static void action_mail_search_folder_from_sender_cb (GtkAction *action, EMailReader *reader) { e_mail_reader_create_vfolder_from_selected (reader, AUTO_FROM); } static void action_mail_search_folder_from_subject_cb (GtkAction *action, EMailReader *reader) { e_mail_reader_create_vfolder_from_selected (reader, AUTO_SUBJECT); } static void action_mail_select_all_cb (GtkAction *action, EMailReader *reader) { EMFormatHTMLDisplay *html_display; GtkHTML *html; const gchar *action_name; gboolean selection_active; html_display = e_mail_reader_get_html_display (reader); html = EM_FORMAT_HTML (html_display)->html; gtk_html_select_all (html); action_name = "mail-clipboard-copy"; action = e_mail_reader_get_action (reader, action_name); selection_active = gtk_html_command (html, "is-selection-active"); gtk_action_set_sensitive (action, selection_active); } static void action_mail_show_all_headers_cb (GtkToggleAction *action, EMailReader *reader) { EMFormatHTMLDisplay *html_display; em_format_mode_t mode; html_display = e_mail_reader_get_html_display (reader); if (gtk_toggle_action_get_active (action)) mode = EM_FORMAT_ALLHEADERS; else mode = EM_FORMAT_NORMAL; em_format_set_mode (EM_FORMAT (html_display), mode); } static void action_mail_show_source_cb (GtkAction *action, EMailReader *reader) { EMFormatHTMLDisplay *html_display; EShellBackend *shell_backend; MessageList *message_list; CamelFolder *folder; GtkWidget *browser; GPtrArray *uids; const gchar *folder_uri; message_list = e_mail_reader_get_message_list (reader); shell_backend = e_mail_reader_get_shell_backend (reader); folder = message_list->folder; folder_uri = message_list->folder_uri; uids = message_list_get_selected (message_list); g_return_if_fail (uids->len > 0); browser = e_mail_browser_new (shell_backend); reader = E_MAIL_READER (browser); html_display = e_mail_reader_get_html_display (reader); em_format_set_mode (EM_FORMAT (html_display), EM_FORMAT_SOURCE); e_mail_reader_set_folder (reader, folder, folder_uri); e_mail_reader_set_message (reader, uids->pdata[0]); gtk_widget_show (browser); message_list_free_uids (message_list, uids); } static void action_mail_toggle_important_cb (GtkAction *action, EMailReader *reader) { MessageList *message_list; CamelFolder *folder; GPtrArray *uids; guint ii; message_list = e_mail_reader_get_message_list (reader); folder = message_list->folder; uids = message_list_get_selected (message_list); camel_folder_freeze (folder); for (ii = 0; ii < uids->len; ii++) { guint32 flags; flags = camel_folder_get_message_flags ( folder, uids->pdata[ii]); flags ^= CAMEL_MESSAGE_FLAGGED; if (flags & CAMEL_MESSAGE_FLAGGED) flags &= ~CAMEL_MESSAGE_DELETED; camel_folder_set_message_flags ( folder, uids->pdata[ii], CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_DELETED, flags); } camel_folder_thaw (folder); message_list_free_uids (message_list, uids); } static void action_mail_undelete_cb (GtkAction *action, EMailReader *reader) { guint32 mask = CAMEL_MESSAGE_DELETED; guint32 set = 0; e_mail_reader_mark_selected (reader, mask, set); } static void action_mail_zoom_100_cb (GtkAction *action, EMailReader *reader) { EMFormatHTMLDisplay *html_display; GtkHTML *html; html_display = e_mail_reader_get_html_display (reader); html = EM_FORMAT_HTML (html_display)->html; gtk_html_zoom_reset (html); } static void action_mail_zoom_in_cb (GtkAction *action, EMailReader *reader) { EMFormatHTMLDisplay *html_display; GtkHTML *html; html_display = e_mail_reader_get_html_display (reader); html = EM_FORMAT_HTML (html_display)->html; gtk_html_zoom_out (html); } static void action_mail_zoom_out_cb (GtkAction *action, EMailReader *reader) { EMFormatHTMLDisplay *html_display; GtkHTML *html; html_display = e_mail_reader_get_html_display (reader); html = EM_FORMAT_HTML (html_display)->html; gtk_html_zoom_out (html); } static void action_search_folder_recipient_cb (GtkAction *action, EMailReader *reader) { EMFormatHTMLDisplay *html_display; MessageList *message_list; EMailDisplay *display; CamelURL *curl; const gchar *uri; /* This action is defined in EMailDisplay. */ html_display = e_mail_reader_get_html_display (reader); message_list = e_mail_reader_get_message_list (reader); display = E_MAIL_DISPLAY (EM_FORMAT_HTML (html_display)->html); uri = e_mail_display_get_selected_uri (display); g_return_if_fail (uri != NULL); curl = camel_url_new (uri, NULL); g_return_if_fail (curl != NULL); if (curl->path != NULL && *curl->path != '\0') { CamelInternetAddress *inet_addr; const gchar *folder_uri; /* Ensure vfolder is running. */ vfolder_load_storage (); folder_uri = message_list->folder_uri; inet_addr = camel_internet_address_new (); camel_address_decode (CAMEL_ADDRESS (inet_addr), curl->path); vfolder_gui_add_from_address (inet_addr, AUTO_TO, folder_uri); camel_object_unref (inet_addr); } camel_url_free (curl); } static void action_search_folder_sender_cb (GtkAction *action, EMailReader *reader) { EMFormatHTMLDisplay *html_display; MessageList *message_list; EMailDisplay *display; CamelURL *curl; const gchar *uri; /* This action is defined in EMailDisplay. */ html_display = e_mail_reader_get_html_display (reader); message_list = e_mail_reader_get_message_list (reader); display = E_MAIL_DISPLAY (EM_FORMAT_HTML (html_display)->html); uri = e_mail_display_get_selected_uri (display); g_return_if_fail (uri != NULL); curl = camel_url_new (uri, NULL); g_return_if_fail (curl != NULL); if (curl->path != NULL && *curl->path != '\0') { CamelInternetAddress *inet_addr; const gchar *folder_uri; /* Ensure vfolder is running. */ vfolder_load_storage (); folder_uri = message_list->folder_uri; inet_addr = camel_internet_address_new (); camel_address_decode (CAMEL_ADDRESS (inet_addr), curl->path); vfolder_gui_add_from_address (inet_addr, AUTO_FROM, folder_uri); camel_object_unref (inet_addr); } camel_url_free (curl); } static GtkActionEntry mail_reader_entries[] = { { "mail-add-sender", NULL, N_("A_dd Sender to Address Book"), NULL, N_("Add sender to address book"), G_CALLBACK (action_mail_add_sender_cb) }, { "mail-check-for-junk", "mail-mark-junk", N_("Check for _Junk"), NULL, N_("Filter the selected messages for junk status"), G_CALLBACK (action_mail_check_for_junk_cb) }, { "mail-clipboard-copy", GTK_STOCK_COPY, NULL, NULL, N_("Copy selected messages to the clipboard"), G_CALLBACK (action_mail_clipboard_copy_cb) }, { "mail-copy", "mail-copy", N_("_Copy to Folder..."), "y", N_("Copy selected messages to another folder"), G_CALLBACK (action_mail_copy_cb) }, { "mail-delete", "user-trash", N_("_Delete Message"), "d", N_("Mark the selected messages for deletion"), G_CALLBACK (action_mail_delete_cb) }, { "mail-filter-on-mailing-list", NULL, N_("Filter on Mailing _List..."), NULL, N_("Create a rule to filter messages to this mailing list"), G_CALLBACK (action_mail_filter_on_mailing_list_cb) }, { "mail-filter-on-recipients", NULL, N_("Filter on _Recipients..."), NULL, N_("Create a rule to filter messages to these recipients"), G_CALLBACK (action_mail_filter_on_recipients_cb) }, { "mail-filter-on-sender", NULL, N_("Filter on Se_nder..."), NULL, N_("Create a rule to filter messages from this sender"), G_CALLBACK (action_mail_filter_on_sender_cb) }, { "mail-filter-on-subject", NULL, N_("Filter on _Subject..."), NULL, N_("Create a rule to filter messages with this subject"), G_CALLBACK (action_mail_filter_on_subject_cb) }, { "mail-filters-apply", "stock_mail-filters-apply", N_("A_pply Filters"), "y", N_("Apply filter rules to the selected messages"), G_CALLBACK (action_mail_filters_apply_cb) }, { "mail-find", GTK_STOCK_FIND, N_("_Find in Message..."), "f", N_("Search for text in the body of the displayed message"), G_CALLBACK (action_mail_find_cb) }, { "mail-flag-clear", NULL, N_("_Clear Flag"), NULL, N_("Remove the follow-up flag from the selected messages"), G_CALLBACK (action_mail_flag_clear_cb) }, { "mail-flag-completed", NULL, N_("_Flag Completed"), NULL, N_("Set the follow-up flag to completed on the selected messages"), G_CALLBACK (action_mail_flag_completed_cb) }, { "mail-flag-for-followup", "stock_mail-flag-for-followup", N_("Follow _Up..."), "g", N_("Flag the selected messages for follow-up"), G_CALLBACK (action_mail_flag_for_followup_cb) }, { "mail-forward", "mail-forward", N_("_Forward"), "f", N_("Forward the selected message to someone"), G_CALLBACK (action_mail_forward_cb) }, { "mail-forward-attached", NULL, N_("_Attached"), NULL, N_("Forward the selected message to someone as an attachment"), G_CALLBACK (action_mail_forward_attached_cb) }, { "mail-forward-inline", NULL, N_("_Inline"), NULL, N_("Forward the selected message in the body of a new message"), G_CALLBACK (action_mail_forward_inline_cb) }, { "mail-forward-quoted", NULL, N_("_Quoted"), NULL, N_("Forward the selected message quoted like a reply"), G_CALLBACK (action_mail_forward_quoted_cb) }, { "mail-load-images", "image-x-generic", N_("_Load Images"), "i", N_("Force images in HTML mail to be loaded"), G_CALLBACK (action_mail_load_images_cb) }, { "mail-mark-important", "mail-mark-important", N_("_Important"), NULL, N_("Mark the selected messages as important"), G_CALLBACK (action_mail_mark_important_cb) }, { "mail-mark-junk", "mail-mark-junk", N_("_Junk"), "j", N_("Mark the selected messages as junk"), G_CALLBACK (action_mail_mark_junk_cb) }, { "mail-mark-notjunk", "mail-mark-notjunk", N_("_Not Junk"), "j", N_("Mark the selected messasges as not being junk"), G_CALLBACK (action_mail_mark_notjunk_cb) }, { "mail-mark-read", "mail-mark-read", N_("_Read"), "k", N_("Mark the selected messages as having been read"), G_CALLBACK (action_mail_mark_read_cb) }, { "mail-mark-unimportant", NULL, N_("Uni_mportant"), NULL, N_("Mark the selected messages as unimportant"), G_CALLBACK (action_mail_mark_unimportant_cb) }, { "mail-mark-unread", "mail-mark-unread", N_("_Unread"), "k", N_("Mark the selected messages as not having been read"), G_CALLBACK (action_mail_mark_unread_cb) }, { "mail-message-edit", NULL, N_("_Edit as New Message..."), NULL, N_("Open the selected messages in the composer for editing"), G_CALLBACK (action_mail_message_edit_cb) }, { "mail-message-new", "mail-message-new", N_("Compose _New Message"), "m", N_("Open a window for composing a mail message"), G_CALLBACK (action_mail_message_new_cb) }, { "mail-message-open", NULL, N_("_Open in New Window"), "o", N_("Open the selected messages in a new window"), G_CALLBACK (action_mail_message_open_cb) }, { "mail-move", "mail-move", N_("_Move to Folder..."), "v", N_("Move selected messages to another folder"), G_CALLBACK (action_mail_move_cb) }, { "mail-next", GTK_STOCK_GO_FORWARD, N_("_Next Message"), "Page_Down", N_("Display the next message"), G_CALLBACK (action_mail_next_cb) }, { "mail-next-important", NULL, N_("Next _Important Message"), NULL, N_("Display the next important message"), G_CALLBACK (action_mail_next_important_cb) }, { "mail-next-thread", NULL, N_("Next _Thread"), NULL, N_("Display the next thread"), G_CALLBACK (action_mail_next_thread_cb) }, { "mail-next-unread", NULL, N_("Next _Unread Message"), "bracketright", N_("Display the next unread message"), G_CALLBACK (action_mail_next_unread_cb) }, { "mail-previous", GTK_STOCK_GO_BACK, N_("_Previous Message"), "Page_Up", N_("Display the previous message"), G_CALLBACK (action_mail_previous_cb) }, { "mail-previous-important", NULL, N_("Pr_evious Important Message"), NULL, N_("Display the previous important message"), G_CALLBACK (action_mail_previous_important_cb) }, { "mail-previous-unread", NULL, N_("P_revious Unread Message"), "bracketleft", N_("Display the previous unread message"), G_CALLBACK (action_mail_previous_unread_cb) }, { "mail-print", GTK_STOCK_PRINT, NULL, "p", N_("Print this message"), G_CALLBACK (action_mail_print_cb) }, { "mail-print-preview", GTK_STOCK_PRINT_PREVIEW, NULL, NULL, N_("Preview the message to be printed"), G_CALLBACK (action_mail_print_preview_cb) }, { "mail-redirect", NULL, N_("Re_direct"), NULL, N_("Redirect (bounce) the selected message to someone"), G_CALLBACK (action_mail_redirect_cb) }, { "mail-reply-all", "mail-reply-all", N_("Reply to _All"), "r", N_("Compose a reply to all the recipients of the selected message"), G_CALLBACK (action_mail_reply_all_cb) }, { "mail-reply-list", NULL, N_("Reply to _List"), "l", N_("Compose a reply to the mailing list of the selected message"), G_CALLBACK (action_mail_reply_list_cb) }, { "mail-reply-sender", "mail-reply-sender", N_("_Reply to Sender"), "r", N_("Compose a reply to the sender of the selected message"), G_CALLBACK (action_mail_reply_sender_cb) }, { "mail-save-as", GTK_STOCK_SAVE_AS, N_("_Save as mbox..."), NULL, N_("Save selected messages as an mbox file"), G_CALLBACK (action_mail_save_as_cb) }, { "mail-search-folder-from-mailing-list", NULL, N_("Search Folder from Mailing _List..."), NULL, N_("Create a search folder for this mailing list"), G_CALLBACK (action_mail_search_folder_from_mailing_list_cb) }, { "mail-search-folder-from-recipients", NULL, N_("Search Folder from Recipien_ts..."), NULL, N_("Create a search folder for these recipients"), G_CALLBACK (action_mail_search_folder_from_recipients_cb) }, { "mail-search-folder-from-sender", NULL, N_("Search Folder from Sen_der..."), NULL, N_("Create a search folder for this sender"), G_CALLBACK (action_mail_search_folder_from_sender_cb) }, { "mail-search-folder-from-subject", NULL, N_("Search Folder from S_ubject..."), NULL, N_("Create a search folder for this subject"), G_CALLBACK (action_mail_search_folder_from_subject_cb) }, { "mail-select-all", NULL, N_("Select _All Text"), "x", N_("Select all the text in a message"), G_CALLBACK (action_mail_select_all_cb) }, { "mail-show-source", NULL, N_("_Message Source"), "u", N_("Show the raw email source of the message"), G_CALLBACK (action_mail_show_source_cb) }, { "mail-toggle-important", NULL, NULL, /* No menu item; key press only */ NULL, NULL, G_CALLBACK (action_mail_toggle_important_cb) }, { "mail-undelete", NULL, N_("_Undelete Message"), "d", N_("Undelete the selected messages"), G_CALLBACK (action_mail_undelete_cb) }, { "mail-zoom-100", GTK_STOCK_ZOOM_100, N_("_Normal Size"), "0", N_("Reset the text to its original size"), G_CALLBACK (action_mail_zoom_100_cb) }, { "mail-zoom-in", GTK_STOCK_ZOOM_IN, N_("_Zoom In"), "plus", N_("Increase the text size"), G_CALLBACK (action_mail_zoom_in_cb) }, { "mail-zoom-out", GTK_STOCK_ZOOM_OUT, N_("Zoom _Out"), "minus", N_("Decrease the text size"), G_CALLBACK (action_mail_zoom_out_cb) }, /*** Menus ***/ { "mail-create-rule-menu", NULL, N_("Create R_ule"), NULL, NULL, NULL }, { "mail-encoding-menu", NULL, N_("Ch_aracter Encoding"), NULL, NULL, NULL }, { "mail-forward-as-menu", NULL, N_("F_orward As..."), NULL, NULL, NULL }, { "mail-goto-menu", GTK_STOCK_JUMP_TO, N_("_Go To"), NULL, NULL, NULL }, { "mail-mark-as-menu", NULL, N_("Mar_k As"), NULL, NULL, NULL }, { "mail-message-menu", NULL, N_("_Message"), NULL, NULL, NULL }, { "mail-zoom-menu", NULL, N_("_Zoom"), NULL, NULL, NULL } }; static EPopupActionEntry mail_reader_popup_entries[] = { { "mail-popup-copy", NULL, "mail-copy" }, { "mail-popup-delete", NULL, "mail-delete" }, { "mail-popup-flag-for-followup", N_("Mark for Follo_w Up..."), "mail-flag-for-followup" }, { "mail-popup-forward", NULL, "mail-forward" }, { "mail-popup-mark-important", N_("Mark as _Important"), "mail-mark-important" }, { "mail-popup-mark-junk", N_("Mark as _Junk"), "mail-mark-junk" }, { "mail-popup-mark-notjunk", N_("Mark as _Not Junk"), "mail-mark-notjunk" }, { "mail-popup-mark-read", N_("Mar_k as Read"), "mail-mark-read" }, { "mail-popup-mark-unimportant", N_("Mark as Uni_mportant"), "mail-mark-unimportant" }, { "mail-popup-mark-unread", N_("Mark as _Unread"), "mail-mark-unread" }, { "mail-popup-message-edit", NULL, "mail-message-edit" }, { "mail-popup-move", NULL, "mail-move" }, { "mail-popup-print", NULL, "mail-print" }, { "mail-popup-reply-all", NULL, "mail-reply-all" }, { "mail-popup-reply-sender", NULL, "mail-reply-sender" }, { "mail-popup-save-as", NULL, "mail-save-as" }, { "mail-popup-undelete", NULL, "mail-undelete" } }; static GtkToggleActionEntry mail_reader_toggle_entries[] = { { "mail-caret-mode", NULL, N_("_Caret Mode"), "F7", N_("Show a blinking cursor in the body of displayed messages"), NULL, /* No callback required */ FALSE }, { "mail-show-all-headers", NULL, N_("All Message _Headers"), NULL, N_("Show messages with all email headers"), G_CALLBACK (action_mail_show_all_headers_cb), FALSE } }; static gboolean mail_reader_button_release_event_cb (EMailReader *reader, GdkEventButton *button, GtkHTML *html) { GtkAction *action; const gchar *action_name; gboolean selection_active; action_name = "mail-clipboard-copy"; action = e_mail_reader_get_action (reader, action_name); selection_active = gtk_html_command (html, "is-selection-active"); gtk_action_set_sensitive (action, selection_active); return FALSE; } static void mail_reader_double_click_cb (EMailReader *reader, gint row, ETreePath path, gint col, GdkEvent *event) { /* Ignore double clicks on columns that handle their own state. */ if (MESSAGE_LIST_COLUMN_IS_ACTIVE (col)) return; e_mail_reader_activate (reader, "mail-message-open"); } static gboolean mail_reader_key_press_event_cb (EMailReader *reader, GdkEventKey *event) { const gchar *action_name; if ((event->state & GDK_CONTROL_MASK) != 0) goto ctrl; /* alone */ switch (event->keyval) { case GDK_Delete: case GDK_KP_Delete: action_name = "mail-delete"; break; case GDK_Return: case GDK_KP_Enter: case GDK_ISO_Enter: action_name = "mail-message-open"; break; case GDK_period: case GDK_bracketleft: action_name = "mail-next-unread"; break; case GDK_comma: case GDK_bracketright: action_name = "mail-previous-unread"; break; #ifdef HAVE_XFREE case XF86XK_Reply: action_name = "mail-reply-all"; break; case XF86XK_MailForward: action_name = "mail-forward"; break; #endif case GDK_exclam: action_name = "mail-toggle-important"; break; default: return FALSE; } goto exit; ctrl: /* Ctrl + */ switch (event->keyval) { case GDK_period: action_name = "mail-next-unread"; break; case GDK_comma: action_name = "mail-previous-unread"; break; default: return FALSE; } exit: e_mail_reader_activate (reader, action_name); return TRUE; } static gint mail_reader_key_press_cb (EMailReader *reader, gint row, ETreePath path, gint col, GdkEvent *event) { return mail_reader_key_press_event_cb (reader, &event->key); } static gboolean mail_reader_message_read_cb (EMailReader *reader) { MessageList *message_list; const gchar *uid; message_list = e_mail_reader_get_message_list (reader); uid = g_object_get_data (G_OBJECT (reader), "mark-read-uid"); g_return_val_if_fail (uid != NULL, FALSE); if (g_strcmp0 (message_list->cursor_uid, uid) == 0) e_mail_reader_mark_as_read (reader, uid); return FALSE; } static void mail_reader_message_loaded_cb (CamelFolder *folder, const gchar *message_uid, CamelMimeMessage *message, gpointer user_data, CamelException *ex) { EMailReader *reader = user_data; EMFormatHTMLDisplay *html_display; MessageList *message_list; EShellBackend *shell_backend; EShellSettings *shell_settings; EShell *shell; EMEvent *event; EMEventTargetMessage *target; gboolean mark_read; gint timeout_interval; html_display = e_mail_reader_get_html_display (reader); message_list = e_mail_reader_get_message_list (reader); shell_backend = e_mail_reader_get_shell_backend (reader); shell = e_shell_backend_get_shell (shell_backend); shell_settings = e_shell_get_shell_settings (shell); /* If the user picked a different message in the time it took * to fetch this message, then don't bother rendering it. */ if (g_strcmp0 (message_list->cursor_uid, message_uid) != 0) return; /** @Event: message.reading * @Title: Viewing a message * @Target: EMEventTargetMessage * * message.reading is emitted whenever a user views a message. */ event = em_event_peek (); target = em_event_target_new_message ( event, folder, message, message_uid, 0, NULL); e_event_emit ( (EEvent *) event, "message.reading", (EEventTarget *) target); em_format_format ( EM_FORMAT (html_display), folder, message_uid, message); /* Reset the shell view icon. */ e_shell_event (shell, "mail-icon", (gpointer) "evolution-mail"); /* Determine whether to mark the message as read. */ mark_read = e_shell_settings_get_boolean ( shell_settings, "mail-mark-seen"); timeout_interval = e_shell_settings_get_int ( shell_settings, "mail-mark-seen-timeout"); g_object_set_data_full ( G_OBJECT (reader), "mark-read-uid", g_strdup (message_uid), (GDestroyNotify) g_free); if (message_list->seen_id > 0) g_source_remove (message_list->seen_id); if (mark_read) { message_list->seen_id = g_timeout_add ( timeout_interval, (GSourceFunc) mail_reader_message_read_cb, reader); } else if (camel_exception_is_set (ex)) { GtkHTMLStream *stream; /* Display the error inline and clear the exception. */ stream = gtk_html_begin ( EM_FORMAT_HTML (html_display)->html); gtk_html_stream_printf ( stream, "

%s

%s

", _("Unable to retrieve message"), ex->desc); gtk_html_stream_close (stream, GTK_HTML_STREAM_OK); camel_exception_clear (ex); } e_mail_reader_update_actions (reader); /* We referenced this in the call to mail_get_messagex(). */ g_object_unref (reader); } static gboolean mail_reader_message_selected_timeout_cb (EMailReader *reader) { EMFormatHTMLDisplay *html_display; MessageList *message_list; const gchar *cursor_uid; const gchar *format_uid; const gchar *key; html_display = e_mail_reader_get_html_display (reader); message_list = e_mail_reader_get_message_list (reader); cursor_uid = message_list->cursor_uid; format_uid = EM_FORMAT (html_display)->uid; if (message_list->last_sel_single) { GtkWidget *widget; gboolean html_display_visible; gboolean selected_uid_changed; /* Decide whether to download the full message now. */ widget = GTK_WIDGET (EM_FORMAT_HTML (html_display)->html); html_display_visible = GTK_WIDGET_MAPPED (widget); selected_uid_changed = g_strcmp0 (cursor_uid, format_uid); if (html_display_visible && selected_uid_changed) mail_get_messagex ( message_list->folder, cursor_uid, mail_reader_message_loaded_cb, g_object_ref (reader), mail_msg_fast_ordered_push); } else em_format_format (EM_FORMAT (html_display), NULL, NULL, NULL); key = "message-selected-timeout"; g_object_set_data (G_OBJECT (reader), key, NULL); return FALSE; } static void mail_reader_message_selected_cb (EMailReader *reader, const gchar *uid) { const gchar *key; guint source_id; gpointer data; /* XXX This is kludgy, but we have no other place to store timeout * state information. Addendum: See EAttachmentView for an example * of storing private data in an interface. Clunky but works. */ key = "message-selected-timeout"; data = g_object_get_data (G_OBJECT (reader), key); source_id = GPOINTER_TO_UINT (data); if (source_id > 0) g_source_remove (source_id); source_id = g_timeout_add ( 100, (GSourceFunc) mail_reader_message_selected_timeout_cb, reader); data = GUINT_TO_POINTER (source_id); g_object_set_data (G_OBJECT (reader), key, data); e_mail_reader_changed (reader); } static void mail_reader_emit_folder_loaded (EMailReader *reader) { g_signal_emit (reader, signals[FOLDER_LOADED], 0); } static void mail_reader_set_folder (EMailReader *reader, CamelFolder *folder, const gchar *folder_uri) { EMFormatHTMLDisplay *html_display; MessageList *message_list; gboolean outgoing; html_display = e_mail_reader_get_html_display (reader); message_list = e_mail_reader_get_message_list (reader); outgoing = folder != NULL && folder_uri != NULL && ( em_utils_folder_is_drafts (folder, folder_uri) || em_utils_folder_is_outbox (folder, folder_uri) || em_utils_folder_is_sent (folder, folder_uri)); if (message_list->folder != NULL) mail_sync_folder (message_list->folder, NULL, NULL); em_format_format (EM_FORMAT (html_display), NULL, NULL, NULL); message_list_set_folder (message_list, folder, folder_uri, outgoing); mail_reader_emit_folder_loaded (reader); } static void mail_reader_set_message (EMailReader *reader, const gchar *uid) { MessageList *message_list; message_list = e_mail_reader_get_message_list (reader); message_list_select_uid (message_list, uid); } static void mail_reader_init_charset_actions (EMailReader *reader) { GtkActionGroup *action_group; GtkRadioAction *default_action; GSList *radio_group; action_group = e_mail_reader_get_action_group (reader); radio_group = e_charset_add_radio_actions ( action_group, "mail-charset-", NULL, G_CALLBACK (action_mail_charset_cb), reader); /* XXX Add a tooltip! */ default_action = gtk_radio_action_new ( "mail-charset-default", _("Default"), NULL, NULL, -1); gtk_radio_action_set_group (default_action, radio_group); g_signal_connect ( default_action, "changed", G_CALLBACK (action_mail_charset_cb), reader); gtk_action_group_add_action ( action_group, GTK_ACTION (default_action)); gtk_radio_action_set_current_value (default_action, -1); } static void mail_reader_class_init (EMailReaderIface *iface) { iface->set_folder = mail_reader_set_folder; iface->set_message = mail_reader_set_message; signals[CHANGED] = g_signal_new ( "changed", G_OBJECT_CLASS_TYPE (iface), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[FOLDER_LOADED] = g_signal_new ( "folder-loaded", G_OBJECT_CLASS_TYPE (iface), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); signals[SHOW_SEARCH_BAR] = g_signal_new ( "show-search-bar", G_OBJECT_CLASS_TYPE (iface), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (EMailReaderIface, show_search_bar), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } GType e_mail_reader_get_type (void) { static GType type = 0; if (G_UNLIKELY (type == 0)) { static const GTypeInfo type_info = { sizeof (EMailReaderIface), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) mail_reader_class_init, (GClassFinalizeFunc) NULL, NULL, /* class_data */ 0, /* instance_size */ 0, /* n_preallocs */ (GInstanceInitFunc) NULL, NULL /* value_table */ }; type = g_type_register_static ( G_TYPE_INTERFACE, "EMailReader", &type_info, 0); g_type_interface_add_prerequisite (type, G_TYPE_OBJECT); } return type; } void e_mail_reader_init (EMailReader *reader) { EShell *shell; EShellBackend *shell_backend; EShellSettings *shell_settings; EMFormatHTMLDisplay *html_display; EMailDisplay *display; GtkActionGroup *action_group; MessageList *message_list; GConfBridge *bridge; GtkAction *action; const gchar *action_name; const gchar *key; g_return_if_fail (E_IS_MAIL_READER (reader)); action_group = e_mail_reader_get_action_group (reader); html_display = e_mail_reader_get_html_display (reader); message_list = e_mail_reader_get_message_list (reader); shell_backend = e_mail_reader_get_shell_backend (reader); shell = e_shell_backend_get_shell (shell_backend); shell_settings = e_shell_get_shell_settings (shell); display = E_MAIL_DISPLAY (EM_FORMAT_HTML (html_display)->html); gtk_action_group_add_actions ( action_group, mail_reader_entries, G_N_ELEMENTS (mail_reader_entries), reader); e_action_group_add_popup_actions ( action_group, mail_reader_popup_entries, G_N_ELEMENTS (mail_reader_popup_entries)); gtk_action_group_add_toggle_actions ( action_group, mail_reader_toggle_entries, G_N_ELEMENTS (mail_reader_toggle_entries), reader); mail_reader_init_charset_actions (reader); /* Bind GObject properties to GConf keys. */ bridge = gconf_bridge_get (); action_name = "mail-caret-mode"; key = "/apps/evolution/mail/display/caret_mode"; action = e_mail_reader_get_action (reader, action_name); gconf_bridge_bind_property (bridge, key, G_OBJECT (action), "active"); action_name = "mail-show-all-headers"; key = "/apps/evolution/mail/display/show_all_headers"; action = e_mail_reader_get_action (reader, action_name); gconf_bridge_bind_property (bridge, key, G_OBJECT (action), "active"); /* Fine tuning. */ action_name = "mail-clipboard-copy"; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, FALSE); action_name = "mail-delete"; action = e_mail_reader_get_action (reader, action_name); g_object_set (action, "short-label", _("Delete"), NULL); action_name = "mail-next"; action = e_mail_reader_get_action (reader, action_name); g_object_set (action, "short-label", _("Next"), NULL); action_name = "mail-previous"; action = e_mail_reader_get_action (reader, action_name); g_object_set (action, "short-label", _("Previous"), NULL); action_name = "mail-reply-sender"; action = e_mail_reader_get_action (reader, action_name); g_object_set (action, "short-label", _("Reply"), NULL); action_name = "search-folder-recipient"; action = e_mail_display_get_action (display, action_name); g_signal_connect ( action, "activate", G_CALLBACK (action_search_folder_recipient_cb), reader); action_name = "search-folder-sender"; action = e_mail_display_get_action (display, action_name); g_signal_connect ( action, "activate", G_CALLBACK (action_search_folder_sender_cb), reader); /* Bind properties. */ e_binding_new_full ( G_OBJECT (shell_settings), "mail-citation-color", G_OBJECT (html_display), "citation-color", e_binding_transform_string_to_color, NULL, NULL); e_binding_new ( G_OBJECT (shell_settings), "mail-image-loading-policy", G_OBJECT (html_display), "image-loading-policy"); e_binding_new ( G_OBJECT (shell_settings), "mail-only-local-photos", G_OBJECT (html_display), "only-local-photos"); e_binding_new ( G_OBJECT (shell_settings), "mail-show-animated-images", G_OBJECT (display), "animate"); e_binding_new ( G_OBJECT (shell_settings), "mail-show-sender-photo", G_OBJECT (html_display), "show-sender-photo"); action_name = "mail-caret-mode"; action = e_mail_reader_get_action (reader, action_name); e_mutual_binding_new ( G_OBJECT (action), "active", G_OBJECT (display), "caret-mode"); /* Connect signals. */ g_signal_connect_swapped ( display, "button-release-event", G_CALLBACK (mail_reader_button_release_event_cb), reader); g_signal_connect_swapped ( display, "key-press-event", G_CALLBACK (mail_reader_key_press_event_cb), reader); g_signal_connect_swapped ( message_list, "message-selected", G_CALLBACK (mail_reader_message_selected_cb), reader); g_signal_connect_swapped ( message_list, "message-list-built", G_CALLBACK (mail_reader_emit_folder_loaded), reader); g_signal_connect_swapped ( message_list->tree, "double-click", G_CALLBACK (mail_reader_double_click_cb), reader); g_signal_connect_swapped ( message_list->tree, "key-press", G_CALLBACK (mail_reader_key_press_cb), reader); g_signal_connect_swapped ( message_list->tree, "selection-change", G_CALLBACK (e_mail_reader_changed), reader); } void e_mail_reader_changed (EMailReader *reader) { g_return_if_fail (E_IS_MAIL_READER (reader)); g_signal_emit (reader, signals[CHANGED], 0); } guint32 e_mail_reader_check_state (EMailReader *reader) { MessageList *message_list; GPtrArray *uids; CamelFolder *folder; CamelStore *store = NULL; const gchar *folder_uri; const gchar *tag; gboolean can_clear_flags = FALSE; gboolean can_flag_completed = FALSE; gboolean can_flag_for_followup = FALSE; gboolean has_deleted = FALSE; gboolean has_important = FALSE; gboolean has_junk = FALSE; gboolean has_not_junk = FALSE; gboolean has_read = FALSE; gboolean has_undeleted = FALSE; gboolean has_unimportant = FALSE; gboolean has_unread = FALSE; gboolean drafts_or_outbox; gboolean store_supports_vjunk = FALSE; gboolean is_mailing_list; guint32 state = 0; guint ii; g_return_val_if_fail (E_IS_MAIL_READER (reader), 0); message_list = e_mail_reader_get_message_list (reader); uids = message_list_get_selected (message_list); folder_uri = message_list->folder_uri; folder = message_list->folder; if (folder != NULL) { store = CAMEL_STORE (folder->parent_store); store_supports_vjunk = (store->flags & CAMEL_STORE_VJUNK); } drafts_or_outbox = em_utils_folder_is_drafts (folder, folder_uri) || em_utils_folder_is_outbox (folder, folder_uri); /* Initialize this flag based on whether there are any * messages selected. We will update it in the loop. */ is_mailing_list = (uids->len > 0); for (ii = 0; ii < uids->len; ii++) { CamelMessageInfo *info; const gchar *string; guint32 flags; info = camel_folder_get_message_info ( folder, uids->pdata[ii]); if (info == NULL) continue; flags = camel_message_info_flags (info); if (flags & CAMEL_MESSAGE_SEEN) has_read = TRUE; else has_unread = TRUE; if (drafts_or_outbox) { has_junk = FALSE; has_not_junk = FALSE; } else if (store_supports_vjunk) { guint32 bitmask; /* XXX Strictly speaking, this logic is correct. * Problem is there's nothing in the message * list that indicates whether a message is * already marked "Not Junk". So the user may * think the "Not Junk" button is enabling and * disabling itself randomly as he reads mail. */ if (flags & CAMEL_MESSAGE_JUNK) has_junk = TRUE; if (flags & CAMEL_MESSAGE_NOTJUNK) has_not_junk = TRUE; bitmask = CAMEL_MESSAGE_JUNK | CAMEL_MESSAGE_NOTJUNK; /* If neither junk flag is set, the * message can be marked either way. */ if ((flags & bitmask) == 0) { has_junk = TRUE; has_not_junk = TRUE; } } else { has_junk = TRUE; has_not_junk = TRUE; } if (flags & CAMEL_MESSAGE_DELETED) has_deleted = TRUE; else has_undeleted = TRUE; if (flags & CAMEL_MESSAGE_FLAGGED) has_important = TRUE; else has_unimportant = TRUE; tag = camel_message_info_user_tag (info, "follow-up"); if (tag != NULL && *tag != '\0') { can_clear_flags = TRUE; tag = camel_message_info_user_tag ( info, "completed-on"); if (tag != NULL && *tag != '\0') can_flag_completed = TRUE; } else can_flag_for_followup = TRUE; string = camel_message_info_mlist (info); is_mailing_list &= (string != NULL && *string != '\0'); } if (em_utils_check_user_can_send_mail ()) state |= E_MAIL_READER_HAVE_ACCOUNT; if (uids->len == 1) state |= E_MAIL_READER_SELECTION_SINGLE; if (uids->len > 1) state |= E_MAIL_READER_SELECTION_MULTIPLE; if (!drafts_or_outbox && uids->len == 1) state |= E_MAIL_READER_SELECTION_CAN_ADD_SENDER; if (can_clear_flags) state |= E_MAIL_READER_SELECTION_FLAG_CLEAR; if (can_flag_completed) state |= E_MAIL_READER_SELECTION_FLAG_COMPLETED; if (can_flag_for_followup) state |= E_MAIL_READER_SELECTION_FLAG_FOLLOWUP; if (has_deleted) state |= E_MAIL_READER_SELECTION_HAS_DELETED; if (has_important) state |= E_MAIL_READER_SELECTION_HAS_IMPORTANT; if (has_junk) state |= E_MAIL_READER_SELECTION_HAS_JUNK; if (has_not_junk) state |= E_MAIL_READER_SELECTION_HAS_NOT_JUNK; if (has_read) state |= E_MAIL_READER_SELECTION_HAS_READ; if (has_undeleted) state |= E_MAIL_READER_SELECTION_HAS_UNDELETED; if (has_unimportant) state |= E_MAIL_READER_SELECTION_HAS_UNIMPORTANT; if (has_unread) state |= E_MAIL_READER_SELECTION_HAS_UNREAD; if (is_mailing_list) state |= E_MAIL_READER_SELECTION_IS_MAILING_LIST; em_utils_uids_free (uids); return state; } void e_mail_reader_update_actions (EMailReader *reader) { EShell *shell; EShellBackend *shell_backend; EShellSettings *shell_settings; GtkAction *action; GtkActionGroup *action_group; const gchar *action_name; gboolean sensitive; guint32 state; /* Be descriptive. */ gboolean any_messages_selected; gboolean disable_printing; gboolean enable_flag_clear; gboolean enable_flag_completed; gboolean enable_flag_for_followup; gboolean have_an_account; gboolean multiple_messages_selected; gboolean selection_has_deleted_messages; gboolean selection_has_important_messages; gboolean selection_has_junk_messages; gboolean selection_has_not_junk_messages; gboolean selection_has_read_messages; gboolean selection_has_undeleted_messages; gboolean selection_has_unimportant_messages; gboolean selection_has_unread_messages; gboolean selection_is_mailing_list; gboolean single_message_selected; g_return_if_fail (E_IS_MAIL_READER (reader)); action_group = e_mail_reader_get_action_group (reader); state = e_mail_reader_check_state (reader); shell_backend = e_mail_reader_get_shell_backend (reader); shell = e_shell_backend_get_shell (shell_backend); shell_settings = e_shell_get_shell_settings (shell); disable_printing = e_shell_settings_get_boolean ( shell_settings, "disable-printing"); have_an_account = (state & E_MAIL_READER_HAVE_ACCOUNT); single_message_selected = (state & E_MAIL_READER_SELECTION_SINGLE); multiple_messages_selected = (state & E_MAIL_READER_SELECTION_MULTIPLE); /* FIXME Missing CAN_ADD_SENDER */ enable_flag_clear = (state & E_MAIL_READER_SELECTION_FLAG_CLEAR); enable_flag_completed = (state & E_MAIL_READER_SELECTION_FLAG_COMPLETED); enable_flag_for_followup = (state & E_MAIL_READER_SELECTION_FLAG_FOLLOWUP); selection_has_deleted_messages = (state & E_MAIL_READER_SELECTION_HAS_DELETED); selection_has_important_messages = (state & E_MAIL_READER_SELECTION_HAS_IMPORTANT); selection_has_junk_messages = (state & E_MAIL_READER_SELECTION_HAS_JUNK); selection_has_not_junk_messages = (state & E_MAIL_READER_SELECTION_HAS_NOT_JUNK); selection_has_read_messages = (state & E_MAIL_READER_SELECTION_HAS_READ); selection_has_undeleted_messages = (state & E_MAIL_READER_SELECTION_HAS_UNDELETED); selection_has_unimportant_messages = (state & E_MAIL_READER_SELECTION_HAS_UNIMPORTANT); selection_has_unread_messages = (state & E_MAIL_READER_SELECTION_HAS_UNREAD); selection_is_mailing_list = (state & E_MAIL_READER_SELECTION_IS_MAILING_LIST); any_messages_selected = (single_message_selected || multiple_messages_selected); action_name = "mail-check-for-junk"; sensitive = any_messages_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-copy"; sensitive = any_messages_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-delete"; sensitive = selection_has_undeleted_messages; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-filters-apply"; sensitive = any_messages_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-forward"; sensitive = have_an_account && any_messages_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-forward-attached"; sensitive = have_an_account && any_messages_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-forward-inline"; sensitive = have_an_account && single_message_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-forward-quoted"; sensitive = have_an_account && single_message_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-load-images"; sensitive = single_message_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-mark-important"; sensitive = selection_has_unimportant_messages; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-mark-junk"; sensitive = selection_has_not_junk_messages; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-mark-notjunk"; sensitive = selection_has_junk_messages; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-mark-read"; sensitive = selection_has_unread_messages; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-mark-unimportant"; sensitive = selection_has_important_messages; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-mark-unread"; sensitive = selection_has_read_messages; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-message-edit"; sensitive = have_an_account && single_message_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-message-new"; sensitive = have_an_account; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-message-open"; sensitive = any_messages_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-move"; sensitive = any_messages_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-next-important"; sensitive = single_message_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-next-thread"; sensitive = single_message_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-next-unread"; sensitive = single_message_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-previous-important"; sensitive = single_message_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-previous-unread"; sensitive = single_message_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-print"; sensitive = single_message_selected && !disable_printing; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-print-preview"; sensitive = single_message_selected && !disable_printing; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-redirect"; sensitive = have_an_account && single_message_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-reply-all"; sensitive = have_an_account && single_message_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-reply-list"; sensitive = have_an_account && single_message_selected && selection_is_mailing_list; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-reply-sender"; sensitive = have_an_account && single_message_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-save-as"; sensitive = any_messages_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-select-all"; sensitive = single_message_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-show-source"; sensitive = single_message_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-undelete"; sensitive = selection_has_deleted_messages; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-zoom-100"; sensitive = single_message_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-zoom-in"; sensitive = single_message_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); action_name = "mail-zoom-out"; sensitive = single_message_selected; action = e_mail_reader_get_action (reader, action_name); gtk_action_set_sensitive (action, sensitive); } GtkAction * e_mail_reader_get_action (EMailReader *reader, const gchar *action_name) { GtkActionGroup *action_group; GtkAction *action; g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL); g_return_val_if_fail (action_name != NULL, NULL); action_group = e_mail_reader_get_action_group (reader); action = gtk_action_group_get_action (action_group, action_name); if (action == NULL) g_critical ( "%s: action `%s' not found", G_STRFUNC, action_name); return action; } GtkActionGroup * e_mail_reader_get_action_group (EMailReader *reader) { EMailReaderIface *iface; g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL); iface = E_MAIL_READER_GET_IFACE (reader); g_return_val_if_fail (iface->get_action_group != NULL, NULL); return iface->get_action_group (reader); } gboolean e_mail_reader_get_hide_deleted (EMailReader *reader) { EMailReaderIface *iface; g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE); iface = E_MAIL_READER_GET_IFACE (reader); g_return_val_if_fail (iface->get_hide_deleted != NULL, FALSE); return iface->get_hide_deleted (reader); } EMFormatHTMLDisplay * e_mail_reader_get_html_display (EMailReader *reader) { EMailReaderIface *iface; g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL); iface = E_MAIL_READER_GET_IFACE (reader); g_return_val_if_fail (iface->get_html_display != NULL, NULL); return iface->get_html_display (reader); } MessageList * e_mail_reader_get_message_list (EMailReader *reader) { EMailReaderIface *iface; g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL); iface = E_MAIL_READER_GET_IFACE (reader); g_return_val_if_fail (iface->get_message_list != NULL, NULL); return iface->get_message_list (reader); } EShellBackend * e_mail_reader_get_shell_backend (EMailReader *reader) { EMailReaderIface *iface; g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL); iface = E_MAIL_READER_GET_IFACE (reader); g_return_val_if_fail (iface->get_shell_backend != NULL, NULL); return iface->get_shell_backend (reader); } GtkWindow * e_mail_reader_get_window (EMailReader *reader) { EMailReaderIface *iface; g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL); iface = E_MAIL_READER_GET_IFACE (reader); g_return_val_if_fail (iface->get_window != NULL, NULL); return iface->get_window (reader); } void e_mail_reader_set_folder (EMailReader *reader, CamelFolder *folder, const gchar *folder_uri) { EMailReaderIface *iface; g_return_if_fail (E_IS_MAIL_READER (reader)); iface = E_MAIL_READER_GET_IFACE (reader); g_return_if_fail (iface->set_folder != NULL); iface->set_folder (reader, folder, folder_uri); } /* Helper for e_mail_reader_set_folder_uri() */ static void mail_reader_got_folder_cb (gchar *folder_uri, CamelFolder *folder, gpointer user_data) { EMailReader *reader = user_data; e_mail_reader_set_folder (reader, folder, folder_uri); } void e_mail_reader_set_folder_uri (EMailReader *reader, const gchar *folder_uri) { g_return_if_fail (E_IS_MAIL_READER (reader)); g_return_if_fail (folder_uri != NULL); /* Fetch the CamelFolder asynchronously. */ mail_get_folder ( folder_uri, 0, mail_reader_got_folder_cb, reader, mail_msg_fast_ordered_push); } void e_mail_reader_set_message (EMailReader *reader, const gchar *uid) { EMailReaderIface *iface; g_return_if_fail (E_IS_MAIL_READER (reader)); iface = E_MAIL_READER_GET_IFACE (reader); g_return_if_fail (iface->set_message != NULL); iface->set_message (reader, uid); } void e_mail_reader_create_charset_menu (EMailReader *reader, GtkUIManager *ui_manager, guint merge_id) { GtkAction *action; const gchar *action_name; const gchar *path; GSList *list; g_return_if_fail (E_IS_MAIL_READER (reader)); g_return_if_fail (GTK_IS_UI_MANAGER (ui_manager)); action_name = "mail-charset-default"; action = e_mail_reader_get_action (reader, action_name); g_return_if_fail (action != NULL); list = gtk_radio_action_get_group (GTK_RADIO_ACTION (action)); list = g_slist_copy (list); list = g_slist_remove (list, action); list = g_slist_sort (list, (GCompareFunc) e_action_compare_by_label); path = "/main-menu/view-menu/mail-message-view-actions/mail-encoding-menu"; while (list != NULL) { action = list->data; gtk_ui_manager_add_ui ( ui_manager, merge_id, path, gtk_action_get_name (action), gtk_action_get_name (action), GTK_UI_MANAGER_AUTO, FALSE); list = g_slist_delete_link (list, list); } gtk_ui_manager_ensure_update (ui_manager); } void e_mail_reader_show_search_bar (EMailReader *reader) { g_return_if_fail (E_IS_MAIL_READER (reader)); g_signal_emit (reader, signals[SHOW_SEARCH_BAR], 0); }