Bug 602612 - Add 'Alternative Reply' menu option
[evolution.git] / src / mail / e-mail-reader.c
blob75d1de343d710da7903db9f081526e321540de87
1 /*
2 * e-mail-reader.c
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * for more details.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
21 #include "evolution-config.h"
23 #include "e-mail-reader.h"
25 #include <glib/gi18n.h>
26 #include <gdk/gdkkeysyms.h>
28 #ifdef HAVE_XFREE
29 #include <X11/XF86keysym.h>
30 #endif
32 #include <shell/e-shell-utils.h>
34 #include <libemail-engine/libemail-engine.h>
36 #include <em-format/e-mail-formatter.h>
37 #include <em-format/e-mail-parser.h>
38 #include <em-format/e-mail-part-utils.h>
40 #include "e-mail-backend.h"
41 #include "e-mail-browser.h"
42 #include "e-mail-enumtypes.h"
43 #include "e-mail-notes.h"
44 #include "e-mail-reader-utils.h"
45 #include "e-mail-ui-session.h"
46 #include "e-mail-view.h"
47 #include "em-composer-utils.h"
48 #include "em-event.h"
49 #include "em-folder-selector.h"
50 #include "em-folder-tree.h"
51 #include "em-utils.h"
52 #include "mail-autofilter.h"
53 #include "mail-vfolder-ui.h"
54 #include "message-list.h"
56 #define E_MAIL_READER_GET_PRIVATE(obj) \
57 ((EMailReaderPrivate *) g_object_get_qdata \
58 (G_OBJECT (obj), quark_private))
60 #define d(x)
62 typedef struct _EMailReaderClosure EMailReaderClosure;
63 typedef struct _EMailReaderPrivate EMailReaderPrivate;
65 struct _EMailReaderClosure {
66 EMailReader *reader;
67 EActivity *activity;
68 gchar *message_uid;
71 struct _EMailReaderPrivate {
73 EMailForwardStyle forward_style;
74 EMailReplyStyle reply_style;
76 /* This timer runs when the user selects a single message. */
77 guint message_selected_timeout_id;
79 /* This allows message retrieval to be cancelled if another
80 * message is selected before the retrieval has completed. */
81 GCancellable *retrieving_message;
83 /* These flags work to prevent a folder switch from
84 * automatically marking the message as read. We only want
85 * that to happen when the -user- selects a message. */
86 guint folder_was_just_selected : 1;
87 guint avoid_next_mark_as_seen : 1;
88 guint did_try_to_open_message : 1;
90 guint group_by_threads : 1;
91 guint mark_seen_always : 1;
92 guint delete_selects_previous : 1;
94 /* to be able to start the mark_seen timeout only after
95 * the message is loaded into the EMailDisplay */
96 gboolean schedule_mark_seen;
97 guint schedule_mark_seen_interval;
99 gpointer remote_content_alert; /* EAlert */
101 gpointer followup_alert; /* weak pointer to an EAlert */
104 enum {
105 CHANGED,
106 COMPOSER_CREATED,
107 FOLDER_LOADED,
108 MESSAGE_LOADED,
109 MESSAGE_SEEN,
110 SHOW_SEARCH_BAR,
111 UPDATE_ACTIONS,
112 LAST_SIGNAL
115 /* Remembers the previously selected folder when transferring messages. */
116 static gchar *default_xfer_messages_uri;
118 static GQuark quark_private;
119 static guint signals[LAST_SIGNAL];
121 G_DEFINE_INTERFACE (EMailReader, e_mail_reader, G_TYPE_INITIALLY_UNOWNED)
123 static void
124 mail_reader_set_display_formatter_for_message (EMailReader *reader,
125 EMailDisplay *display,
126 const gchar *message_uid,
127 CamelMimeMessage *message,
128 CamelFolder *folder);
130 static void
131 mail_reader_closure_free (EMailReaderClosure *closure)
133 if (closure->reader != NULL)
134 g_object_unref (closure->reader);
136 if (closure->activity != NULL)
137 g_object_unref (closure->activity);
139 g_free (closure->message_uid);
141 g_slice_free (EMailReaderClosure, closure);
144 static void
145 mail_reader_private_free (EMailReaderPrivate *priv)
147 if (priv->message_selected_timeout_id > 0)
148 g_source_remove (priv->message_selected_timeout_id);
150 if (priv->retrieving_message != NULL) {
151 g_cancellable_cancel (priv->retrieving_message);
152 g_object_unref (priv->retrieving_message);
153 priv->retrieving_message = 0;
156 g_slice_free (EMailReaderPrivate, priv);
159 static void
160 action_mail_add_sender_cb (GtkAction *action,
161 EMailReader *reader)
163 EShell *shell;
164 EMailBackend *backend;
165 EMailSession *session;
166 EShellBackend *shell_backend;
167 CamelInternetAddress *cia;
168 CamelMessageInfo *info = NULL;
169 CamelFolder *folder;
170 GPtrArray *uids;
171 const gchar *address;
172 const gchar *message_uid;
174 folder = e_mail_reader_ref_folder (reader);
175 backend = e_mail_reader_get_backend (reader);
176 session = e_mail_backend_get_session (backend);
178 uids = e_mail_reader_get_selected_uids (reader);
179 g_return_if_fail (uids != NULL && uids->len == 1);
180 message_uid = g_ptr_array_index (uids, 0);
182 info = camel_folder_get_message_info (folder, message_uid);
183 if (info == NULL)
184 goto exit;
186 address = camel_message_info_get_from (info);
187 if (address == NULL || *address == '\0')
188 goto exit;
190 /* XXX EBookShellBackend should be listening for this
191 * event. Kind of kludgey, but works for now. */
192 shell_backend = E_SHELL_BACKEND (backend);
193 shell = e_shell_backend_get_shell (shell_backend);
194 e_shell_event (shell, "contact-quick-add-email", (gpointer) address);
196 /* Remove this address from the photo cache. */
197 cia = camel_internet_address_new ();
198 if (camel_address_decode (CAMEL_ADDRESS (cia), address) > 0) {
199 EPhotoCache *photo_cache;
200 const gchar *address_only = NULL;
202 photo_cache = e_mail_ui_session_get_photo_cache (
203 E_MAIL_UI_SESSION (session));
204 camel_internet_address_get (cia, 0, NULL, &address_only);
205 e_photo_cache_remove_photo (photo_cache, address_only);
207 g_object_unref (cia);
209 exit:
210 g_clear_object (&info);
211 g_ptr_array_unref (uids);
213 g_clear_object (&folder);
216 static void
217 action_add_to_address_book_cb (GtkAction *action,
218 EMailReader *reader)
220 EShell *shell;
221 EMailBackend *backend;
222 EMailDisplay *display;
223 EMailSession *session;
224 EShellBackend *shell_backend;
225 CamelInternetAddress *cia;
226 EPhotoCache *photo_cache;
227 EWebView *web_view;
228 CamelURL *curl;
229 const gchar *uri;
230 const gchar *address_only = NULL;
231 gchar *email;
233 /* This action is defined in EMailDisplay. */
235 backend = e_mail_reader_get_backend (reader);
236 session = e_mail_backend_get_session (backend);
238 display = e_mail_reader_get_mail_display (reader);
239 if (display == NULL)
240 return;
242 web_view = E_WEB_VIEW (display);
243 uri = e_web_view_get_selected_uri (web_view);
244 g_return_if_fail (uri != NULL);
246 curl = camel_url_new (uri, NULL);
247 g_return_if_fail (curl != NULL);
249 if (curl->path == NULL || *curl->path == '\0')
250 goto exit;
252 cia = camel_internet_address_new ();
253 if (camel_address_decode (CAMEL_ADDRESS (cia), curl->path) < 0) {
254 g_object_unref (cia);
255 goto exit;
258 /* XXX EBookShellBackend should be listening for this
259 * event. Kind of kludgey, but works for now. */
260 shell_backend = E_SHELL_BACKEND (backend);
261 shell = e_shell_backend_get_shell (shell_backend);
262 email = camel_address_format (CAMEL_ADDRESS (cia));
263 e_shell_event (shell, "contact-quick-add-email", email);
264 g_free (email);
266 /* Remove this address from the photo cache. */
267 photo_cache = e_mail_ui_session_get_photo_cache (
268 E_MAIL_UI_SESSION (session));
269 camel_internet_address_get (cia, 0, NULL, &address_only);
270 e_photo_cache_remove_photo (photo_cache, address_only);
272 g_object_unref (cia);
274 exit:
275 camel_url_free (curl);
278 static void
279 action_mail_charset_cb (GtkRadioAction *action,
280 GtkRadioAction *current,
281 EMailReader *reader)
283 EMailDisplay *display;
284 EMailFormatter *formatter;
286 if (action != current)
287 return;
289 display = e_mail_reader_get_mail_display (reader);
290 formatter = e_mail_display_get_formatter (display);
292 if (formatter != NULL) {
293 const gchar *charset;
295 /* Charset for "Default" action will be NULL. */
296 charset = g_object_get_data (G_OBJECT (action), "charset");
297 e_mail_formatter_set_charset (formatter, charset);
301 static void
302 action_mail_check_for_junk_cb (GtkAction *action,
303 EMailReader *reader)
305 EMailBackend *backend;
306 EMailSession *session;
307 CamelFolder *folder;
308 GPtrArray *uids;
310 folder = e_mail_reader_ref_folder (reader);
311 backend = e_mail_reader_get_backend (reader);
312 uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
314 session = e_mail_backend_get_session (backend);
316 mail_filter_folder (
317 session, folder, uids,
318 E_FILTER_SOURCE_JUNKTEST, FALSE);
320 g_clear_object (&folder);
321 g_ptr_array_unref (uids);
324 static void
325 mail_reader_copy_or_move_selected_messages (EMailReader *reader,
326 gboolean is_move)
328 CamelFolder *folder;
329 EMailBackend *backend;
330 EMailSession *session;
331 EMFolderSelector *selector;
332 EMFolderTree *folder_tree;
333 EMFolderTreeModel *model;
334 GtkWidget *dialog;
335 GtkWindow *window;
336 GPtrArray *uids;
337 const gchar *uri;
339 backend = e_mail_reader_get_backend (reader);
340 session = e_mail_backend_get_session (backend);
342 folder = e_mail_reader_ref_folder (reader);
343 window = e_mail_reader_get_window (reader);
344 uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
346 model = em_folder_tree_model_get_default ();
348 dialog = em_folder_selector_new (window, model);
350 gtk_window_set_title (GTK_WINDOW (dialog), is_move ? _("Move to Folder") : _("Copy to Folder"));
352 selector = EM_FOLDER_SELECTOR (dialog);
353 em_folder_selector_set_can_create (selector, TRUE);
354 em_folder_selector_set_default_button_label (selector, is_move ? _("_Move") : _("C_opy"));
356 folder_tree = em_folder_selector_get_folder_tree (selector);
358 em_folder_tree_set_excluded (
359 folder_tree,
360 EMFT_EXCLUDE_NOSELECT |
361 EMFT_EXCLUDE_VIRTUAL |
362 EMFT_EXCLUDE_VTRASH);
363 gtk_tree_view_expand_all (GTK_TREE_VIEW (folder_tree));
365 if (default_xfer_messages_uri != NULL) {
366 em_folder_tree_set_selected (
367 folder_tree, default_xfer_messages_uri, FALSE);
368 } else if (folder) {
369 gchar *uri = e_mail_folder_uri_from_folder (folder);
371 if (uri) {
372 em_folder_tree_set_selected (folder_tree, uri, FALSE);
373 g_free (uri);
377 if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK)
378 goto exit;
380 uri = em_folder_selector_get_selected_uri (selector);
382 g_free (default_xfer_messages_uri);
383 default_xfer_messages_uri = g_strdup (uri);
385 if (uri != NULL)
386 mail_transfer_messages (
387 session, folder, uids,
388 is_move, uri, 0, NULL, NULL);
390 exit:
391 gtk_widget_destroy (dialog);
393 g_clear_object (&folder);
394 g_ptr_array_unref (uids);
397 static void
398 action_mail_copy_cb (GtkAction *action,
399 EMailReader *reader)
401 mail_reader_copy_or_move_selected_messages (reader, FALSE);
404 static gboolean
405 mail_reader_replace_vee_folder_with_real (CamelFolder **inout_folder,
406 const gchar *uid,
407 gchar **out_real_uid)
409 g_return_val_if_fail (inout_folder != NULL, FALSE);
410 g_return_val_if_fail (CAMEL_IS_FOLDER (*inout_folder), FALSE);
411 g_return_val_if_fail (uid != NULL, FALSE);
412 g_return_val_if_fail (out_real_uid != NULL, FALSE);
414 *out_real_uid = NULL;
416 if (CAMEL_IS_VEE_FOLDER (*inout_folder)) {
417 CamelMessageInfo *info;
419 info = camel_folder_get_message_info (*inout_folder, uid);
420 if (info) {
421 CamelFolder *real_folder;
423 real_folder = camel_vee_folder_get_location (CAMEL_VEE_FOLDER (*inout_folder), CAMEL_VEE_MESSAGE_INFO (info), out_real_uid);
425 if (real_folder && *out_real_uid) {
426 g_object_unref (*inout_folder);
428 *inout_folder = g_object_ref (real_folder);
431 g_object_unref (info);
432 } else {
433 g_warn_if_reached ();
437 return *out_real_uid != NULL;
440 static void
441 action_mail_edit_note_cb (GtkAction *action,
442 EMailReader *reader)
444 CamelFolder *folder;
445 GPtrArray *uids;
447 folder = e_mail_reader_ref_folder (reader);
448 uids = e_mail_reader_get_selected_uids (reader);
450 if (uids && uids->len == 1) {
451 gchar *real_uid = NULL;
452 const gchar *uid = uids->pdata[0];
454 if (mail_reader_replace_vee_folder_with_real (&folder, uid, &real_uid))
455 uid = real_uid;
457 e_mail_notes_edit (e_mail_reader_get_window (reader), folder, uid);
459 g_free (real_uid);
460 } else {
461 g_warn_if_reached ();
464 g_clear_object (&folder);
465 g_ptr_array_unref (uids);
468 typedef struct {
469 CamelFolder *folder;
470 gchar *uid;
471 } DeleteNoteData;
473 static void
474 delete_note_data_free (gpointer ptr)
476 DeleteNoteData *dnd = ptr;
478 if (dnd) {
479 g_clear_object (&dnd->folder);
480 g_free (dnd->uid);
481 g_free (dnd);
485 static void
486 mail_delete_note_thread (EAlertSinkThreadJobData *job_data,
487 gpointer user_data,
488 GCancellable *cancellable,
489 GError **error)
491 DeleteNoteData *dnd = user_data;
493 g_return_if_fail (dnd != NULL);
494 g_return_if_fail (CAMEL_IS_FOLDER (dnd->folder));
495 g_return_if_fail (dnd->uid != NULL);
497 e_mail_notes_remove_sync (dnd->folder, dnd->uid, cancellable, error);
500 static void
501 action_mail_delete_note_cb (GtkAction *action,
502 EMailReader *reader)
504 CamelFolder *folder;
505 GPtrArray *uids;
507 folder = e_mail_reader_ref_folder (reader);
508 uids = e_mail_reader_get_selected_uids (reader);
510 if (uids && uids->len == 1) {
511 DeleteNoteData *dnd;
512 EAlertSink *alert_sink;
513 EActivity *activity;
514 gchar *full_display_name;
515 gchar *real_uid = NULL;
516 const gchar *uid = uids->pdata[0];
518 if (mail_reader_replace_vee_folder_with_real (&folder, uid, &real_uid))
519 uid = real_uid;
521 dnd = g_new0 (DeleteNoteData, 1);
522 dnd->folder = g_object_ref (folder);
523 dnd->uid = g_strdup (uid);
525 full_display_name = e_mail_folder_to_full_display_name (folder, NULL);
526 alert_sink = e_mail_reader_get_alert_sink (reader);
528 activity = e_alert_sink_submit_thread_job (alert_sink,
529 _("Deleting message note..."),
530 "mail:failed-delete-note",
531 full_display_name ? full_display_name : camel_folder_get_full_name (folder),
532 mail_delete_note_thread, dnd, delete_note_data_free);
534 if (activity)
535 e_shell_backend_add_activity (E_SHELL_BACKEND (e_mail_reader_get_backend (reader)), activity);
537 g_clear_object (&activity);
538 g_free (full_display_name);
539 g_free (real_uid);
540 } else {
541 g_warn_if_reached ();
544 g_clear_object (&folder);
545 g_ptr_array_unref (uids);
548 static void
549 action_mail_delete_cb (GtkAction *action,
550 EMailReader *reader)
552 guint32 mask = CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_DELETED;
553 guint32 set = CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_DELETED;
555 if (!e_mail_reader_confirm_delete (reader))
556 return;
558 /* FIXME Verify all selected messages are deletable.
559 * But handle it by disabling this action. */
561 if (e_mail_reader_mark_selected (reader, mask, set) != 0) {
562 if (e_mail_reader_get_delete_selects_previous (reader))
563 e_mail_reader_select_previous_message (reader, FALSE);
564 else
565 e_mail_reader_select_next_message (reader, FALSE);
569 static void
570 action_mail_filter_on_mailing_list_cb (GtkAction *action,
571 EMailReader *reader)
573 e_mail_reader_create_filter_from_selected (reader, AUTO_MLIST);
576 static void
577 action_mail_filter_on_recipients_cb (GtkAction *action,
578 EMailReader *reader)
580 e_mail_reader_create_filter_from_selected (reader, AUTO_TO);
583 static void
584 action_mail_filter_on_sender_cb (GtkAction *action,
585 EMailReader *reader)
587 e_mail_reader_create_filter_from_selected (reader, AUTO_FROM);
590 static void
591 action_mail_filter_on_subject_cb (GtkAction *action,
592 EMailReader *reader)
594 e_mail_reader_create_filter_from_selected (reader, AUTO_SUBJECT);
597 static void
598 action_mail_filters_apply_cb (GtkAction *action,
599 EMailReader *reader)
601 EMailBackend *backend;
602 EMailSession *session;
603 CamelFolder *folder;
604 GPtrArray *uids;
606 folder = e_mail_reader_ref_folder (reader);
607 backend = e_mail_reader_get_backend (reader);
608 uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
610 session = e_mail_backend_get_session (backend);
612 mail_filter_folder (
613 session, folder, uids,
614 E_FILTER_SOURCE_DEMAND, FALSE);
616 g_clear_object (&folder);
617 g_ptr_array_unref (uids);
620 static void
621 action_mail_remove_attachments_cb (GtkAction *action,
622 EMailReader *reader)
624 e_mail_reader_remove_attachments (reader);
627 static void
628 action_mail_remove_duplicates_cb (GtkAction *action,
629 EMailReader *reader)
631 e_mail_reader_remove_duplicates (reader);
634 static void
635 action_mail_find_cb (GtkAction *action,
636 EMailReader *reader)
638 e_mail_reader_show_search_bar (reader);
641 static void
642 action_mail_flag_clear_cb (GtkAction *action,
643 EMailReader *reader)
645 EMailDisplay *display;
646 CamelFolder *folder;
647 GtkWindow *window;
648 GPtrArray *uids;
650 folder = e_mail_reader_ref_folder (reader);
651 display = e_mail_reader_get_mail_display (reader);
652 uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
653 window = e_mail_reader_get_window (reader);
655 em_utils_flag_for_followup_clear (window, folder, uids);
657 e_mail_display_reload (display);
659 g_clear_object (&folder);
660 g_ptr_array_unref (uids);
663 static void
664 action_mail_flag_completed_cb (GtkAction *action,
665 EMailReader *reader)
667 EMailDisplay *display;
668 CamelFolder *folder;
669 GtkWindow *window;
670 GPtrArray *uids;
672 folder = e_mail_reader_ref_folder (reader);
673 display = e_mail_reader_get_mail_display (reader);
674 uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
675 window = e_mail_reader_get_window (reader);
677 em_utils_flag_for_followup_completed (window, folder, uids);
679 e_mail_display_reload (display);
681 g_clear_object (&folder);
682 g_ptr_array_unref (uids);
685 static void
686 action_mail_flag_for_followup_cb (GtkAction *action,
687 EMailReader *reader)
689 CamelFolder *folder;
690 GPtrArray *uids;
692 folder = e_mail_reader_ref_folder (reader);
693 uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
695 em_utils_flag_for_followup (reader, folder, uids);
697 g_clear_object (&folder);
698 g_ptr_array_unref (uids);
701 static void
702 action_mail_forward_cb (GtkAction *action,
703 EMailReader *reader)
705 GtkWindow *window;
706 GPtrArray *uids;
708 window = e_mail_reader_get_window (reader);
709 uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
710 g_return_if_fail (uids != NULL);
712 if (em_utils_ask_open_many (window, uids->len)) {
713 CamelFolder *folder;
715 folder = e_mail_reader_ref_folder (reader);
717 e_mail_reader_forward_messages (
718 reader, folder, uids,
719 e_mail_reader_get_forward_style (reader));
721 g_clear_object (&folder);
724 g_ptr_array_unref (uids);
727 static void
728 action_mail_forward_attached_cb (GtkAction *action,
729 EMailReader *reader)
731 GtkWindow *window;
732 GPtrArray *uids;
734 window = e_mail_reader_get_window (reader);
735 uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
736 g_return_if_fail (uids != NULL);
738 if (em_utils_ask_open_many (window, uids->len)) {
739 CamelFolder *folder;
741 folder = e_mail_reader_ref_folder (reader);
743 e_mail_reader_forward_messages (
744 reader, folder, uids,
745 E_MAIL_FORWARD_STYLE_ATTACHED);
747 g_clear_object (&folder);
750 g_ptr_array_unref (uids);
753 static void
754 action_mail_forward_inline_cb (GtkAction *action,
755 EMailReader *reader)
757 GtkWindow *window;
758 GPtrArray *uids;
760 window = e_mail_reader_get_window (reader);
761 uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
762 g_return_if_fail (uids != NULL);
764 if (em_utils_ask_open_many (window, uids->len)) {
765 CamelFolder *folder;
767 folder = e_mail_reader_ref_folder (reader);
769 e_mail_reader_forward_messages (
770 reader, folder, uids,
771 E_MAIL_FORWARD_STYLE_INLINE);
773 g_clear_object (&folder);
776 g_ptr_array_unref (uids);
779 static void
780 action_mail_forward_quoted_cb (GtkAction *action,
781 EMailReader *reader)
783 GtkWindow *window;
784 GPtrArray *uids;
786 window = e_mail_reader_get_window (reader);
787 uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
788 g_return_if_fail (uids != NULL);
790 if (em_utils_ask_open_many (window, uids->len)) {
791 CamelFolder *folder;
793 folder = e_mail_reader_ref_folder (reader);
795 e_mail_reader_forward_messages (
796 reader, folder, uids,
797 E_MAIL_FORWARD_STYLE_QUOTED);
799 g_clear_object (&folder);
802 g_ptr_array_unref (uids);
805 static void
806 action_mail_load_images_cb (GtkAction *action,
807 EMailReader *reader)
809 EMailDisplay *display;
811 display = e_mail_reader_get_mail_display (reader);
813 e_mail_display_load_images (display);
816 static void
817 action_mail_mark_important_cb (GtkAction *action,
818 EMailReader *reader)
820 guint32 mask = CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_DELETED;
821 guint32 set = CAMEL_MESSAGE_FLAGGED;
823 e_mail_reader_mark_selected (reader, mask, set);
826 static void
827 action_mail_mark_junk_cb (GtkAction *action,
828 EMailReader *reader)
830 guint32 mask =
831 CAMEL_MESSAGE_SEEN |
832 CAMEL_MESSAGE_JUNK |
833 CAMEL_MESSAGE_NOTJUNK |
834 CAMEL_MESSAGE_JUNK_LEARN;
835 guint32 set =
836 CAMEL_MESSAGE_SEEN |
837 CAMEL_MESSAGE_JUNK |
838 CAMEL_MESSAGE_JUNK_LEARN;
840 if (e_mail_reader_mark_selected (reader, mask, set) != 0) {
841 if (e_mail_reader_get_delete_selects_previous (reader))
842 e_mail_reader_select_previous_message (reader, TRUE);
843 else
844 e_mail_reader_select_next_message (reader, TRUE);
848 static void
849 action_mail_mark_notjunk_cb (GtkAction *action,
850 EMailReader *reader)
852 guint32 mask =
853 CAMEL_MESSAGE_JUNK |
854 CAMEL_MESSAGE_NOTJUNK |
855 CAMEL_MESSAGE_JUNK_LEARN;
856 guint32 set =
857 CAMEL_MESSAGE_NOTJUNK |
858 CAMEL_MESSAGE_JUNK_LEARN;
860 if (e_mail_reader_mark_selected (reader, mask, set) != 0) {
861 if (e_mail_reader_get_delete_selects_previous (reader))
862 e_mail_reader_select_previous_message (reader, TRUE);
863 else
864 e_mail_reader_select_next_message (reader, TRUE);
868 static void
869 action_mail_mark_read_cb (GtkAction *action,
870 EMailReader *reader)
872 guint32 mask = CAMEL_MESSAGE_SEEN;
873 guint32 set = CAMEL_MESSAGE_SEEN;
875 e_mail_reader_mark_selected (reader, mask, set);
878 static void
879 action_mail_mark_unimportant_cb (GtkAction *action,
880 EMailReader *reader)
882 guint32 mask = CAMEL_MESSAGE_FLAGGED;
883 guint32 set = 0;
885 e_mail_reader_mark_selected (reader, mask, set);
888 static void
889 action_mail_mark_ignore_thread_sub_cb (GtkAction *action,
890 EMailReader *reader)
892 e_mail_reader_mark_selected_ignore_thread (reader, E_IGNORE_THREAD_SUBSET_SET);
895 static void
896 action_mail_mark_unignore_thread_sub_cb (GtkAction *action,
897 EMailReader *reader)
899 e_mail_reader_mark_selected_ignore_thread (reader, E_IGNORE_THREAD_SUBSET_UNSET);
902 static void
903 action_mail_mark_ignore_thread_whole_cb (GtkAction *action,
904 EMailReader *reader)
906 e_mail_reader_mark_selected_ignore_thread (reader, E_IGNORE_THREAD_WHOLE_SET);
909 static void
910 action_mail_mark_unignore_thread_whole_cb (GtkAction *action,
911 EMailReader *reader)
913 e_mail_reader_mark_selected_ignore_thread (reader, E_IGNORE_THREAD_WHOLE_UNSET);
916 static void
917 action_mail_mark_unread_cb (GtkAction *action,
918 EMailReader *reader)
920 GtkWidget *message_list;
921 EMFolderTreeModel *model;
922 CamelFolder *folder;
923 guint32 mask = CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_DELETED;
924 guint32 set = 0;
925 guint n_marked;
927 message_list = e_mail_reader_get_message_list (reader);
929 n_marked = e_mail_reader_mark_selected (reader, mask, set);
931 if (MESSAGE_LIST (message_list)->seen_id != 0) {
932 g_source_remove (MESSAGE_LIST (message_list)->seen_id);
933 MESSAGE_LIST (message_list)->seen_id = 0;
936 folder = e_mail_reader_ref_folder (reader);
938 /* Notify the tree model that the user has marked messages as
939 * unread so it doesn't mistake the event as new mail arriving. */
940 model = em_folder_tree_model_get_default ();
941 em_folder_tree_model_user_marked_unread (model, folder, n_marked);
943 g_clear_object (&folder);
946 static void
947 action_mail_message_edit_cb (GtkAction *action,
948 EMailReader *reader)
950 EShell *shell;
951 EMailBackend *backend;
952 ESourceRegistry *registry;
953 CamelFolder *folder;
954 GPtrArray *uids;
955 gboolean replace;
957 uids = e_mail_reader_get_selected_uids (reader);
958 g_return_if_fail (uids != NULL);
960 backend = e_mail_reader_get_backend (reader);
961 shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
962 registry = e_shell_get_registry (shell);
964 folder = e_mail_reader_ref_folder (reader);
965 replace = em_utils_folder_is_drafts (registry, folder);
966 e_mail_reader_edit_messages (reader, folder, uids, replace, replace);
967 g_clear_object (&folder);
969 g_ptr_array_unref (uids);
972 typedef struct _CreateComposerData {
973 EMailReader *reader;
974 CamelMimeMessage *message;
975 CamelFolder *folder;
976 const gchar *message_uid; /* In the Camel string pool */
977 gboolean is_redirect;
978 } CreateComposerData;
980 static void
981 mail_reader_new_composer_created_cb (GObject *source_object,
982 GAsyncResult *result,
983 gpointer user_data)
985 CreateComposerData *ccd = user_data;
986 EMsgComposer *composer;
987 GError *error = NULL;
989 g_return_if_fail (ccd != NULL);
991 composer = e_msg_composer_new_finish (result, &error);
992 if (error) {
993 g_warning ("%s: Failed to create msg composer: %s", G_STRFUNC, error->message);
994 g_clear_error (&error);
995 } else {
996 if (ccd->is_redirect)
997 em_utils_redirect_message (composer, ccd->message);
998 else
999 em_utils_compose_new_message_with_selection (composer, ccd->folder, ccd->message_uid);
1001 e_mail_reader_composer_created (ccd->reader, composer, ccd->message);
1004 g_clear_object (&ccd->reader);
1005 g_clear_object (&ccd->message);
1006 g_clear_object (&ccd->folder);
1007 camel_pstring_free (ccd->message_uid);
1008 g_free (ccd);
1011 static void
1012 action_mail_message_new_cb (GtkAction *action,
1013 EMailReader *reader)
1015 EShell *shell;
1016 EMailBackend *backend;
1017 EShellBackend *shell_backend;
1018 CamelFolder *folder;
1019 CreateComposerData *ccd;
1020 GPtrArray *selected_uids = NULL;
1021 const gchar *selected_uid = NULL;
1023 folder = e_mail_reader_ref_folder (reader);
1024 backend = e_mail_reader_get_backend (reader);
1026 selected_uids = e_mail_reader_get_selected_uids (reader);
1027 if (selected_uids && selected_uids->len > 0)
1028 selected_uid = g_ptr_array_index (selected_uids, 0);
1030 if (!selected_uid) {
1031 GtkWidget *message_list;
1033 message_list = e_mail_reader_get_message_list (reader);
1034 if (message_list)
1035 selected_uid = MESSAGE_LIST (message_list)->cursor_uid;
1038 shell_backend = E_SHELL_BACKEND (backend);
1039 shell = e_shell_backend_get_shell (shell_backend);
1041 ccd = g_new0 (CreateComposerData, 1);
1042 ccd->reader = g_object_ref (reader);
1043 ccd->folder = folder;
1044 ccd->message_uid = camel_pstring_strdup (selected_uid);
1045 ccd->is_redirect = FALSE;
1047 e_msg_composer_new (shell, mail_reader_new_composer_created_cb, ccd);
1049 if (selected_uids)
1050 g_ptr_array_unref (selected_uids);
1053 static void
1054 action_mail_message_open_cb (GtkAction *action,
1055 EMailReader *reader)
1057 e_mail_reader_open_selected_mail (reader);
1060 static void
1061 action_mail_archive_cb (GtkAction *action,
1062 EMailReader *reader)
1064 CamelFolder *folder;
1065 EMailBackend *backend;
1066 EMailSession *session;
1067 GPtrArray *uids;
1068 gchar *archive_folder;
1070 backend = e_mail_reader_get_backend (reader);
1071 session = e_mail_backend_get_session (backend);
1073 uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
1074 g_return_if_fail (uids != NULL);
1076 folder = e_mail_reader_ref_folder (reader);
1077 archive_folder = em_utils_get_archive_folder_uri_from_folder (folder, backend, uids, TRUE);
1079 if (archive_folder != NULL)
1080 mail_transfer_messages (
1081 session, folder, uids,
1082 TRUE, archive_folder, 0, NULL, NULL);
1084 g_clear_object (&folder);
1085 g_ptr_array_unref (uids);
1086 g_free (archive_folder);
1089 static void
1090 action_mail_move_cb (GtkAction *action,
1091 EMailReader *reader)
1093 mail_reader_copy_or_move_selected_messages (reader, TRUE);
1096 static void
1097 action_mail_next_cb (GtkAction *action,
1098 EMailReader *reader)
1100 GtkWidget *message_list;
1101 MessageListSelectDirection direction;
1102 guint32 flags, mask;
1104 direction = MESSAGE_LIST_SELECT_NEXT;
1105 flags = 0;
1106 mask = 0;
1108 message_list = e_mail_reader_get_message_list (reader);
1110 message_list_select (
1111 MESSAGE_LIST (message_list), direction, flags, mask);
1114 static void
1115 action_mail_next_important_cb (GtkAction *action,
1116 EMailReader *reader)
1118 GtkWidget *message_list;
1119 MessageListSelectDirection direction;
1120 guint32 flags, mask;
1122 direction = MESSAGE_LIST_SELECT_NEXT | MESSAGE_LIST_SELECT_WRAP;
1123 flags = CAMEL_MESSAGE_FLAGGED;
1124 mask = CAMEL_MESSAGE_FLAGGED;
1126 message_list = e_mail_reader_get_message_list (reader);
1128 message_list_select (
1129 MESSAGE_LIST (message_list), direction, flags, mask);
1132 static void
1133 action_mail_next_thread_cb (GtkAction *action,
1134 EMailReader *reader)
1136 GtkWidget *message_list;
1138 message_list = e_mail_reader_get_message_list (reader);
1140 message_list_select_next_thread (MESSAGE_LIST (message_list));
1143 static void
1144 action_mail_next_unread_cb (GtkAction *action,
1145 EMailReader *reader)
1147 GtkWidget *message_list;
1148 MessageListSelectDirection direction;
1149 guint32 flags, mask;
1151 direction = MESSAGE_LIST_SELECT_NEXT | MESSAGE_LIST_SELECT_WRAP;
1152 flags = 0;
1153 mask = CAMEL_MESSAGE_SEEN;
1155 message_list = e_mail_reader_get_message_list (reader);
1157 message_list_select (
1158 MESSAGE_LIST (message_list), direction, flags, mask);
1161 static void
1162 action_mail_previous_cb (GtkAction *action,
1163 EMailReader *reader)
1165 GtkWidget *message_list;
1166 MessageListSelectDirection direction;
1167 guint32 flags, mask;
1169 direction = MESSAGE_LIST_SELECT_PREVIOUS;
1170 flags = 0;
1171 mask = 0;
1173 message_list = e_mail_reader_get_message_list (reader);
1175 message_list_select (
1176 MESSAGE_LIST (message_list), direction, flags, mask);
1179 static void
1180 action_mail_previous_important_cb (GtkAction *action,
1181 EMailReader *reader)
1183 GtkWidget *message_list;
1184 MessageListSelectDirection direction;
1185 guint32 flags, mask;
1187 direction = MESSAGE_LIST_SELECT_PREVIOUS | MESSAGE_LIST_SELECT_WRAP;
1188 flags = CAMEL_MESSAGE_FLAGGED;
1189 mask = CAMEL_MESSAGE_FLAGGED;
1191 message_list = e_mail_reader_get_message_list (reader);
1193 message_list_select (
1194 MESSAGE_LIST (message_list), direction, flags, mask);
1197 static void
1198 action_mail_previous_thread_cb (GtkAction *action,
1199 EMailReader *reader)
1201 GtkWidget *message_list;
1203 message_list = e_mail_reader_get_message_list (reader);
1205 message_list_select_prev_thread (MESSAGE_LIST (message_list));
1208 static void
1209 action_mail_previous_unread_cb (GtkAction *action,
1210 EMailReader *reader)
1212 GtkWidget *message_list;
1213 MessageListSelectDirection direction;
1214 guint32 flags, mask;
1216 direction = MESSAGE_LIST_SELECT_PREVIOUS | MESSAGE_LIST_SELECT_WRAP;
1217 flags = 0;
1218 mask = CAMEL_MESSAGE_SEEN;
1220 message_list = e_mail_reader_get_message_list (reader);
1222 message_list_select (
1223 MESSAGE_LIST (message_list), direction, flags, mask);
1226 static void
1227 action_mail_print_cb (GtkAction *action,
1228 EMailReader *reader)
1230 GtkPrintOperationAction print_action;
1232 print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG;
1233 e_mail_reader_print (reader, print_action);
1236 static void
1237 action_mail_print_preview_cb (GtkAction *action,
1238 EMailReader *reader)
1240 GtkPrintOperationAction print_action;
1242 print_action = GTK_PRINT_OPERATION_ACTION_PREVIEW;
1243 e_mail_reader_print (reader, print_action);
1246 static void
1247 mail_reader_redirect_cb (CamelFolder *folder,
1248 GAsyncResult *result,
1249 EMailReaderClosure *closure)
1251 EShell *shell;
1252 EMailBackend *backend;
1253 EAlertSink *alert_sink;
1254 CamelMimeMessage *message;
1255 CreateComposerData *ccd;
1256 GError *error = NULL;
1258 alert_sink = e_activity_get_alert_sink (closure->activity);
1260 message = camel_folder_get_message_finish (folder, result, &error);
1262 if (e_activity_handle_cancellation (closure->activity, error)) {
1263 g_warn_if_fail (message == NULL);
1264 mail_reader_closure_free (closure);
1265 g_error_free (error);
1266 return;
1268 } else if (error != NULL) {
1269 g_warn_if_fail (message == NULL);
1270 e_alert_submit (
1271 alert_sink, "mail:no-retrieve-message",
1272 error->message, NULL);
1273 mail_reader_closure_free (closure);
1274 g_error_free (error);
1275 return;
1278 g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
1280 backend = e_mail_reader_get_backend (closure->reader);
1281 shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
1283 ccd = g_new0 (CreateComposerData, 1);
1284 ccd->reader = g_object_ref (closure->reader);
1285 ccd->message = message;
1286 ccd->message_uid = camel_pstring_strdup (closure->message_uid);
1287 ccd->is_redirect = TRUE;
1289 e_msg_composer_new (shell, mail_reader_new_composer_created_cb, ccd);
1291 mail_reader_closure_free (closure);
1294 static void
1295 action_mail_redirect_cb (GtkAction *action,
1296 EMailReader *reader)
1298 EActivity *activity;
1299 GCancellable *cancellable;
1300 EMailReaderClosure *closure;
1301 GtkWidget *message_list;
1302 CamelFolder *folder;
1303 const gchar *message_uid;
1305 message_list = e_mail_reader_get_message_list (reader);
1306 message_uid = MESSAGE_LIST (message_list)->cursor_uid;
1307 g_return_if_fail (message_uid != NULL);
1309 /* Open the message asynchronously. */
1311 activity = e_mail_reader_new_activity (reader);
1312 cancellable = e_activity_get_cancellable (activity);
1314 closure = g_slice_new0 (EMailReaderClosure);
1315 closure->activity = activity;
1316 closure->reader = g_object_ref (reader);
1317 closure->message_uid = g_strdup (message_uid);
1319 folder = e_mail_reader_ref_folder (reader);
1321 camel_folder_get_message (
1322 folder, message_uid, G_PRIORITY_DEFAULT,
1323 cancellable, (GAsyncReadyCallback)
1324 mail_reader_redirect_cb, closure);
1326 g_clear_object (&folder);
1329 static void
1330 action_mail_reply_all_check (CamelFolder *folder,
1331 GAsyncResult *result,
1332 EMailReaderClosure *closure)
1334 EAlertSink *alert_sink;
1335 CamelMimeMessage *message;
1336 CamelInternetAddress *to, *cc;
1337 gint recip_count = 0;
1338 EMailReplyType type = E_MAIL_REPLY_TO_ALL;
1339 GError *error = NULL;
1341 alert_sink = e_activity_get_alert_sink (closure->activity);
1343 message = camel_folder_get_message_finish (folder, result, &error);
1345 if (e_activity_handle_cancellation (closure->activity, error)) {
1346 g_warn_if_fail (message == NULL);
1347 mail_reader_closure_free (closure);
1348 g_error_free (error);
1349 return;
1351 } else if (error != NULL) {
1352 g_warn_if_fail (message == NULL);
1353 e_alert_submit (
1354 alert_sink, "mail:no-retrieve-message",
1355 error->message, NULL);
1356 mail_reader_closure_free (closure);
1357 g_error_free (error);
1358 return;
1361 g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
1363 to = camel_mime_message_get_recipients (
1364 message, CAMEL_RECIPIENT_TYPE_TO);
1365 cc = camel_mime_message_get_recipients (
1366 message, CAMEL_RECIPIENT_TYPE_CC);
1368 recip_count = camel_address_length (CAMEL_ADDRESS (to));
1369 recip_count += camel_address_length (CAMEL_ADDRESS (cc));
1371 if (recip_count >= 15) {
1372 GtkWidget *dialog;
1373 GtkWidget *check;
1374 GtkWidget *container;
1375 gint response;
1377 dialog = e_alert_dialog_new_for_args (
1378 e_mail_reader_get_window (closure->reader),
1379 "mail:ask-reply-many-recips", NULL);
1381 container = e_alert_dialog_get_content_area (
1382 E_ALERT_DIALOG (dialog));
1384 /* Check buttons */
1385 check = gtk_check_button_new_with_mnemonic (
1386 _("_Do not ask me again."));
1387 gtk_box_pack_start (
1388 GTK_BOX (container), check, FALSE, FALSE, 0);
1389 gtk_widget_show (check);
1391 response = gtk_dialog_run (GTK_DIALOG (dialog));
1393 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check))) {
1394 GSettings *settings;
1395 const gchar *key;
1397 settings = e_util_ref_settings ("org.gnome.evolution.mail");
1399 key = "prompt-on-reply-many-recips";
1400 g_settings_set_boolean (settings, key, FALSE);
1402 g_object_unref (settings);
1405 gtk_widget_destroy (dialog);
1407 switch (response) {
1408 case GTK_RESPONSE_NO:
1409 type = E_MAIL_REPLY_TO_SENDER;
1410 break;
1411 case GTK_RESPONSE_CANCEL:
1412 case GTK_RESPONSE_DELETE_EVENT:
1413 goto exit;
1414 default:
1415 break;
1419 e_mail_reader_reply_to_message (closure->reader, message, type);
1421 exit:
1422 g_object_unref (message);
1424 mail_reader_closure_free (closure);
1427 static void
1428 action_mail_reply_all_cb (GtkAction *action,
1429 EMailReader *reader)
1431 GSettings *settings;
1432 const gchar *key;
1433 guint32 state;
1434 gboolean ask;
1436 state = e_mail_reader_check_state (reader);
1438 settings = e_util_ref_settings ("org.gnome.evolution.mail");
1440 key = "prompt-on-reply-many-recips";
1441 ask = g_settings_get_boolean (settings, key);
1443 g_object_unref (settings);
1445 if (ask && !(state & E_MAIL_READER_SELECTION_IS_MAILING_LIST)) {
1446 EActivity *activity;
1447 GCancellable *cancellable;
1448 EMailReaderClosure *closure;
1449 CamelFolder *folder;
1450 GtkWidget *message_list;
1451 const gchar *message_uid;
1453 message_list = e_mail_reader_get_message_list (reader);
1454 message_uid = MESSAGE_LIST (message_list)->cursor_uid;
1455 g_return_if_fail (message_uid != NULL);
1457 activity = e_mail_reader_new_activity (reader);
1458 cancellable = e_activity_get_cancellable (activity);
1460 closure = g_slice_new0 (EMailReaderClosure);
1461 closure->activity = activity;
1462 closure->reader = g_object_ref (reader);
1464 folder = e_mail_reader_ref_folder (reader);
1466 camel_folder_get_message (
1467 folder, message_uid, G_PRIORITY_DEFAULT,
1468 cancellable, (GAsyncReadyCallback)
1469 action_mail_reply_all_check, closure);
1471 g_clear_object (&folder);
1473 return;
1476 e_mail_reader_reply_to_message (reader, NULL, E_MAIL_REPLY_TO_ALL);
1479 static void
1480 action_mail_reply_alternative_got_message (CamelFolder *folder,
1481 GAsyncResult *result,
1482 EMailReaderClosure *closure)
1484 EAlertSink *alert_sink;
1485 EMailDisplay *mail_display;
1486 CamelMimeMessage *message;
1487 GError *error = NULL;
1489 alert_sink = e_activity_get_alert_sink (closure->activity);
1491 message = camel_folder_get_message_finish (folder, result, &error);
1493 if (e_activity_handle_cancellation (closure->activity, error)) {
1494 g_warn_if_fail (message == NULL);
1495 mail_reader_closure_free (closure);
1496 g_error_free (error);
1497 return;
1499 } else if (error != NULL) {
1500 g_warn_if_fail (message == NULL);
1501 e_alert_submit (
1502 alert_sink, "mail:no-retrieve-message",
1503 error->message, NULL);
1504 mail_reader_closure_free (closure);
1505 g_error_free (error);
1506 return;
1509 g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
1511 g_clear_object (&closure->activity);
1513 mail_display = e_mail_reader_get_mail_display (closure->reader);
1515 em_utils_reply_alternative (e_mail_reader_get_window (closure->reader),
1516 e_shell_backend_get_shell (E_SHELL_BACKEND (e_mail_reader_get_backend (closure->reader))),
1517 alert_sink, message, folder, closure->message_uid,
1518 e_mail_reader_get_reply_style (closure->reader),
1519 mail_display ? e_mail_display_get_part_list (mail_display) : NULL);
1521 g_object_unref (message);
1522 mail_reader_closure_free (closure);
1525 static void
1526 action_mail_reply_alternative_cb (GtkAction *action,
1527 EMailReader *reader)
1529 EActivity *activity;
1530 GCancellable *cancellable;
1531 EMailReaderClosure *closure;
1532 CamelFolder *folder;
1533 GtkWidget *message_list;
1534 const gchar *message_uid;
1536 message_list = e_mail_reader_get_message_list (reader);
1537 message_uid = MESSAGE_LIST (message_list)->cursor_uid;
1538 g_return_if_fail (message_uid != NULL);
1540 activity = e_mail_reader_new_activity (reader);
1541 cancellable = e_activity_get_cancellable (activity);
1543 closure = g_slice_new0 (EMailReaderClosure);
1544 closure->activity = activity;
1545 closure->reader = g_object_ref (reader);
1546 closure->message_uid = g_strdup (message_uid);
1548 folder = e_mail_reader_ref_folder (reader);
1550 camel_folder_get_message (
1551 folder, message_uid, G_PRIORITY_DEFAULT,
1552 cancellable, (GAsyncReadyCallback)
1553 action_mail_reply_alternative_got_message, closure);
1555 g_clear_object (&folder);
1558 static void
1559 action_mail_reply_group_cb (GtkAction *action,
1560 EMailReader *reader)
1562 GSettings *settings;
1563 gboolean reply_list;
1564 guint32 state;
1565 const gchar *key;
1567 state = e_mail_reader_check_state (reader);
1569 settings = e_util_ref_settings ("org.gnome.evolution.mail");
1571 key = "composer-group-reply-to-list";
1572 reply_list = g_settings_get_boolean (settings, key);
1574 g_object_unref (settings);
1576 if (reply_list && (state & E_MAIL_READER_SELECTION_IS_MAILING_LIST)) {
1577 e_mail_reader_reply_to_message (
1578 reader, NULL, E_MAIL_REPLY_TO_LIST);
1579 } else
1580 action_mail_reply_all_cb (action, reader);
1583 static void
1584 action_mail_reply_list_cb (GtkAction *action,
1585 EMailReader *reader)
1587 e_mail_reader_reply_to_message (reader, NULL, E_MAIL_REPLY_TO_LIST);
1590 static gboolean
1591 message_is_list_administrative (CamelMimeMessage *message)
1593 const gchar *header;
1595 header = camel_medium_get_header (
1596 CAMEL_MEDIUM (message), "X-List-Administrivia");
1597 if (header == NULL)
1598 return FALSE;
1600 while (*header == ' ' || *header == '\t')
1601 header++;
1603 return g_ascii_strncasecmp (header, "yes", 3) == 0;
1606 static void
1607 action_mail_reply_sender_check (CamelFolder *folder,
1608 GAsyncResult *result,
1609 EMailReaderClosure *closure)
1611 EAlertSink *alert_sink;
1612 CamelMimeMessage *message;
1613 EMailReplyType type = E_MAIL_REPLY_TO_SENDER;
1614 GSettings *settings;
1615 gboolean ask_ignore_list_reply_to;
1616 gboolean ask_list_reply_to;
1617 gboolean munged_list_message;
1618 gboolean active;
1619 const gchar *key;
1620 GError *local_error = NULL;
1622 alert_sink = e_activity_get_alert_sink (closure->activity);
1624 message = camel_folder_get_message_finish (
1625 folder, result, &local_error);
1627 /* Sanity check. */
1628 g_return_if_fail (
1629 ((message != NULL) && (local_error == NULL)) ||
1630 ((message == NULL) && (local_error != NULL)));
1632 if (e_activity_handle_cancellation (closure->activity, local_error)) {
1633 mail_reader_closure_free (closure);
1634 g_error_free (local_error);
1635 return;
1637 } else if (local_error != NULL) {
1638 e_alert_submit (
1639 alert_sink, "mail:no-retrieve-message",
1640 local_error->message, NULL);
1641 mail_reader_closure_free (closure);
1642 g_error_free (local_error);
1643 return;
1646 settings = e_util_ref_settings ("org.gnome.evolution.mail");
1648 key = "composer-ignore-list-reply-to";
1649 ask_ignore_list_reply_to = g_settings_get_boolean (settings, key);
1651 key = "prompt-on-list-reply-to";
1652 ask_list_reply_to = g_settings_get_boolean (settings, key);
1654 munged_list_message = em_utils_is_munged_list_message (message);
1656 if (message_is_list_administrative (message)) {
1657 /* Do not ask for messages which are list administrative,
1658 * like list confirmation messages. */
1659 } else if (ask_ignore_list_reply_to || !munged_list_message) {
1660 /* Don't do the "Are you sure you want to reply in private?"
1661 * pop-up if it's a Reply-To: munged list message... unless
1662 * we're ignoring munging. */
1663 GtkWidget *dialog;
1664 GtkWidget *check;
1665 GtkWidget *container;
1666 gint response;
1668 dialog = e_alert_dialog_new_for_args (
1669 e_mail_reader_get_window (closure->reader),
1670 "mail:ask-list-private-reply", NULL);
1672 container = e_alert_dialog_get_content_area (
1673 E_ALERT_DIALOG (dialog));
1675 /* Check buttons */
1676 check = gtk_check_button_new_with_mnemonic (
1677 _("_Do not ask me again."));
1678 gtk_box_pack_start (
1679 GTK_BOX (container), check, FALSE, FALSE, 0);
1680 gtk_widget_show (check);
1682 response = gtk_dialog_run (GTK_DIALOG (dialog));
1684 active = gtk_toggle_button_get_active (
1685 GTK_TOGGLE_BUTTON (check));
1686 if (active) {
1687 key = "prompt-on-private-list-reply";
1688 g_settings_set_boolean (settings, key, FALSE);
1691 gtk_widget_destroy (dialog);
1693 if (response == GTK_RESPONSE_YES)
1694 type = E_MAIL_REPLY_TO_ALL;
1695 else if (response == GTK_RESPONSE_OK)
1696 type = E_MAIL_REPLY_TO_LIST;
1697 else if (response == GTK_RESPONSE_CANCEL ||
1698 response == GTK_RESPONSE_DELETE_EVENT) {
1699 goto exit;
1702 } else if (ask_list_reply_to) {
1703 GtkWidget *dialog;
1704 GtkWidget *container;
1705 GtkWidget *check_again;
1706 GtkWidget *check_always_ignore;
1707 gint response;
1709 dialog = e_alert_dialog_new_for_args (
1710 e_mail_reader_get_window (closure->reader),
1711 "mail:ask-list-honour-reply-to", NULL);
1713 container = e_alert_dialog_get_content_area (
1714 E_ALERT_DIALOG (dialog));
1716 check_again = gtk_check_button_new_with_mnemonic (
1717 _("_Do not ask me again."));
1718 gtk_box_pack_start (
1719 GTK_BOX (container), check_again, FALSE, FALSE, 0);
1720 gtk_widget_show (check_again);
1722 check_always_ignore = gtk_check_button_new_with_mnemonic (
1723 _("_Always ignore Reply-To: for mailing lists."));
1724 gtk_box_pack_start (
1725 GTK_BOX (container), check_always_ignore,
1726 FALSE, FALSE, 0);
1727 gtk_widget_show (check_always_ignore);
1729 response = gtk_dialog_run (GTK_DIALOG (dialog));
1731 active = gtk_toggle_button_get_active (
1732 GTK_TOGGLE_BUTTON (check_again));
1733 if (active) {
1734 key = "prompt-on-list-reply-to";
1735 g_settings_set_boolean (settings, key, FALSE);
1738 key = "composer-ignore-list-reply-to";
1739 active = gtk_toggle_button_get_active (
1740 GTK_TOGGLE_BUTTON (check_always_ignore));
1741 g_settings_set_boolean (settings, key, active);
1743 gtk_widget_destroy (dialog);
1745 switch (response) {
1746 case GTK_RESPONSE_NO:
1747 type = E_MAIL_REPLY_TO_FROM;
1748 break;
1749 case GTK_RESPONSE_OK:
1750 type = E_MAIL_REPLY_TO_LIST;
1751 break;
1752 case GTK_RESPONSE_CANCEL:
1753 case GTK_RESPONSE_DELETE_EVENT:
1754 goto exit;
1755 default:
1756 break;
1760 e_mail_reader_reply_to_message (closure->reader, message, type);
1762 exit:
1763 g_object_unref (settings);
1764 g_object_unref (message);
1766 mail_reader_closure_free (closure);
1769 static void
1770 action_mail_reply_sender_cb (GtkAction *action,
1771 EMailReader *reader)
1773 GSettings *settings;
1774 gboolean ask_list_reply_to;
1775 gboolean ask_private_list_reply;
1776 gboolean ask;
1777 guint32 state;
1778 const gchar *key;
1780 state = e_mail_reader_check_state (reader);
1782 settings = e_util_ref_settings ("org.gnome.evolution.mail");
1784 key = "prompt-on-list-reply-to";
1785 ask_list_reply_to = g_settings_get_boolean (settings, key);
1787 key = "prompt-on-private-list-reply";
1788 ask_private_list_reply = g_settings_get_boolean (settings, key);
1790 g_object_unref (settings);
1792 ask = (ask_private_list_reply || ask_list_reply_to);
1794 if (ask && (state & E_MAIL_READER_SELECTION_IS_MAILING_LIST)) {
1795 EActivity *activity;
1796 GCancellable *cancellable;
1797 EMailReaderClosure *closure;
1798 CamelFolder *folder;
1799 GtkWidget *message_list;
1800 const gchar *message_uid;
1802 message_list = e_mail_reader_get_message_list (reader);
1803 message_uid = MESSAGE_LIST (message_list)->cursor_uid;
1804 g_return_if_fail (message_uid != NULL);
1806 activity = e_mail_reader_new_activity (reader);
1807 cancellable = e_activity_get_cancellable (activity);
1809 closure = g_slice_new0 (EMailReaderClosure);
1810 closure->activity = activity;
1811 closure->reader = g_object_ref (reader);
1813 folder = e_mail_reader_ref_folder (reader);
1815 camel_folder_get_message (
1816 folder, message_uid, G_PRIORITY_DEFAULT,
1817 cancellable, (GAsyncReadyCallback)
1818 action_mail_reply_sender_check, closure);
1820 g_clear_object (&folder);
1822 return;
1825 e_mail_reader_reply_to_message (reader, NULL, E_MAIL_REPLY_TO_SENDER);
1828 static void
1829 action_mail_reply_recipient_cb (GtkAction *action,
1830 EMailReader *reader)
1832 e_mail_reader_reply_to_message (reader, NULL, E_MAIL_REPLY_TO_RECIPIENT);
1835 static void
1836 action_mail_save_as_cb (GtkAction *action,
1837 EMailReader *reader)
1839 e_mail_reader_save_messages (reader);
1842 static void
1843 action_mail_search_folder_from_mailing_list_cb (GtkAction *action,
1844 EMailReader *reader)
1846 e_mail_reader_create_vfolder_from_selected (reader, AUTO_MLIST);
1849 static void
1850 action_mail_search_folder_from_recipients_cb (GtkAction *action,
1851 EMailReader *reader)
1853 e_mail_reader_create_vfolder_from_selected (reader, AUTO_TO);
1856 static void
1857 action_mail_search_folder_from_sender_cb (GtkAction *action,
1858 EMailReader *reader)
1860 e_mail_reader_create_vfolder_from_selected (reader, AUTO_FROM);
1863 static void
1864 action_mail_search_folder_from_subject_cb (GtkAction *action,
1865 EMailReader *reader)
1867 e_mail_reader_create_vfolder_from_selected (reader, AUTO_SUBJECT);
1870 static void
1871 action_mail_show_all_headers_cb (GtkToggleAction *action,
1872 EMailReader *reader)
1874 EMailDisplay *display;
1875 EMailFormatterMode mode;
1877 display = e_mail_reader_get_mail_display (reader);
1879 /* Ignore action when viewing message source. */
1880 mode = e_mail_display_get_mode (display);
1881 if (mode == E_MAIL_FORMATTER_MODE_SOURCE)
1882 return;
1883 if (mode == E_MAIL_FORMATTER_MODE_RAW)
1884 return;
1886 if (gtk_toggle_action_get_active (action))
1887 mode = E_MAIL_FORMATTER_MODE_ALL_HEADERS;
1888 else
1889 mode = E_MAIL_FORMATTER_MODE_NORMAL;
1891 e_mail_display_set_mode (display, mode);
1894 static void
1895 mail_source_retrieved (GObject *source_object,
1896 GAsyncResult *result,
1897 gpointer user_data)
1899 EMailReaderClosure *closure;
1900 CamelMimeMessage *message;
1901 EMailDisplay *display;
1902 GError *error = NULL;
1904 closure = (EMailReaderClosure *) user_data;
1905 display = e_mail_reader_get_mail_display (closure->reader);
1907 message = camel_folder_get_message_finish (
1908 CAMEL_FOLDER (source_object), result, &error);
1910 /* Sanity check. */
1911 g_return_if_fail (
1912 ((message != NULL) && (error == NULL)) ||
1913 ((message == NULL) && (error != NULL)));
1915 if (message != NULL) {
1916 mail_reader_set_display_formatter_for_message (
1917 closure->reader, display,
1918 closure->message_uid, message,
1919 CAMEL_FOLDER (source_object));
1920 g_object_unref (message);
1921 } else {
1922 gchar *status;
1924 status = g_strdup_printf (
1925 "%s<br>%s",
1926 _("Failed to retrieve message:"),
1927 error->message);
1928 e_mail_display_set_status (display, status);
1929 g_free (status);
1931 g_error_free (error);
1934 e_activity_set_state (closure->activity, E_ACTIVITY_COMPLETED);
1936 mail_reader_closure_free (closure);
1939 static void
1940 action_mail_show_source_cb (GtkAction *action,
1941 EMailReader *reader)
1943 EMailDisplay *display;
1944 EMailBackend *backend;
1945 GtkWidget *browser;
1946 CamelFolder *folder;
1947 GPtrArray *uids;
1948 const gchar *message_uid;
1949 gchar *string;
1950 EActivity *activity;
1951 GCancellable *cancellable;
1952 EMailReaderClosure *closure;
1953 MessageList *ml;
1955 backend = e_mail_reader_get_backend (reader);
1956 folder = e_mail_reader_ref_folder (reader);
1957 uids = e_mail_reader_get_selected_uids (reader);
1958 g_return_if_fail (uids != NULL && uids->len == 1);
1959 message_uid = g_ptr_array_index (uids, 0);
1961 browser = e_mail_browser_new (backend, E_MAIL_FORMATTER_MODE_SOURCE);
1962 ml = MESSAGE_LIST (e_mail_reader_get_message_list (E_MAIL_READER (browser)));
1964 message_list_freeze (ml);
1965 e_mail_reader_set_folder (E_MAIL_READER (browser), folder);
1966 e_mail_reader_set_message (E_MAIL_READER (browser), message_uid);
1967 message_list_thaw (ml);
1969 display = e_mail_reader_get_mail_display (E_MAIL_READER (browser));
1971 string = g_strdup_printf (_("Retrieving message “%s”"), message_uid);
1972 e_mail_display_set_part_list (display, NULL);
1973 e_mail_display_set_status (display, string);
1974 gtk_widget_show (browser);
1976 activity = e_mail_reader_new_activity (reader);
1977 e_activity_set_text (activity, string);
1978 cancellable = e_activity_get_cancellable (activity);
1979 g_free (string);
1981 closure = g_slice_new0 (EMailReaderClosure);
1982 closure->reader = g_object_ref (browser);
1983 closure->activity = g_object_ref (activity);
1984 closure->message_uid = g_strdup (message_uid);
1986 camel_folder_get_message (
1987 folder, message_uid, G_PRIORITY_DEFAULT,
1988 cancellable, mail_source_retrieved, closure);
1990 g_object_unref (activity);
1992 g_ptr_array_unref (uids);
1994 g_clear_object (&folder);
1997 static void
1998 action_mail_toggle_important_cb (GtkAction *action,
1999 EMailReader *reader)
2001 CamelFolder *folder;
2002 GPtrArray *uids;
2003 guint ii;
2005 folder = e_mail_reader_ref_folder (reader);
2006 uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
2008 camel_folder_freeze (folder);
2010 for (ii = 0; ii < uids->len; ii++) {
2011 guint32 flags;
2013 flags = camel_folder_get_message_flags (
2014 folder, uids->pdata[ii]);
2015 flags ^= CAMEL_MESSAGE_FLAGGED;
2016 if (flags & CAMEL_MESSAGE_FLAGGED)
2017 flags &= ~CAMEL_MESSAGE_DELETED;
2019 camel_folder_set_message_flags (
2020 folder, uids->pdata[ii], CAMEL_MESSAGE_FLAGGED |
2021 CAMEL_MESSAGE_DELETED, flags);
2024 camel_folder_thaw (folder);
2026 g_clear_object (&folder);
2027 g_ptr_array_unref (uids);
2030 static void
2031 action_mail_undelete_cb (GtkAction *action,
2032 EMailReader *reader)
2034 guint32 mask = CAMEL_MESSAGE_DELETED;
2035 guint32 set = 0;
2037 e_mail_reader_mark_selected (reader, mask, set);
2040 static void
2041 action_mail_zoom_100_cb (GtkAction *action,
2042 EMailReader *reader)
2044 EMailDisplay *display;
2046 display = e_mail_reader_get_mail_display (reader);
2048 e_web_view_zoom_100 (E_WEB_VIEW (display));
2051 static void
2052 action_mail_zoom_in_cb (GtkAction *action,
2053 EMailReader *reader)
2055 EMailDisplay *display;
2057 display = e_mail_reader_get_mail_display (reader);
2059 e_web_view_zoom_in (E_WEB_VIEW (display));
2062 static void
2063 action_mail_zoom_out_cb (GtkAction *action,
2064 EMailReader *reader)
2066 EMailDisplay *display;
2068 display = e_mail_reader_get_mail_display (reader);
2070 e_web_view_zoom_out (E_WEB_VIEW (display));
2073 static void
2074 action_search_folder_recipient_cb (GtkAction *action,
2075 EMailReader *reader)
2077 EMailBackend *backend;
2078 EMailSession *session;
2079 EWebView *web_view;
2080 CamelURL *curl;
2081 const gchar *uri;
2083 /* This action is defined in EMailDisplay. */
2085 web_view = E_WEB_VIEW (e_mail_reader_get_mail_display (reader));
2087 uri = e_web_view_get_selected_uri (web_view);
2088 g_return_if_fail (uri != NULL);
2090 curl = camel_url_new (uri, NULL);
2091 g_return_if_fail (curl != NULL);
2093 backend = e_mail_reader_get_backend (reader);
2094 session = e_mail_backend_get_session (backend);
2096 if (curl->path != NULL && *curl->path != '\0') {
2097 CamelFolder *folder;
2098 CamelInternetAddress *inet_addr;
2100 folder = e_mail_reader_ref_folder (reader);
2102 inet_addr = camel_internet_address_new ();
2103 camel_address_decode (CAMEL_ADDRESS (inet_addr), curl->path);
2104 vfolder_gui_add_from_address (
2105 session, inet_addr, AUTO_TO, folder);
2106 g_object_unref (inet_addr);
2108 g_clear_object (&folder);
2111 camel_url_free (curl);
2114 static void
2115 action_search_folder_sender_cb (GtkAction *action,
2116 EMailReader *reader)
2118 EMailBackend *backend;
2119 EMailSession *session;
2120 EWebView *web_view;
2121 CamelURL *curl;
2122 const gchar *uri;
2124 /* This action is defined in EMailDisplay. */
2126 web_view = E_WEB_VIEW (e_mail_reader_get_mail_display (reader));
2128 uri = e_web_view_get_selected_uri (web_view);
2129 g_return_if_fail (uri != NULL);
2131 curl = camel_url_new (uri, NULL);
2132 g_return_if_fail (curl != NULL);
2134 backend = e_mail_reader_get_backend (reader);
2135 session = e_mail_backend_get_session (backend);
2137 if (curl->path != NULL && *curl->path != '\0') {
2138 CamelFolder *folder;
2139 CamelInternetAddress *inet_addr;
2141 folder = e_mail_reader_ref_folder (reader);
2143 inet_addr = camel_internet_address_new ();
2144 camel_address_decode (CAMEL_ADDRESS (inet_addr), curl->path);
2145 vfolder_gui_add_from_address (
2146 session, inet_addr, AUTO_FROM, folder);
2147 g_object_unref (inet_addr);
2149 g_clear_object (&folder);
2152 camel_url_free (curl);
2155 static GtkActionEntry mail_reader_entries[] = {
2157 { "mail-add-sender",
2158 NULL,
2159 N_("A_dd Sender to Address Book"),
2160 NULL,
2161 N_("Add sender to address book"),
2162 G_CALLBACK (action_mail_add_sender_cb) },
2164 { "mail-archive",
2165 "mail-archive",
2166 N_("_Archive..."),
2167 "<Alt><Control>a",
2168 N_("Move selected messages to the Archive folder for the account"),
2169 G_CALLBACK (action_mail_archive_cb) },
2171 { "mail-check-for-junk",
2172 "mail-mark-junk",
2173 N_("Check for _Junk"),
2174 "<Control><Alt>j",
2175 N_("Filter the selected messages for junk status"),
2176 G_CALLBACK (action_mail_check_for_junk_cb) },
2178 { "mail-copy",
2179 "mail-copy",
2180 N_("_Copy to Folder..."),
2181 "<Shift><Control>y",
2182 N_("Copy selected messages to another folder"),
2183 G_CALLBACK (action_mail_copy_cb) },
2185 { "mail-delete",
2186 "user-trash",
2187 N_("_Delete Message"),
2188 "<Control>d",
2189 N_("Mark the selected messages for deletion"),
2190 G_CALLBACK (action_mail_delete_cb) },
2192 { "mail-add-note",
2193 "evolution-memos",
2194 N_("_Add note..."),
2195 NULL,
2196 N_("Add a note for the selected message"),
2197 G_CALLBACK (action_mail_edit_note_cb) },
2199 { "mail-delete-note",
2200 NULL,
2201 N_("Delete no_te"),
2202 NULL,
2203 N_("Delete the note for the selected message"),
2204 G_CALLBACK (action_mail_delete_note_cb) },
2206 { "mail-edit-note",
2207 "evolution-memos",
2208 N_("_Edit note..."),
2209 NULL,
2210 N_("Edit a note for the selected message"),
2211 G_CALLBACK (action_mail_edit_note_cb) },
2213 { "mail-filter-rule-for-mailing-list",
2214 NULL,
2215 N_("Create a Filter Rule for Mailing _List..."),
2216 NULL,
2217 N_("Create a rule to filter messages to this mailing list"),
2218 G_CALLBACK (action_mail_filter_on_mailing_list_cb) },
2220 { "mail-filter-rule-for-recipients",
2221 NULL,
2222 N_("Create a Filter Rule for _Recipients..."),
2223 NULL,
2224 N_("Create a rule to filter messages to these recipients"),
2225 G_CALLBACK (action_mail_filter_on_recipients_cb) },
2227 { "mail-filter-rule-for-sender",
2228 NULL,
2229 N_("Create a Filter Rule for Se_nder..."),
2230 NULL,
2231 N_("Create a rule to filter messages from this sender"),
2232 G_CALLBACK (action_mail_filter_on_sender_cb) },
2234 { "mail-filter-rule-for-subject",
2235 NULL,
2236 N_("Create a Filter Rule for _Subject..."),
2237 NULL,
2238 N_("Create a rule to filter messages with this subject"),
2239 G_CALLBACK (action_mail_filter_on_subject_cb) },
2241 { "mail-filters-apply",
2242 "stock_mail-filters-apply",
2243 N_("A_pply Filters"),
2244 "<Control>y",
2245 N_("Apply filter rules to the selected messages"),
2246 G_CALLBACK (action_mail_filters_apply_cb) },
2248 { "mail-find",
2249 "edit-find",
2250 N_("_Find in Message..."),
2251 "<Shift><Control>f",
2252 N_("Search for text in the body of the displayed message"),
2253 G_CALLBACK (action_mail_find_cb) },
2255 { "mail-flag-clear",
2256 NULL,
2257 N_("_Clear Flag"),
2258 NULL,
2259 N_("Remove the follow-up flag from the selected messages"),
2260 G_CALLBACK (action_mail_flag_clear_cb) },
2262 { "mail-flag-completed",
2263 NULL,
2264 N_("_Flag Completed"),
2265 NULL,
2266 N_("Set the follow-up flag to completed on the selected messages"),
2267 G_CALLBACK (action_mail_flag_completed_cb) },
2269 { "mail-flag-for-followup",
2270 "stock_mail-flag-for-followup",
2271 N_("Follow _Up..."),
2272 "<Shift><Control>g",
2273 N_("Flag the selected messages for follow-up"),
2274 G_CALLBACK (action_mail_flag_for_followup_cb) },
2276 { "mail-forward-attached",
2277 NULL,
2278 N_("_Attached"),
2279 NULL,
2280 N_("Forward the selected message to someone as an attachment"),
2281 G_CALLBACK (action_mail_forward_attached_cb) },
2283 { "mail-forward-attached-full",
2284 NULL,
2285 N_("Forward As _Attached"),
2286 NULL,
2287 N_("Forward the selected message to someone as an attachment"),
2288 G_CALLBACK (action_mail_forward_attached_cb) },
2290 { "mail-forward-inline",
2291 NULL,
2292 N_("_Inline"),
2293 NULL,
2294 N_("Forward the selected message in the body of a new message"),
2295 G_CALLBACK (action_mail_forward_inline_cb) },
2297 { "mail-forward-inline-full",
2298 NULL,
2299 N_("Forward As _Inline"),
2300 NULL,
2301 N_("Forward the selected message in the body of a new message"),
2302 G_CALLBACK (action_mail_forward_inline_cb) },
2304 { "mail-forward-quoted",
2305 NULL,
2306 N_("_Quoted"),
2307 NULL,
2308 N_("Forward the selected message quoted like a reply"),
2309 G_CALLBACK (action_mail_forward_quoted_cb) },
2311 { "mail-forward-quoted-full",
2312 NULL,
2313 N_("Forward As _Quoted"),
2314 NULL,
2315 N_("Forward the selected message quoted like a reply"),
2316 G_CALLBACK (action_mail_forward_quoted_cb) },
2318 { "mail-load-images",
2319 "image-x-generic",
2320 N_("_Load Images"),
2321 "<Control>i",
2322 N_("Force images in HTML mail to be loaded"),
2323 G_CALLBACK (action_mail_load_images_cb) },
2325 { "mail-mark-ignore-thread-sub",
2326 NULL,
2327 N_("_Ignore Subthread"),
2328 NULL,
2329 N_("Mark new mails in a subthread as read automatically"),
2330 G_CALLBACK (action_mail_mark_ignore_thread_sub_cb) },
2332 { "mail-mark-ignore-thread-whole",
2333 NULL,
2334 N_("_Ignore Thread"),
2335 NULL,
2336 N_("Mark new mails in this thread as read automatically"),
2337 G_CALLBACK (action_mail_mark_ignore_thread_whole_cb) },
2339 { "mail-mark-important",
2340 "mail-mark-important",
2341 N_("_Important"),
2342 NULL,
2343 N_("Mark the selected messages as important"),
2344 G_CALLBACK (action_mail_mark_important_cb) },
2346 { "mail-mark-junk",
2347 "mail-mark-junk",
2348 N_("_Junk"),
2349 "<Control>j",
2350 N_("Mark the selected messages as junk"),
2351 G_CALLBACK (action_mail_mark_junk_cb) },
2353 { "mail-mark-notjunk",
2354 "mail-mark-notjunk",
2355 N_("_Not Junk"),
2356 "<Shift><Control>j",
2357 N_("Mark the selected messages as not being junk"),
2358 G_CALLBACK (action_mail_mark_notjunk_cb) },
2360 { "mail-mark-read",
2361 "mail-mark-read",
2362 N_("_Read"),
2363 "<Control>k",
2364 N_("Mark the selected messages as having been read"),
2365 G_CALLBACK (action_mail_mark_read_cb) },
2367 { "mail-mark-unignore-thread-sub",
2368 NULL,
2369 N_("Do not _Ignore Subthread"),
2370 NULL,
2371 N_("Do not mark new mails in a subthread as read automatically"),
2372 G_CALLBACK (action_mail_mark_unignore_thread_sub_cb) },
2374 { "mail-mark-unignore-thread-whole",
2375 NULL,
2376 N_("Do not _Ignore Thread"),
2377 NULL,
2378 N_("Do not mark new mails in this thread as read automatically"),
2379 G_CALLBACK (action_mail_mark_unignore_thread_whole_cb) },
2381 { "mail-mark-unimportant",
2382 NULL,
2383 N_("Uni_mportant"),
2384 NULL,
2385 N_("Mark the selected messages as unimportant"),
2386 G_CALLBACK (action_mail_mark_unimportant_cb) },
2388 { "mail-mark-unread",
2389 "mail-mark-unread",
2390 N_("_Unread"),
2391 "<Shift><Control>k",
2392 N_("Mark the selected messages as not having been read"),
2393 G_CALLBACK (action_mail_mark_unread_cb) },
2395 { "mail-message-edit",
2396 NULL,
2397 N_("_Edit as New Message..."),
2398 NULL,
2399 N_("Open the selected messages in the composer for editing"),
2400 G_CALLBACK (action_mail_message_edit_cb) },
2402 { "mail-message-new",
2403 "mail-message-new",
2404 N_("Compose _New Message"),
2405 "<Shift><Control>m",
2406 N_("Open a window for composing a mail message"),
2407 G_CALLBACK (action_mail_message_new_cb) },
2409 { "mail-message-open",
2410 NULL,
2411 N_("_Open in New Window"),
2412 "<Control>o",
2413 N_("Open the selected messages in a new window"),
2414 G_CALLBACK (action_mail_message_open_cb) },
2416 { "mail-move",
2417 "mail-move",
2418 N_("_Move to Folder..."),
2419 "<Shift><Control>v",
2420 N_("Move selected messages to another folder"),
2421 G_CALLBACK (action_mail_move_cb) },
2423 { "mail-next",
2424 "go-next",
2425 N_("_Next Message"),
2426 "<Control>Page_Down",
2427 N_("Display the next message"),
2428 G_CALLBACK (action_mail_next_cb) },
2430 { "mail-next-important",
2431 NULL,
2432 N_("Next _Important Message"),
2433 NULL,
2434 N_("Display the next important message"),
2435 G_CALLBACK (action_mail_next_important_cb) },
2437 { "mail-next-thread",
2438 NULL,
2439 N_("Next _Thread"),
2440 NULL,
2441 N_("Display the next thread"),
2442 G_CALLBACK (action_mail_next_thread_cb) },
2444 { "mail-next-unread",
2445 "go-jump",
2446 N_("Next _Unread Message"),
2447 "<Control>bracketright",
2448 N_("Display the next unread message"),
2449 G_CALLBACK (action_mail_next_unread_cb) },
2451 { "mail-previous",
2452 "go-previous",
2453 N_("_Previous Message"),
2454 "<Control>Page_Up",
2455 N_("Display the previous message"),
2456 G_CALLBACK (action_mail_previous_cb) },
2458 { "mail-previous-important",
2459 NULL,
2460 N_("Pr_evious Important Message"),
2461 NULL,
2462 N_("Display the previous important message"),
2463 G_CALLBACK (action_mail_previous_important_cb) },
2465 { "mail-previous-thread",
2466 NULL,
2467 N_("Previous T_hread"),
2468 NULL,
2469 N_("Display the previous thread"),
2470 G_CALLBACK (action_mail_previous_thread_cb) },
2472 { "mail-previous-unread",
2473 NULL,
2474 N_("P_revious Unread Message"),
2475 "<Control>bracketleft",
2476 N_("Display the previous unread message"),
2477 G_CALLBACK (action_mail_previous_unread_cb) },
2479 { "mail-print",
2480 "document-print",
2481 N_("_Print..."),
2482 "<Control>p",
2483 N_("Print this message"),
2484 G_CALLBACK (action_mail_print_cb) },
2486 { "mail-print-preview",
2487 "document-print-preview",
2488 N_("Pre_view..."),
2489 NULL,
2490 N_("Preview the message to be printed"),
2491 G_CALLBACK (action_mail_print_preview_cb) },
2493 { "mail-redirect",
2494 NULL,
2495 N_("Re_direct"),
2496 NULL,
2497 N_("Redirect (bounce) the selected message to someone"),
2498 G_CALLBACK (action_mail_redirect_cb) },
2500 { "mail-remove-attachments",
2501 "edit-delete",
2502 N_("Remo_ve Attachments"),
2503 NULL,
2504 N_("Remove attachments"),
2505 G_CALLBACK (action_mail_remove_attachments_cb) },
2507 { "mail-remove-duplicates",
2508 NULL,
2509 N_("Remove Du_plicate Messages"),
2510 NULL,
2511 N_("Checks selected messages for duplicates"),
2512 G_CALLBACK (action_mail_remove_duplicates_cb) },
2514 { "mail-reply-all",
2515 NULL,
2516 N_("Reply to _All"),
2517 "<Shift><Control>r",
2518 N_("Compose a reply to all the recipients of the selected message"),
2519 G_CALLBACK (action_mail_reply_all_cb) },
2521 { "mail-reply-alternative",
2522 NULL,
2523 N_("Al_ternative Reply…"),
2524 "<Alt><Control>r",
2525 N_("Choose reply options for the selected message"),
2526 G_CALLBACK (action_mail_reply_alternative_cb) },
2528 { "mail-reply-list",
2529 NULL,
2530 N_("Reply to _List"),
2531 "<Control>l",
2532 N_("Compose a reply to the mailing list of the selected message"),
2533 G_CALLBACK (action_mail_reply_list_cb) },
2535 { "mail-reply-sender",
2536 "mail-reply-sender",
2537 N_("_Reply to Sender"),
2538 "<Control>r",
2539 N_("Compose a reply to the sender of the selected message"),
2540 G_CALLBACK (action_mail_reply_sender_cb) },
2542 { "mail-save-as",
2543 "document-save-as",
2544 N_("_Save as mbox..."),
2545 "<Control>s",
2546 N_("Save selected messages as an mbox file"),
2547 G_CALLBACK (action_mail_save_as_cb) },
2549 { "mail-show-source",
2550 NULL,
2551 N_("_Message Source"),
2552 "<Control>u",
2553 N_("Show the raw email source of the message"),
2554 G_CALLBACK (action_mail_show_source_cb) },
2556 { "mail-toggle-important",
2557 NULL,
2558 NULL, /* No menu item; key press only */
2559 NULL,
2560 NULL,
2561 G_CALLBACK (action_mail_toggle_important_cb) },
2563 { "mail-undelete",
2564 NULL,
2565 N_("_Undelete Message"),
2566 "<Shift><Control>d",
2567 N_("Undelete the selected messages"),
2568 G_CALLBACK (action_mail_undelete_cb) },
2570 { "mail-zoom-100",
2571 "zoom-original",
2572 N_("_Normal Size"),
2573 "<Control>0",
2574 N_("Reset the text to its original size"),
2575 G_CALLBACK (action_mail_zoom_100_cb) },
2577 { "mail-zoom-in",
2578 "zoom-in",
2579 N_("_Zoom In"),
2580 "<Control>plus",
2581 N_("Increase the text size"),
2582 G_CALLBACK (action_mail_zoom_in_cb) },
2584 { "mail-zoom-out",
2585 "zoom-out",
2586 N_("Zoom _Out"),
2587 "<Control>minus",
2588 N_("Decrease the text size"),
2589 G_CALLBACK (action_mail_zoom_out_cb) },
2591 /*** Menus ***/
2593 { "mail-create-menu",
2594 NULL,
2595 N_("Cre_ate"),
2596 NULL,
2597 NULL,
2598 NULL },
2600 { "mail-encoding-menu",
2601 NULL,
2602 N_("Ch_aracter Encoding"),
2603 NULL,
2604 NULL,
2605 NULL },
2607 { "mail-forward-as-menu",
2608 NULL,
2609 N_("F_orward As"),
2610 NULL,
2611 NULL,
2612 NULL },
2614 { "mail-reply-group-menu",
2615 NULL,
2616 N_("_Group Reply"),
2617 NULL,
2618 NULL,
2619 NULL },
2621 { "mail-goto-menu",
2622 NULL,
2623 N_("_Go To"),
2624 NULL,
2625 NULL,
2626 NULL },
2628 { "mail-mark-as-menu",
2629 NULL,
2630 N_("Mar_k As"),
2631 NULL,
2632 NULL,
2633 NULL },
2635 { "mail-message-menu",
2636 NULL,
2637 N_("_Message"),
2638 NULL,
2639 NULL,
2640 NULL },
2642 { "mail-zoom-menu",
2643 NULL,
2644 N_("_Zoom"),
2645 NULL,
2646 NULL,
2647 NULL }
2650 static GtkActionEntry mail_reader_search_folder_entries[] = {
2652 { "mail-search-folder-from-mailing-list",
2653 NULL,
2654 N_("Create a Search Folder from Mailing _List..."),
2655 NULL,
2656 N_("Create a search folder for this mailing list"),
2657 G_CALLBACK (action_mail_search_folder_from_mailing_list_cb) },
2659 { "mail-search-folder-from-recipients",
2660 NULL,
2661 N_("Create a Search Folder from Recipien_ts..."),
2662 NULL,
2663 N_("Create a search folder for these recipients"),
2664 G_CALLBACK (action_mail_search_folder_from_recipients_cb) },
2666 { "mail-search-folder-from-sender",
2667 NULL,
2668 N_("Create a Search Folder from Sen_der..."),
2669 NULL,
2670 N_("Create a search folder for this sender"),
2671 G_CALLBACK (action_mail_search_folder_from_sender_cb) },
2673 { "mail-search-folder-from-subject",
2674 NULL,
2675 N_("Create a Search Folder from S_ubject..."),
2676 NULL,
2677 N_("Create a search folder for this subject"),
2678 G_CALLBACK (action_mail_search_folder_from_subject_cb) },
2681 static EPopupActionEntry mail_reader_popup_entries[] = {
2683 { "mail-popup-archive",
2684 NULL,
2685 "mail-archive" },
2687 { "mail-popup-copy",
2688 NULL,
2689 "mail-copy" },
2691 { "mail-popup-delete",
2692 NULL,
2693 "mail-delete" },
2695 { "mail-popup-add-note",
2696 NULL,
2697 "mail-add-note" },
2699 { "mail-popup-delete-note",
2700 NULL,
2701 "mail-delete-note" },
2703 { "mail-popup-edit-note",
2704 NULL,
2705 "mail-edit-note" },
2707 { "mail-popup-flag-clear",
2708 NULL,
2709 "mail-flag-clear" },
2711 { "mail-popup-flag-completed",
2712 NULL,
2713 "mail-flag-completed" },
2715 { "mail-popup-flag-for-followup",
2716 N_("Mark for Follo_w Up..."),
2717 "mail-flag-for-followup" },
2719 { "mail-popup-forward",
2720 NULL,
2721 "mail-forward" },
2723 { "mail-popup-mark-ignore-thread-sub",
2724 N_("_Ignore Subthread"),
2725 "mail-mark-ignore-thread-sub" },
2727 { "mail-popup-mark-ignore-thread-whole",
2728 N_("_Ignore Thread"),
2729 "mail-mark-ignore-thread-whole" },
2731 { "mail-popup-mark-important",
2732 N_("Mark as _Important"),
2733 "mail-mark-important" },
2735 { "mail-popup-mark-junk",
2736 N_("Mark as _Junk"),
2737 "mail-mark-junk" },
2739 { "mail-popup-mark-notjunk",
2740 N_("Mark as _Not Junk"),
2741 "mail-mark-notjunk" },
2743 { "mail-popup-mark-read",
2744 N_("Mar_k as Read"),
2745 "mail-mark-read" },
2747 { "mail-popup-mark-unignore-thread-sub",
2748 N_("Do not _Ignore Subthread"),
2749 "mail-mark-unignore-thread-sub" },
2751 { "mail-popup-mark-unignore-thread-whole",
2752 N_("Do not _Ignore Thread"),
2753 "mail-mark-unignore-thread-whole" },
2755 { "mail-popup-mark-unimportant",
2756 N_("Mark as Uni_mportant"),
2757 "mail-mark-unimportant" },
2759 { "mail-popup-mark-unread",
2760 N_("Mark as _Unread"),
2761 "mail-mark-unread" },
2763 { "mail-popup-message-edit",
2764 NULL,
2765 "mail-message-edit" },
2767 { "mail-popup-move",
2768 NULL,
2769 "mail-move" },
2771 { "mail-popup-print",
2772 NULL,
2773 "mail-print" },
2775 { "mail-popup-remove-attachments",
2776 NULL,
2777 "mail-remove-attachments" },
2779 { "mail-popup-remove-duplicates",
2780 NULL,
2781 "mail-remove-duplicates" },
2783 { "mail-popup-reply-all",
2784 NULL,
2785 "mail-reply-all" },
2787 { "mail-popup-reply-sender",
2788 NULL,
2789 "mail-reply-sender" },
2791 { "mail-popup-save-as",
2792 NULL,
2793 "mail-save-as" },
2795 { "mail-popup-undelete",
2796 NULL,
2797 "mail-undelete" }
2800 static GtkToggleActionEntry mail_reader_toggle_entries[] = {
2802 { "mail-caret-mode",
2803 NULL,
2804 N_("_Caret Mode"),
2805 "F7",
2806 N_("Show a blinking cursor in the body of displayed messages"),
2807 NULL, /* No callback required */
2808 FALSE },
2810 { "mail-show-all-headers",
2811 NULL,
2812 N_("All Message _Headers"),
2813 NULL,
2814 N_("Show messages with all email headers"),
2815 G_CALLBACK (action_mail_show_all_headers_cb),
2816 FALSE }
2819 static void
2820 mail_reader_double_click_cb (EMailReader *reader,
2821 gint row,
2822 ETreePath path,
2823 gint col,
2824 GdkEvent *event)
2826 GtkAction *action;
2828 /* Ignore double clicks on columns that handle their own state. */
2829 if (MESSAGE_LIST_COLUMN_IS_ACTIVE (col))
2830 return;
2832 action = e_mail_reader_get_action (reader, "mail-message-open");
2833 gtk_action_activate (action);
2836 static gboolean
2837 mail_reader_key_press_event_cb (EMailReader *reader,
2838 GdkEventKey *event)
2840 GtkAction *action;
2841 const gchar *action_name;
2843 if (!gtk_widget_has_focus (GTK_WIDGET (reader))) {
2844 EMailDisplay *display;
2846 display = e_mail_reader_get_mail_display (reader);
2847 if (e_web_view_get_need_input (E_WEB_VIEW (display)) &&
2848 gtk_widget_has_focus (GTK_WIDGET (display)))
2849 return FALSE;
2852 if ((event->state & GDK_CONTROL_MASK) != 0)
2853 goto ctrl;
2855 /* <keyval> alone */
2856 switch (event->keyval) {
2857 case GDK_KEY_Delete:
2858 case GDK_KEY_KP_Delete:
2859 action_name = "mail-delete";
2860 break;
2862 case GDK_KEY_Return:
2863 case GDK_KEY_KP_Enter:
2864 case GDK_KEY_ISO_Enter:
2865 if (E_IS_MAIL_BROWSER (reader))
2866 return FALSE;
2868 action_name = "mail-message-open";
2869 break;
2871 case GDK_KEY_period:
2872 case GDK_KEY_bracketright:
2873 action_name = "mail-next-unread";
2874 break;
2876 case GDK_KEY_comma:
2877 case GDK_KEY_bracketleft:
2878 action_name = "mail-previous-unread";
2879 break;
2881 #ifdef HAVE_XFREE
2882 case XF86XK_Reply:
2883 action_name = "mail-reply-all";
2884 break;
2886 case XF86XK_MailForward:
2887 action_name = "mail-forward";
2888 break;
2889 #endif
2891 case GDK_KEY_exclam:
2892 action_name = "mail-toggle-important";
2893 break;
2895 case GDK_KEY_ZoomIn:
2896 action_name = "mail-zoom-in";
2897 break;
2899 case GDK_KEY_ZoomOut:
2900 action_name = "mail-zoom-out";
2901 break;
2903 default:
2904 return FALSE;
2907 goto exit;
2909 ctrl:
2911 /* Ctrl + <keyval> */
2912 switch (event->keyval) {
2913 case GDK_KEY_period:
2914 action_name = "mail-next-unread";
2915 break;
2917 case GDK_KEY_comma:
2918 action_name = "mail-previous-unread";
2919 break;
2921 case GDK_KEY_equal:
2922 case GDK_KEY_KP_Add:
2923 action_name = "mail-zoom-in";
2924 break;
2926 case GDK_KEY_KP_Subtract:
2927 action_name = "mail-zoom-out";
2928 break;
2930 default:
2931 return FALSE;
2934 exit:
2935 action = e_mail_reader_get_action (reader, action_name);
2936 gtk_action_activate (action);
2938 return TRUE;
2941 static gint
2942 mail_reader_key_press_cb (EMailReader *reader,
2943 gint row,
2944 ETreePath path,
2945 gint col,
2946 GdkEvent *event)
2948 return mail_reader_key_press_event_cb (reader, &event->key);
2951 static gboolean
2952 mail_reader_message_seen_cb (gpointer user_data)
2954 EMailReaderClosure *closure = user_data;
2955 EMailReader *reader;
2956 GtkWidget *message_list;
2957 EMailPartList *parts;
2958 EMailDisplay *display;
2959 CamelMimeMessage *message;
2960 const gchar *current_uid;
2961 const gchar *message_uid;
2962 gboolean uid_is_current = TRUE;
2964 reader = closure->reader;
2965 message_uid = closure->message_uid;
2967 display = e_mail_reader_get_mail_display (reader);
2968 parts = e_mail_display_get_part_list (display);
2969 message_list = e_mail_reader_get_message_list (reader);
2971 g_return_val_if_fail (IS_MESSAGE_LIST (message_list), FALSE);
2973 /* zero the timeout id now, if it was not rescheduled */
2974 if (g_source_get_id (g_main_current_source ()) == MESSAGE_LIST (message_list)->seen_id)
2975 MESSAGE_LIST (message_list)->seen_id = 0;
2977 if (e_tree_is_dragging (E_TREE (message_list)))
2978 return FALSE;
2980 current_uid = MESSAGE_LIST (message_list)->cursor_uid;
2981 uid_is_current &= (g_strcmp0 (current_uid, message_uid) == 0);
2983 if (parts != NULL)
2984 message = e_mail_part_list_get_message (parts);
2985 else
2986 message = NULL;
2988 if (uid_is_current && message != NULL)
2989 g_signal_emit (
2990 reader, signals[MESSAGE_SEEN], 0,
2991 message_uid, message);
2993 return FALSE;
2996 static void
2997 schedule_timeout_mark_seen (EMailReader *reader)
2999 EMailReaderPrivate *priv;
3000 MessageList *message_list;
3002 g_return_if_fail (E_IS_MAIL_READER (reader));
3004 priv = E_MAIL_READER_GET_PRIVATE (reader);
3006 message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
3007 g_return_if_fail (message_list != NULL);
3009 if (message_list->cursor_uid) {
3010 EMailReaderClosure *timeout_closure;
3012 if (message_list->seen_id > 0) {
3013 g_source_remove (message_list->seen_id);
3014 message_list->seen_id = 0;
3017 timeout_closure = g_slice_new0 (EMailReaderClosure);
3018 timeout_closure->reader = g_object_ref (reader);
3019 timeout_closure->message_uid = g_strdup (message_list->cursor_uid);
3021 MESSAGE_LIST (message_list)->seen_id =
3022 e_named_timeout_add_full (
3023 G_PRIORITY_DEFAULT, priv->schedule_mark_seen_interval,
3024 mail_reader_message_seen_cb,
3025 timeout_closure, (GDestroyNotify)
3026 mail_reader_closure_free);
3030 static void
3031 mail_reader_load_changed_cb (EMailReader *reader,
3032 WebKitLoadEvent event,
3033 EMailDisplay *display)
3035 EMailReaderPrivate *priv;
3037 if (event != WEBKIT_LOAD_FINISHED)
3038 return;
3040 priv = E_MAIL_READER_GET_PRIVATE (reader);
3041 if (priv->schedule_mark_seen &&
3042 E_IS_MAIL_VIEW (reader) &&
3043 e_mail_display_get_part_list (display) &&
3044 e_mail_view_get_preview_visible (E_MAIL_VIEW (reader))) {
3045 if (priv->folder_was_just_selected)
3046 priv->folder_was_just_selected = FALSE;
3047 else
3048 schedule_timeout_mark_seen (reader);
3052 static gboolean
3053 maybe_schedule_timeout_mark_seen (EMailReader *reader)
3055 EMailReaderPrivate *priv;
3056 MessageList *message_list;
3057 GSettings *settings;
3058 gboolean schedule_timeout;
3059 gint timeout_interval;
3060 const gchar *message_uid;
3062 message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
3064 message_uid = message_list->cursor_uid;
3065 if (message_uid == NULL ||
3066 e_tree_is_dragging (E_TREE (message_list)))
3067 return FALSE;
3069 settings = e_util_ref_settings ("org.gnome.evolution.mail");
3071 /* FIXME These should be EMailReader properties. */
3072 schedule_timeout =
3073 (message_uid != NULL) &&
3074 g_settings_get_boolean (settings, "mark-seen");
3075 timeout_interval = g_settings_get_int (settings, "mark-seen-timeout");
3077 g_object_unref (settings);
3079 if (message_list->seen_id > 0) {
3080 g_source_remove (message_list->seen_id);
3081 message_list->seen_id = 0;
3084 priv = E_MAIL_READER_GET_PRIVATE (reader);
3085 priv->schedule_mark_seen = schedule_timeout;
3086 priv->schedule_mark_seen_interval = timeout_interval;
3088 return schedule_timeout;
3091 static gboolean
3092 discard_timeout_mark_seen_cb (EMailReader *reader)
3094 EMailReaderPrivate *priv;
3095 MessageList *message_list;
3097 g_return_val_if_fail (reader != NULL, FALSE);
3099 priv = E_MAIL_READER_GET_PRIVATE (reader);
3100 priv->schedule_mark_seen = FALSE;
3102 message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
3103 g_return_val_if_fail (message_list != NULL, FALSE);
3105 if (message_list->seen_id > 0) {
3106 g_source_remove (message_list->seen_id);
3107 message_list->seen_id = 0;
3110 return FALSE;
3114 static void
3115 mail_reader_preview_pane_visible_changed_cb (EMailReader *reader,
3116 GParamSpec *param,
3117 GtkWidget *widget)
3119 g_return_if_fail (E_IS_MAIL_READER (reader));
3120 g_return_if_fail (GTK_IS_WIDGET (widget));
3122 if (!gtk_widget_get_visible (widget))
3123 discard_timeout_mark_seen_cb (reader);
3126 static void
3127 mail_reader_remove_followup_alert (EMailReader *reader)
3129 EMailReaderPrivate *priv;
3131 g_return_if_fail (E_IS_MAIL_READER (reader));
3133 priv = E_MAIL_READER_GET_PRIVATE (reader);
3134 if (!priv)
3135 return;
3137 if (priv->followup_alert)
3138 e_alert_response (priv->followup_alert, GTK_RESPONSE_OK);
3141 static void
3142 mail_reader_manage_followup_flag (EMailReader *reader,
3143 CamelFolder *folder,
3144 const gchar *message_uid)
3146 EMailReaderPrivate *priv;
3147 CamelMessageInfo *info;
3148 const gchar *followup, *completed_on, *due_by;
3149 time_t date;
3150 gchar *date_str = NULL;
3151 gboolean alert_added = FALSE;
3153 g_return_if_fail (E_IS_MAIL_READER (reader));
3154 g_return_if_fail (CAMEL_IS_FOLDER (folder));
3155 g_return_if_fail (message_uid != NULL);
3157 priv = E_MAIL_READER_GET_PRIVATE (reader);
3158 if (!priv)
3159 return;
3161 info = camel_folder_get_message_info (folder, message_uid);
3162 if (!info)
3163 return;
3165 followup = camel_message_info_get_user_tag (info, "follow-up");
3166 if (followup && *followup) {
3167 EPreviewPane *preview_pane;
3168 const gchar *alert_tag;
3169 EAlert *alert;
3171 completed_on = camel_message_info_get_user_tag (info, "completed-on");
3172 due_by = camel_message_info_get_user_tag (info, "due-by");
3174 if (completed_on && *completed_on) {
3175 alert_tag = "mail:follow-up-completed-info";
3176 date = camel_header_decode_date (completed_on, NULL);
3177 date_str = e_datetime_format_format ("mail", "header", DTFormatKindDateTime, date);
3178 } else if (due_by && *due_by) {
3179 time_t now;
3181 alert_tag = "mail:follow-up-dueby-info";
3182 date = camel_header_decode_date (due_by, NULL);
3183 date_str = e_datetime_format_format ("mail", "header", DTFormatKindDateTime, date);
3185 now = time (NULL);
3186 if (now > date)
3187 alert_tag = "mail:follow-up-overdue-error";
3188 } else {
3189 alert_tag = "mail:follow-up-flag-info";
3192 alert = e_alert_new (alert_tag, followup, date_str ? date_str : "???", NULL);
3194 g_free (date_str);
3196 preview_pane = e_mail_reader_get_preview_pane (reader);
3197 e_alert_sink_submit_alert (E_ALERT_SINK (preview_pane), alert);
3199 alert_added = TRUE;
3201 mail_reader_remove_followup_alert (reader);
3202 priv->followup_alert = alert;
3203 g_object_add_weak_pointer (G_OBJECT (priv->followup_alert), &priv->followup_alert);
3205 g_object_unref (alert);
3208 g_clear_object (&info);
3210 if (!alert_added)
3211 mail_reader_remove_followup_alert (reader);
3214 static void
3215 mail_reader_message_loaded_cb (CamelFolder *folder,
3216 GAsyncResult *result,
3217 EMailReaderClosure *closure)
3219 EMailReader *reader;
3220 EMailReaderPrivate *priv;
3221 CamelMimeMessage *message = NULL;
3222 GtkWidget *message_list;
3223 const gchar *message_uid;
3224 GError *error = NULL;
3226 reader = closure->reader;
3227 message_uid = closure->message_uid;
3229 priv = E_MAIL_READER_GET_PRIVATE (reader);
3231 /* If the private struct is NULL, the EMailReader was destroyed
3232 * while we were loading the message and we're likely holding the
3233 * last reference. Nothing to do but drop the reference.
3234 * FIXME Use a GWeakRef instead of this hack. */
3235 if (priv == NULL) {
3236 mail_reader_closure_free (closure);
3237 return;
3240 message = camel_folder_get_message_finish (folder, result, &error);
3242 /* If the user picked a different message in the time it took
3243 * to fetch this message, then don't bother rendering it. */
3244 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
3245 g_clear_error (&error);
3246 goto exit;
3249 message_list = e_mail_reader_get_message_list (reader);
3251 if (message_list == NULL) {
3252 /* For cases where message fetching took so long that
3253 * user closed the message window before this was called. */
3254 goto exit;
3257 if (message != NULL) {
3258 mail_reader_manage_followup_flag (reader, folder, message_uid);
3260 g_signal_emit (
3261 reader, signals[MESSAGE_LOADED], 0,
3262 message_uid, message);
3265 exit:
3266 if (error != NULL) {
3267 EPreviewPane *preview_pane;
3268 EWebView *web_view;
3270 preview_pane = e_mail_reader_get_preview_pane (reader);
3271 web_view = e_preview_pane_get_web_view (preview_pane);
3273 if (g_error_matches (error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_UNAVAILABLE) &&
3274 CAMEL_IS_OFFLINE_FOLDER (folder) &&
3275 camel_service_get_connection_status (CAMEL_SERVICE (camel_folder_get_parent_store (folder))) != CAMEL_SERVICE_CONNECTED)
3276 e_alert_submit (
3277 E_ALERT_SINK (web_view),
3278 "mail:no-retrieve-message-offline",
3279 NULL);
3280 else
3281 e_alert_submit (
3282 E_ALERT_SINK (web_view),
3283 "mail:no-retrieve-message",
3284 error->message, NULL);
3287 g_clear_error (&error);
3289 mail_reader_closure_free (closure);
3291 g_clear_object (&message);
3294 static gboolean
3295 mail_reader_message_selected_timeout_cb (gpointer user_data)
3297 EMailReader *reader;
3298 EMailReaderPrivate *priv;
3299 EMailDisplay *display;
3300 GtkWidget *message_list;
3301 const gchar *cursor_uid;
3302 const gchar *format_uid;
3303 EMailPartList *parts;
3305 reader = E_MAIL_READER (user_data);
3306 priv = E_MAIL_READER_GET_PRIVATE (reader);
3308 message_list = e_mail_reader_get_message_list (reader);
3309 display = e_mail_reader_get_mail_display (reader);
3310 parts = e_mail_display_get_part_list (display);
3312 cursor_uid = MESSAGE_LIST (message_list)->cursor_uid;
3313 if (parts != NULL)
3314 format_uid = e_mail_part_list_get_message_uid (parts);
3315 else
3316 format_uid = NULL;
3318 if (MESSAGE_LIST (message_list)->last_sel_single) {
3319 GtkWidget *widget;
3320 gboolean display_visible;
3321 gboolean selected_uid_changed;
3323 /* Decide whether to download the full message now. */
3324 widget = GTK_WIDGET (display);
3325 display_visible = gtk_widget_get_mapped (widget);
3327 selected_uid_changed = (g_strcmp0 (cursor_uid, format_uid) != 0);
3329 if (display_visible && selected_uid_changed) {
3330 EMailReaderClosure *closure;
3331 GCancellable *cancellable;
3332 CamelFolder *folder;
3333 EActivity *activity;
3334 gchar *string;
3336 string = g_strdup_printf (
3337 _("Retrieving message “%s”"), cursor_uid);
3338 e_mail_display_set_part_list (display, NULL);
3339 e_mail_display_set_status (display, string);
3340 g_free (string);
3342 activity = e_mail_reader_new_activity (reader);
3343 e_activity_set_text (activity, _("Retrieving message"));
3344 cancellable = e_activity_get_cancellable (activity);
3346 closure = g_slice_new0 (EMailReaderClosure);
3347 closure->activity = activity;
3348 closure->reader = g_object_ref (reader);
3349 closure->message_uid = g_strdup (cursor_uid);
3351 folder = e_mail_reader_ref_folder (reader);
3353 camel_folder_get_message (
3354 folder, cursor_uid, G_PRIORITY_DEFAULT,
3355 cancellable, (GAsyncReadyCallback)
3356 mail_reader_message_loaded_cb, closure);
3358 g_clear_object (&folder);
3360 if (priv->retrieving_message != NULL)
3361 g_object_unref (priv->retrieving_message);
3362 priv->retrieving_message = g_object_ref (cancellable);
3364 } else {
3365 e_mail_display_set_part_list (display, NULL);
3368 priv->message_selected_timeout_id = 0;
3370 return FALSE;
3373 static void
3374 mail_reader_message_selected_cb (EMailReader *reader,
3375 const gchar *message_uid)
3377 EMailReaderPrivate *priv;
3378 MessageList *message_list;
3380 priv = E_MAIL_READER_GET_PRIVATE (reader);
3382 /* Cancel the previous message retrieval activity. */
3383 g_cancellable_cancel (priv->retrieving_message);
3385 /* Cancel the message selected timer. */
3386 if (priv->message_selected_timeout_id > 0) {
3387 g_source_remove (priv->message_selected_timeout_id);
3388 priv->message_selected_timeout_id = 0;
3391 if (priv->folder_was_just_selected && message_uid) {
3392 if (priv->did_try_to_open_message)
3393 priv->folder_was_just_selected = FALSE;
3394 else
3395 priv->did_try_to_open_message = TRUE;
3398 message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
3399 if (message_list) {
3400 EMailPartList *parts;
3401 const gchar *cursor_uid, *format_uid;
3403 parts = e_mail_display_get_part_list (e_mail_reader_get_mail_display (reader));
3405 cursor_uid = MESSAGE_LIST (message_list)->cursor_uid;
3406 if (parts != NULL)
3407 format_uid = e_mail_part_list_get_message_uid (parts);
3408 else
3409 format_uid = NULL;
3411 /* It can happen when the message was loaded that quickly that
3412 it was delivered before this callback. */
3413 if (g_strcmp0 (cursor_uid, format_uid) == 0) {
3414 e_mail_reader_changed (reader);
3415 return;
3419 /* Cancel the seen timer. */
3420 if (message_list != NULL && message_list->seen_id) {
3421 g_source_remove (message_list->seen_id);
3422 message_list->seen_id = 0;
3425 if (message_list_selected_count (message_list) != 1) {
3426 EMailDisplay *display;
3428 display = e_mail_reader_get_mail_display (reader);
3429 e_mail_display_set_part_list (display, NULL);
3430 e_web_view_clear (E_WEB_VIEW (display));
3432 } else if (priv->folder_was_just_selected) {
3433 /* Skip the timeout if we're restoring the previous message
3434 * selection. The timeout is there for when we're scrolling
3435 * rapidly through the message list. */
3436 mail_reader_message_selected_timeout_cb (reader);
3438 } else {
3439 priv->message_selected_timeout_id = e_named_timeout_add (
3440 100, mail_reader_message_selected_timeout_cb, reader);
3443 e_mail_reader_changed (reader);
3446 static void
3447 mail_reader_message_cursor_change_cb (EMailReader *reader)
3449 MessageList *message_list;
3450 EMailReaderPrivate *priv;
3452 g_return_if_fail (reader != NULL);
3454 priv = E_MAIL_READER_GET_PRIVATE (reader);
3455 g_return_if_fail (priv != NULL);
3457 message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
3458 g_return_if_fail (message_list != NULL);
3460 if (message_list->seen_id == 0 &&
3461 E_IS_MAIL_VIEW (reader) &&
3462 e_mail_view_get_preview_visible (E_MAIL_VIEW (reader)) &&
3463 !priv->avoid_next_mark_as_seen)
3464 maybe_schedule_timeout_mark_seen (reader);
3467 static void
3468 mail_reader_emit_folder_loaded (EMailReader *reader)
3470 EMailReaderPrivate *priv;
3471 MessageList *message_list;
3473 priv = E_MAIL_READER_GET_PRIVATE (reader);
3474 message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
3476 if (priv && (message_list_count (message_list) <= 0 ||
3477 message_list_selected_count (message_list) <= 0))
3478 priv->avoid_next_mark_as_seen = FALSE;
3480 g_signal_emit (reader, signals[FOLDER_LOADED], 0);
3483 static void
3484 mail_reader_message_list_built_cb (MessageList *message_list,
3485 EMailReader *reader)
3487 EMailReaderPrivate *priv;
3489 priv = E_MAIL_READER_GET_PRIVATE (reader);
3490 mail_reader_emit_folder_loaded (reader);
3492 /* No cursor_uid means that there will not be emitted any
3493 "cursor-changed" and "message-selected" signal, thus
3494 unset the "just selected folder" flag */
3495 if (!message_list->cursor_uid)
3496 priv->folder_was_just_selected = FALSE;
3499 static EAlertSink *
3500 mail_reader_get_alert_sink (EMailReader *reader)
3502 EPreviewPane *preview_pane;
3504 preview_pane = e_mail_reader_get_preview_pane (reader);
3506 if (!gtk_widget_is_visible (GTK_WIDGET (preview_pane))) {
3507 GtkWindow *window;
3509 window = e_mail_reader_get_window (reader);
3511 if (E_IS_SHELL_WINDOW (window))
3512 return E_ALERT_SINK (window);
3515 return E_ALERT_SINK (preview_pane);
3518 static GPtrArray *
3519 mail_reader_get_selected_uids (EMailReader *reader)
3521 GtkWidget *message_list;
3523 message_list = e_mail_reader_get_message_list (reader);
3525 return message_list_get_selected (MESSAGE_LIST (message_list));
3528 static GPtrArray *
3529 mail_reader_get_selected_uids_with_collapsed_threads (EMailReader *reader)
3531 GtkWidget *message_list;
3533 message_list = e_mail_reader_get_message_list (reader);
3535 return message_list_get_selected_with_collapsed_threads (MESSAGE_LIST (message_list));
3538 static CamelFolder *
3539 mail_reader_ref_folder (EMailReader *reader)
3541 GtkWidget *message_list;
3543 message_list = e_mail_reader_get_message_list (reader);
3545 return message_list_ref_folder (MESSAGE_LIST (message_list));
3548 static void
3549 mail_reader_set_folder (EMailReader *reader,
3550 CamelFolder *folder)
3552 EMailReaderPrivate *priv;
3553 EMailDisplay *display;
3554 CamelFolder *previous_folder;
3555 GtkWidget *message_list;
3556 EMailBackend *backend;
3557 EShell *shell;
3558 gboolean sync_folder;
3560 priv = E_MAIL_READER_GET_PRIVATE (reader);
3562 display = e_mail_reader_get_mail_display (reader);
3563 message_list = e_mail_reader_get_message_list (reader);
3565 previous_folder = e_mail_reader_ref_folder (reader);
3567 backend = e_mail_reader_get_backend (reader);
3568 shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
3570 /* Only synchronize the real folder if we're online. */
3571 sync_folder =
3572 (previous_folder != NULL) &&
3573 (CAMEL_IS_VEE_FOLDER (previous_folder) ||
3574 e_shell_get_online (shell));
3575 if (sync_folder)
3576 mail_sync_folder (previous_folder, TRUE, NULL, NULL);
3578 /* Skip the rest if we're already viewing the folder. */
3579 if (folder != previous_folder) {
3580 e_web_view_clear (E_WEB_VIEW (display));
3582 priv->folder_was_just_selected = (folder != NULL) && !priv->mark_seen_always;
3583 priv->did_try_to_open_message = FALSE;
3585 /* This is to make sure any post-poned changes in Search
3586 * Folders will be propagated on folder selection. */
3587 if (CAMEL_IS_VEE_FOLDER (folder))
3588 mail_sync_folder (folder, FALSE, NULL, NULL);
3590 message_list_set_folder (MESSAGE_LIST (message_list), folder);
3592 mail_reader_emit_folder_loaded (reader);
3595 g_clear_object (&previous_folder);
3598 static void
3599 mail_reader_set_message (EMailReader *reader,
3600 const gchar *message_uid)
3602 GtkWidget *message_list;
3603 EMailReaderPrivate *priv;
3605 priv = E_MAIL_READER_GET_PRIVATE (reader);
3607 /* For a case when the preview panel had been disabled */
3608 priv->folder_was_just_selected = FALSE;
3610 message_list = e_mail_reader_get_message_list (reader);
3612 message_list_select_uid (
3613 MESSAGE_LIST (message_list), message_uid, FALSE);
3616 static void
3617 mail_reader_folder_loaded (EMailReader *reader)
3619 guint32 state;
3621 state = e_mail_reader_check_state (reader);
3622 e_mail_reader_update_actions (reader, state);
3625 static void
3626 set_mail_display_part_list (GObject *object,
3627 GAsyncResult *result,
3628 gpointer user_data)
3630 EMailPartList *part_list;
3631 EMailReader *reader;
3632 EMailDisplay *display;
3633 GError *local_error = NULL;
3635 reader = E_MAIL_READER (object);
3636 display = e_mail_reader_get_mail_display (reader);
3638 part_list = e_mail_reader_parse_message_finish (reader, result, &local_error);
3640 if (local_error) {
3641 g_warn_if_fail (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED));
3643 g_clear_error (&local_error);
3644 return;
3647 e_mail_display_set_part_list (display, part_list);
3648 e_mail_display_load (display, NULL);
3650 /* Remove the reference added when parts list was
3651 * created, so that only owners are EMailDisplays. */
3652 g_object_unref (part_list);
3655 static void
3656 mail_reader_set_display_formatter_for_message (EMailReader *reader,
3657 EMailDisplay *display,
3658 const gchar *message_uid,
3659 CamelMimeMessage *message,
3660 CamelFolder *folder)
3662 CamelObjectBag *registry;
3663 EMailPartList *parts;
3664 EMailReaderPrivate *priv;
3665 gchar *mail_uri;
3667 priv = E_MAIL_READER_GET_PRIVATE (reader);
3668 mail_uri = e_mail_part_build_uri (folder, message_uid, NULL, NULL);
3669 registry = e_mail_part_list_get_registry ();
3670 parts = camel_object_bag_peek (registry, mail_uri);
3671 g_free (mail_uri);
3673 if (parts == NULL) {
3674 e_mail_reader_parse_message (
3675 reader, folder, message_uid, message,
3676 priv->retrieving_message,
3677 set_mail_display_part_list, NULL);
3678 } else {
3679 e_mail_display_set_part_list (display, parts);
3680 e_mail_display_load (display, NULL);
3681 g_object_unref (parts);
3685 static void
3686 mail_reader_message_loaded (EMailReader *reader,
3687 const gchar *message_uid,
3688 CamelMimeMessage *message)
3690 EMailReaderPrivate *priv;
3691 GtkWidget *message_list;
3692 EMailBackend *backend;
3693 CamelFolder *folder;
3694 EMailDisplay *display;
3695 EShellBackend *shell_backend;
3696 EShell *shell;
3697 EMEvent *event;
3698 EMEventTargetMessage *target;
3699 GError *error = NULL;
3701 priv = E_MAIL_READER_GET_PRIVATE (reader);
3703 folder = e_mail_reader_ref_folder (reader);
3704 backend = e_mail_reader_get_backend (reader);
3705 display = e_mail_reader_get_mail_display (reader);
3706 message_list = e_mail_reader_get_message_list (reader);
3708 shell_backend = E_SHELL_BACKEND (backend);
3709 shell = e_shell_backend_get_shell (shell_backend);
3711 /** @Event: message.reading
3712 * @Title: Viewing a message
3713 * @Target: EMEventTargetMessage
3715 * message.reading is emitted whenever a user views a message.
3717 event = em_event_peek ();
3718 target = em_event_target_new_message (
3719 event, folder, message, message_uid, 0, NULL);
3720 e_event_emit (
3721 (EEvent *) event, "message.reading",
3722 (EEventTarget *) target);
3724 mail_reader_set_display_formatter_for_message (
3725 reader, display, message_uid, message, folder);
3727 /* Reset the shell view icon. */
3728 e_shell_event (shell, "mail-icon", (gpointer) "evolution-mail");
3730 if (MESSAGE_LIST (message_list)->seen_id > 0) {
3731 g_source_remove (MESSAGE_LIST (message_list)->seen_id);
3732 MESSAGE_LIST (message_list)->seen_id = 0;
3735 /* Determine whether to mark the message as read. */
3736 if (message != NULL &&
3737 !priv->avoid_next_mark_as_seen &&
3738 maybe_schedule_timeout_mark_seen (reader)) {
3739 g_clear_error (&error);
3740 } else if (error != NULL) {
3741 e_alert_submit (
3742 E_ALERT_SINK (display),
3743 "mail:no-retrieve-message",
3744 error->message, NULL);
3745 g_error_free (error);
3748 priv->avoid_next_mark_as_seen = FALSE;
3750 g_clear_object (&folder);
3753 static void
3754 mail_reader_message_seen (EMailReader *reader,
3755 const gchar *message_uid,
3756 CamelMimeMessage *message)
3758 CamelFolder *folder;
3759 guint32 mask, set;
3761 mask = CAMEL_MESSAGE_SEEN;
3762 set = CAMEL_MESSAGE_SEEN;
3764 folder = e_mail_reader_ref_folder (reader);
3765 camel_folder_set_message_flags (folder, message_uid, mask, set);
3766 g_clear_object (&folder);
3769 static void
3770 mail_reader_show_search_bar (EMailReader *reader)
3772 EPreviewPane *preview_pane;
3774 preview_pane = e_mail_reader_get_preview_pane (reader);
3775 e_preview_pane_show_search_bar (preview_pane);
3778 static void
3779 mail_reader_update_actions (EMailReader *reader,
3780 guint32 state)
3782 GtkAction *action;
3783 const gchar *action_name;
3784 gboolean sensitive;
3786 /* Be descriptive. */
3787 gboolean any_messages_selected;
3788 gboolean enable_flag_clear;
3789 gboolean enable_flag_completed;
3790 gboolean enable_flag_for_followup;
3791 gboolean have_enabled_account;
3792 gboolean multiple_messages_selected;
3793 gboolean selection_has_attachment_messages;
3794 gboolean selection_has_deleted_messages;
3795 gboolean selection_has_ignore_thread_messages;
3796 gboolean selection_has_notignore_thread_messages;
3797 gboolean selection_has_important_messages;
3798 gboolean selection_has_junk_messages;
3799 gboolean selection_has_not_junk_messages;
3800 gboolean selection_has_read_messages;
3801 gboolean selection_has_undeleted_messages;
3802 gboolean selection_has_unimportant_messages;
3803 gboolean selection_has_unread_messages;
3804 gboolean selection_has_mail_note;
3805 gboolean selection_is_mailing_list;
3806 gboolean single_message_selected;
3807 gboolean first_message_selected = FALSE;
3808 gboolean last_message_selected = FALSE;
3810 have_enabled_account =
3811 (state & E_MAIL_READER_HAVE_ENABLED_ACCOUNT);
3812 single_message_selected =
3813 (state & E_MAIL_READER_SELECTION_SINGLE);
3814 multiple_messages_selected =
3815 (state & E_MAIL_READER_SELECTION_MULTIPLE);
3816 /* FIXME Missing CAN_ADD_SENDER */
3817 enable_flag_clear =
3818 (state & E_MAIL_READER_SELECTION_FLAG_CLEAR);
3819 enable_flag_completed =
3820 (state & E_MAIL_READER_SELECTION_FLAG_COMPLETED);
3821 enable_flag_for_followup =
3822 (state & E_MAIL_READER_SELECTION_FLAG_FOLLOWUP);
3823 selection_has_attachment_messages =
3824 (state & E_MAIL_READER_SELECTION_HAS_ATTACHMENTS);
3825 selection_has_deleted_messages =
3826 (state & E_MAIL_READER_SELECTION_HAS_DELETED);
3827 selection_has_ignore_thread_messages =
3828 (state & E_MAIL_READER_SELECTION_HAS_IGNORE_THREAD);
3829 selection_has_notignore_thread_messages =
3830 (state & E_MAIL_READER_SELECTION_HAS_NOTIGNORE_THREAD);
3831 selection_has_important_messages =
3832 (state & E_MAIL_READER_SELECTION_HAS_IMPORTANT);
3833 selection_has_junk_messages =
3834 (state & E_MAIL_READER_SELECTION_HAS_JUNK);
3835 selection_has_not_junk_messages =
3836 (state & E_MAIL_READER_SELECTION_HAS_NOT_JUNK);
3837 selection_has_read_messages =
3838 (state & E_MAIL_READER_SELECTION_HAS_READ);
3839 selection_has_undeleted_messages =
3840 (state & E_MAIL_READER_SELECTION_HAS_UNDELETED);
3841 selection_has_unimportant_messages =
3842 (state & E_MAIL_READER_SELECTION_HAS_UNIMPORTANT);
3843 selection_has_unread_messages =
3844 (state & E_MAIL_READER_SELECTION_HAS_UNREAD);
3845 selection_has_mail_note =
3846 (state & E_MAIL_READER_SELECTION_HAS_MAIL_NOTE);
3847 selection_is_mailing_list =
3848 (state & E_MAIL_READER_SELECTION_IS_MAILING_LIST);
3850 any_messages_selected =
3851 (single_message_selected || multiple_messages_selected);
3853 if (any_messages_selected) {
3854 MessageList *message_list;
3855 gint row = -1, count = -1;
3856 ETreeTableAdapter *etta;
3857 ETreePath node = NULL;
3859 message_list = MESSAGE_LIST (
3860 e_mail_reader_get_message_list (reader));
3861 etta = e_tree_get_table_adapter (E_TREE (message_list));
3863 if (message_list->cursor_uid != NULL)
3864 node = g_hash_table_lookup (
3865 message_list->uid_nodemap,
3866 message_list->cursor_uid);
3868 if (node != NULL) {
3869 row = e_tree_table_adapter_row_of_node (etta, node);
3870 count = e_table_model_row_count (E_TABLE_MODEL (etta));
3873 first_message_selected = row <= 0;
3874 last_message_selected = row < 0 || row + 1 >= count;
3877 action_name = "mail-add-sender";
3878 sensitive = single_message_selected;
3879 action = e_mail_reader_get_action (reader, action_name);
3880 gtk_action_set_sensitive (action, sensitive);
3882 action_name = "mail-archive";
3883 sensitive = any_messages_selected && (state & E_MAIL_READER_FOLDER_ARCHIVE_FOLDER_SET) != 0;
3884 action = e_mail_reader_get_action (reader, action_name);
3885 gtk_action_set_sensitive (action, sensitive);
3887 action_name = "mail-check-for-junk";
3888 sensitive = any_messages_selected;
3889 action = e_mail_reader_get_action (reader, action_name);
3890 gtk_action_set_sensitive (action, sensitive);
3892 action_name = "mail-copy";
3893 sensitive = any_messages_selected;
3894 action = e_mail_reader_get_action (reader, action_name);
3895 gtk_action_set_sensitive (action, sensitive);
3897 action_name = "mail-create-menu";
3898 sensitive = single_message_selected;
3899 action = e_mail_reader_get_action (reader, action_name);
3900 gtk_action_set_sensitive (action, sensitive);
3902 /* If a single message is selected, let the user hit delete to
3903 * advance the cursor even if the message is already deleted. */
3904 action_name = "mail-delete";
3905 sensitive =
3906 (single_message_selected ||
3907 selection_has_undeleted_messages) &&
3908 (state & E_MAIL_READER_FOLDER_IS_VTRASH) == 0;
3909 action = e_mail_reader_get_action (reader, action_name);
3910 gtk_action_set_sensitive (action, sensitive);
3912 action_name = "mail-add-note";
3913 sensitive = single_message_selected && !selection_has_mail_note;
3914 action = e_mail_reader_get_action (reader, action_name);
3915 gtk_action_set_sensitive (action, sensitive);
3916 gtk_action_set_visible (action, sensitive);
3918 action_name = "mail-edit-note";
3919 sensitive = single_message_selected && selection_has_mail_note;
3920 action = e_mail_reader_get_action (reader, action_name);
3921 gtk_action_set_sensitive (action, sensitive);
3922 gtk_action_set_visible (action, sensitive);
3924 action_name = "mail-delete-note";
3925 sensitive = single_message_selected && selection_has_mail_note;
3926 action = e_mail_reader_get_action (reader, action_name);
3927 gtk_action_set_sensitive (action, sensitive);
3928 gtk_action_set_visible (action, sensitive);
3930 action_name = "mail-filters-apply";
3931 sensitive = any_messages_selected;
3932 action = e_mail_reader_get_action (reader, action_name);
3933 gtk_action_set_sensitive (action, sensitive);
3935 action_name = "mail-filter-rule-for-mailing-list";
3936 sensitive = single_message_selected && selection_is_mailing_list;
3937 action = e_mail_reader_get_action (reader, action_name);
3938 gtk_action_set_sensitive (action, sensitive);
3940 action_name = "mail-find";
3941 sensitive = single_message_selected;
3942 action = e_mail_reader_get_action (reader, action_name);
3943 gtk_action_set_sensitive (action, sensitive);
3945 action_name = "mail-flag-clear";
3946 sensitive = enable_flag_clear;
3947 action = e_mail_reader_get_action (reader, action_name);
3948 gtk_action_set_sensitive (action, sensitive);
3950 action_name = "mail-flag-completed";
3951 sensitive = enable_flag_completed;
3952 action = e_mail_reader_get_action (reader, action_name);
3953 gtk_action_set_sensitive (action, sensitive);
3955 action_name = "mail-flag-for-followup";
3956 sensitive = enable_flag_for_followup;
3957 action = e_mail_reader_get_action (reader, action_name);
3958 gtk_action_set_sensitive (action, sensitive);
3960 action_name = "mail-forward";
3961 sensitive = have_enabled_account && any_messages_selected;
3962 action = e_mail_reader_get_action (reader, action_name);
3963 gtk_action_set_sensitive (action, sensitive);
3965 action_name = "mail-forward-attached";
3966 sensitive = have_enabled_account && any_messages_selected;
3967 action = e_mail_reader_get_action (reader, action_name);
3968 gtk_action_set_sensitive (action, sensitive);
3970 action_name = "mail-forward-attached-full";
3971 sensitive = have_enabled_account && any_messages_selected;
3972 action = e_mail_reader_get_action (reader, action_name);
3973 gtk_action_set_sensitive (action, sensitive);
3975 action_name = "mail-forward-as-menu";
3976 sensitive = have_enabled_account && any_messages_selected;
3977 action = e_mail_reader_get_action (reader, action_name);
3978 gtk_action_set_sensitive (action, sensitive);
3980 action_name = "mail-forward-inline";
3981 sensitive = have_enabled_account && single_message_selected;
3982 action = e_mail_reader_get_action (reader, action_name);
3983 gtk_action_set_sensitive (action, sensitive);
3985 action_name = "mail-forward-inline-full";
3986 sensitive = have_enabled_account && single_message_selected;
3987 action = e_mail_reader_get_action (reader, action_name);
3988 gtk_action_set_sensitive (action, sensitive);
3990 action_name = "mail-forward-quoted";
3991 sensitive = have_enabled_account && single_message_selected;
3992 action = e_mail_reader_get_action (reader, action_name);
3993 gtk_action_set_sensitive (action, sensitive);
3995 action_name = "mail-forward-quoted-full";
3996 sensitive = have_enabled_account && single_message_selected;
3997 action = e_mail_reader_get_action (reader, action_name);
3998 gtk_action_set_sensitive (action, sensitive);
4000 action_name = "mail-goto-menu";
4001 sensitive = any_messages_selected;
4002 action = e_mail_reader_get_action (reader, action_name);
4003 gtk_action_set_sensitive (action, sensitive);
4005 action_name = "mail-load-images";
4006 sensitive = single_message_selected;
4007 action = e_mail_reader_get_action (reader, action_name);
4008 gtk_action_set_sensitive (action, sensitive);
4010 action_name = "mail-mark-as-menu";
4011 sensitive = any_messages_selected;
4012 action = e_mail_reader_get_action (reader, action_name);
4013 gtk_action_set_sensitive (action, sensitive);
4015 action_name = "mail-mark-ignore-thread-sub";
4016 sensitive = selection_has_notignore_thread_messages;
4017 action = e_mail_reader_get_action (reader, action_name);
4018 gtk_action_set_sensitive (action, sensitive);
4019 gtk_action_set_visible (action, sensitive);
4021 action_name = "mail-mark-ignore-thread-whole";
4022 sensitive = selection_has_notignore_thread_messages;
4023 action = e_mail_reader_get_action (reader, action_name);
4024 gtk_action_set_sensitive (action, sensitive);
4025 gtk_action_set_visible (action, sensitive);
4027 action_name = "mail-mark-important";
4028 sensitive = selection_has_unimportant_messages;
4029 action = e_mail_reader_get_action (reader, action_name);
4030 gtk_action_set_sensitive (action, sensitive);
4032 action_name = "mail-mark-junk";
4033 sensitive = selection_has_not_junk_messages;
4034 action = e_mail_reader_get_action (reader, action_name);
4035 gtk_action_set_sensitive (action, sensitive);
4037 action_name = "mail-mark-notjunk";
4038 sensitive = selection_has_junk_messages;
4039 action = e_mail_reader_get_action (reader, action_name);
4040 gtk_action_set_sensitive (action, sensitive);
4042 action_name = "mail-mark-read";
4043 sensitive = selection_has_unread_messages;
4044 action = e_mail_reader_get_action (reader, action_name);
4045 gtk_action_set_sensitive (action, sensitive);
4047 action_name = "mail-mark-unignore-thread-sub";
4048 sensitive = selection_has_ignore_thread_messages;
4049 action = e_mail_reader_get_action (reader, action_name);
4050 gtk_action_set_sensitive (action, sensitive);
4051 gtk_action_set_visible (action, sensitive);
4053 action_name = "mail-mark-unignore-thread-whole";
4054 sensitive = selection_has_ignore_thread_messages;
4055 action = e_mail_reader_get_action (reader, action_name);
4056 gtk_action_set_sensitive (action, sensitive);
4057 gtk_action_set_visible (action, sensitive);
4059 action_name = "mail-mark-unimportant";
4060 sensitive = selection_has_important_messages;
4061 action = e_mail_reader_get_action (reader, action_name);
4062 gtk_action_set_sensitive (action, sensitive);
4064 action_name = "mail-mark-unread";
4065 sensitive = selection_has_read_messages;
4066 action = e_mail_reader_get_action (reader, action_name);
4067 gtk_action_set_sensitive (action, sensitive);
4069 action_name = "mail-message-edit";
4070 sensitive = have_enabled_account && single_message_selected;
4071 action = e_mail_reader_get_action (reader, action_name);
4072 gtk_action_set_sensitive (action, sensitive);
4074 action_name = "mail-message-new";
4075 sensitive = have_enabled_account;
4076 action = e_mail_reader_get_action (reader, action_name);
4077 gtk_action_set_sensitive (action, sensitive);
4079 action_name = "mail-message-open";
4080 sensitive = any_messages_selected;
4081 action = e_mail_reader_get_action (reader, action_name);
4082 gtk_action_set_sensitive (action, sensitive);
4084 action_name = "mail-move";
4085 sensitive = any_messages_selected;
4086 action = e_mail_reader_get_action (reader, action_name);
4087 gtk_action_set_sensitive (action, sensitive);
4089 action_name = "mail-next";
4090 sensitive = any_messages_selected && !last_message_selected;
4091 action = e_mail_reader_get_action (reader, action_name);
4092 gtk_action_set_sensitive (action, sensitive);
4094 action_name = "mail-next-important";
4095 sensitive = single_message_selected;
4096 action = e_mail_reader_get_action (reader, action_name);
4097 gtk_action_set_sensitive (action, sensitive);
4099 action_name = "mail-next-thread";
4100 sensitive = single_message_selected && !last_message_selected;
4101 action = e_mail_reader_get_action (reader, action_name);
4102 gtk_action_set_sensitive (action, sensitive);
4104 action_name = "mail-next-unread";
4105 sensitive = any_messages_selected;
4106 action = e_mail_reader_get_action (reader, action_name);
4107 gtk_action_set_sensitive (action, sensitive);
4109 action_name = "mail-previous";
4110 sensitive = any_messages_selected && !first_message_selected;
4111 action = e_mail_reader_get_action (reader, action_name);
4112 gtk_action_set_sensitive (action, sensitive);
4114 action_name = "mail-previous-important";
4115 sensitive = single_message_selected;
4116 action = e_mail_reader_get_action (reader, action_name);
4117 gtk_action_set_sensitive (action, sensitive);
4119 action_name = "mail-previous-unread";
4120 sensitive = any_messages_selected;
4121 action = e_mail_reader_get_action (reader, action_name);
4122 gtk_action_set_sensitive (action, sensitive);
4124 action_name = "mail-previous-thread";
4125 sensitive = any_messages_selected && !first_message_selected;
4126 action = e_mail_reader_get_action (reader, action_name);
4127 gtk_action_set_sensitive (action, sensitive);
4129 action_name = "mail-print";
4130 sensitive = single_message_selected;
4131 action = e_mail_reader_get_action (reader, action_name);
4132 gtk_action_set_sensitive (action, sensitive);
4134 action_name = "mail-print-preview";
4135 sensitive = single_message_selected;
4136 action = e_mail_reader_get_action (reader, action_name);
4137 gtk_action_set_sensitive (action, sensitive);
4139 action_name = "mail-redirect";
4140 sensitive = have_enabled_account && single_message_selected;
4141 action = e_mail_reader_get_action (reader, action_name);
4142 gtk_action_set_sensitive (action, sensitive);
4144 action_name = "mail-remove-attachments";
4145 sensitive = any_messages_selected && selection_has_attachment_messages;
4146 action = e_mail_reader_get_action (reader, action_name);
4147 gtk_action_set_sensitive (action, sensitive);
4149 action_name = "mail-remove-duplicates";
4150 sensitive = multiple_messages_selected;
4151 action = e_mail_reader_get_action (reader, action_name);
4152 gtk_action_set_sensitive (action, sensitive);
4154 action_name = "mail-reply-all";
4155 sensitive = have_enabled_account && single_message_selected;
4156 action = e_mail_reader_get_action (reader, action_name);
4157 gtk_action_set_sensitive (action, sensitive);
4159 action_name = "mail-reply-alternative";
4160 sensitive = have_enabled_account && single_message_selected;
4161 action = e_mail_reader_get_action (reader, action_name);
4162 gtk_action_set_sensitive (action, sensitive);
4164 action_name = "mail-reply-group";
4165 sensitive = have_enabled_account && single_message_selected;
4166 action = e_mail_reader_get_action (reader, action_name);
4167 gtk_action_set_sensitive (action, sensitive);
4169 action_name = "mail-reply-group-menu";
4170 sensitive = have_enabled_account && any_messages_selected;
4171 action = e_mail_reader_get_action (reader, action_name);
4172 gtk_action_set_sensitive (action, sensitive);
4174 action_name = "mail-reply-list";
4175 sensitive = have_enabled_account && single_message_selected &&
4176 selection_is_mailing_list;
4177 action = e_mail_reader_get_action (reader, action_name);
4178 gtk_action_set_sensitive (action, sensitive);
4180 action_name = "mail-reply-sender";
4181 sensitive = have_enabled_account && single_message_selected;
4182 action = e_mail_reader_get_action (reader, action_name);
4183 gtk_action_set_sensitive (action, sensitive);
4185 action_name = "mail-save-as";
4186 sensitive = any_messages_selected;
4187 action = e_mail_reader_get_action (reader, action_name);
4188 gtk_action_set_sensitive (action, sensitive);
4190 action_name = "mail-show-source";
4191 sensitive = single_message_selected;
4192 action = e_mail_reader_get_action (reader, action_name);
4193 gtk_action_set_sensitive (action, sensitive);
4195 action_name = "mail-undelete";
4196 sensitive = selection_has_deleted_messages;
4197 action = e_mail_reader_get_action (reader, action_name);
4198 gtk_action_set_sensitive (action, sensitive);
4200 action_name = "mail-zoom-100";
4201 sensitive = single_message_selected;
4202 action = e_mail_reader_get_action (reader, action_name);
4203 gtk_action_set_sensitive (action, sensitive);
4205 action_name = "mail-zoom-in";
4206 sensitive = single_message_selected;
4207 action = e_mail_reader_get_action (reader, action_name);
4208 gtk_action_set_sensitive (action, sensitive);
4210 action_name = "mail-zoom-out";
4211 sensitive = single_message_selected;
4212 action = e_mail_reader_get_action (reader, action_name);
4213 gtk_action_set_sensitive (action, sensitive);
4216 static void
4217 mail_reader_init_charset_actions (EMailReader *reader,
4218 GtkActionGroup *action_group)
4220 GtkRadioAction *default_action;
4221 GSList *radio_group;
4223 radio_group = e_charset_add_radio_actions (
4224 action_group, "mail-charset-", NULL,
4225 G_CALLBACK (action_mail_charset_cb), reader);
4227 /* XXX Add a tooltip! */
4228 default_action = gtk_radio_action_new (
4229 "mail-charset-default", _("Default"), NULL, NULL, -1);
4231 gtk_radio_action_set_group (default_action, radio_group);
4233 g_signal_connect (
4234 default_action, "changed",
4235 G_CALLBACK (action_mail_charset_cb), reader);
4237 gtk_action_group_add_action (
4238 action_group, GTK_ACTION (default_action));
4240 gtk_radio_action_set_current_value (default_action, -1);
4243 static void
4244 e_mail_reader_default_init (EMailReaderInterface *iface)
4246 quark_private = g_quark_from_static_string ("e-mail-reader-private");
4248 iface->get_alert_sink = mail_reader_get_alert_sink;
4249 iface->get_selected_uids = mail_reader_get_selected_uids;
4250 iface->get_selected_uids_with_collapsed_threads = mail_reader_get_selected_uids_with_collapsed_threads;
4251 iface->ref_folder = mail_reader_ref_folder;
4252 iface->set_folder = mail_reader_set_folder;
4253 iface->set_message = mail_reader_set_message;
4254 iface->open_selected_mail = e_mail_reader_open_selected;
4255 iface->folder_loaded = mail_reader_folder_loaded;
4256 iface->message_loaded = mail_reader_message_loaded;
4257 iface->message_seen = mail_reader_message_seen;
4258 iface->show_search_bar = mail_reader_show_search_bar;
4259 iface->update_actions = mail_reader_update_actions;
4261 g_object_interface_install_property (
4262 iface,
4263 g_param_spec_enum (
4264 "forward-style",
4265 "Forward Style",
4266 "How to forward messages",
4267 E_TYPE_MAIL_FORWARD_STYLE,
4268 E_MAIL_FORWARD_STYLE_ATTACHED,
4269 G_PARAM_READWRITE));
4271 g_object_interface_install_property (
4272 iface,
4273 g_param_spec_boolean (
4274 "group-by-threads",
4275 "Group by Threads",
4276 "Whether to group messages by threads",
4277 FALSE,
4278 G_PARAM_READWRITE));
4280 g_object_interface_install_property (
4281 iface,
4282 g_param_spec_enum (
4283 "reply-style",
4284 "Reply Style",
4285 "How to reply to messages",
4286 E_TYPE_MAIL_REPLY_STYLE,
4287 E_MAIL_REPLY_STYLE_QUOTED,
4288 G_PARAM_READWRITE));
4290 g_object_interface_install_property (
4291 iface,
4292 g_param_spec_boolean (
4293 "mark-seen-always",
4294 "Mark Seen Always",
4295 "Whether to mark unread message seen even after folder change",
4296 FALSE,
4297 G_PARAM_READWRITE));
4299 g_object_interface_install_property (
4300 iface,
4301 g_param_spec_boolean (
4302 "delete-selects-previous",
4303 "Delete Selects Previous",
4304 "Whether go to the previous message after message deletion",
4305 FALSE,
4306 G_PARAM_READWRITE));
4308 signals[CHANGED] = g_signal_new (
4309 "changed",
4310 G_OBJECT_CLASS_TYPE (iface),
4311 G_SIGNAL_RUN_FIRST,
4312 0, NULL, NULL,
4313 g_cclosure_marshal_VOID__VOID,
4314 G_TYPE_NONE, 0);
4316 signals[COMPOSER_CREATED] = g_signal_new (
4317 "composer-created",
4318 G_OBJECT_CLASS_TYPE (iface),
4319 G_SIGNAL_RUN_FIRST,
4320 G_STRUCT_OFFSET (EMailReaderInterface, composer_created),
4321 NULL, NULL, NULL,
4322 G_TYPE_NONE, 2,
4323 E_TYPE_MSG_COMPOSER,
4324 CAMEL_TYPE_MIME_MESSAGE);
4326 signals[FOLDER_LOADED] = g_signal_new (
4327 "folder-loaded",
4328 G_OBJECT_CLASS_TYPE (iface),
4329 G_SIGNAL_RUN_FIRST,
4330 G_STRUCT_OFFSET (EMailReaderInterface, folder_loaded),
4331 NULL, NULL,
4332 g_cclosure_marshal_VOID__VOID,
4333 G_TYPE_NONE, 0);
4335 signals[MESSAGE_LOADED] = g_signal_new (
4336 "message-loaded",
4337 G_OBJECT_CLASS_TYPE (iface),
4338 G_SIGNAL_RUN_LAST,
4339 G_STRUCT_OFFSET (EMailReaderInterface, message_loaded),
4340 NULL, NULL,
4341 e_marshal_VOID__STRING_OBJECT,
4342 G_TYPE_NONE, 2,
4343 G_TYPE_STRING,
4344 CAMEL_TYPE_MIME_MESSAGE);
4346 signals[MESSAGE_SEEN] = g_signal_new (
4347 "message-seen",
4348 G_OBJECT_CLASS_TYPE (iface),
4349 G_SIGNAL_RUN_LAST,
4350 G_STRUCT_OFFSET (EMailReaderInterface, message_seen),
4351 NULL, NULL,
4352 e_marshal_VOID__STRING_OBJECT,
4353 G_TYPE_NONE, 2,
4354 G_TYPE_STRING,
4355 CAMEL_TYPE_MIME_MESSAGE);
4357 signals[SHOW_SEARCH_BAR] = g_signal_new (
4358 "show-search-bar",
4359 G_OBJECT_CLASS_TYPE (iface),
4360 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
4361 G_STRUCT_OFFSET (EMailReaderInterface, show_search_bar),
4362 NULL, NULL,
4363 g_cclosure_marshal_VOID__VOID,
4364 G_TYPE_NONE, 0);
4366 signals[UPDATE_ACTIONS] = g_signal_new (
4367 "update-actions",
4368 G_OBJECT_CLASS_TYPE (iface),
4369 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
4370 G_STRUCT_OFFSET (EMailReaderInterface, update_actions),
4371 NULL, NULL,
4372 g_cclosure_marshal_VOID__UINT,
4373 G_TYPE_NONE, 1,
4374 G_TYPE_UINT);
4377 void
4378 e_mail_reader_init (EMailReader *reader,
4379 gboolean init_actions,
4380 gboolean connect_signals)
4382 EMenuToolAction *menu_tool_action;
4383 GtkActionGroup *action_group;
4384 GtkWidget *message_list;
4385 GtkAction *action;
4386 const gchar *action_name;
4387 EMailDisplay *display;
4388 GSettings *settings;
4390 g_return_if_fail (E_IS_MAIL_READER (reader));
4392 message_list = e_mail_reader_get_message_list (reader);
4393 display = e_mail_reader_get_mail_display (reader);
4395 /* Initialize a private struct. */
4396 g_object_set_qdata_full (
4397 G_OBJECT (reader), quark_private,
4398 g_slice_new0 (EMailReaderPrivate),
4399 (GDestroyNotify) mail_reader_private_free);
4401 e_binding_bind_property (
4402 reader, "group-by-threads",
4403 message_list, "group-by-threads",
4404 G_BINDING_SYNC_CREATE);
4406 if (!init_actions)
4407 goto connect_signals;
4409 /* Add the "standard" EMailReader actions. */
4411 action_group = e_mail_reader_get_action_group (
4412 reader, E_MAIL_READER_ACTION_GROUP_STANDARD);
4414 /* The "mail-forward" action is special: it uses a GtkMenuToolButton
4415 * for its toolbar item type. So we have to create it separately. */
4417 menu_tool_action = e_menu_tool_action_new (
4418 "mail-forward", _("_Forward"),
4419 _("Forward the selected message to someone"));
4421 gtk_action_set_icon_name (
4422 GTK_ACTION (menu_tool_action), "mail-forward");
4424 g_signal_connect (
4425 menu_tool_action, "activate",
4426 G_CALLBACK (action_mail_forward_cb), reader);
4428 gtk_action_group_add_action_with_accel (
4429 action_group, GTK_ACTION (menu_tool_action), "<Control>f");
4431 /* Likewise the "mail-reply-group" action. */
4433 menu_tool_action = e_menu_tool_action_new (
4434 /* For Translators: "Group Reply" will reply either to a mailing list
4435 * (if possible and if that configuration option is enabled), or else
4436 * it will reply to all. The word "Group" was chosen because it covers
4437 * either of those, without too strongly implying one or the other. */
4438 "mail-reply-group", _("Group Reply"),
4439 _("Reply to the mailing list, or to all recipients"));
4441 gtk_action_set_icon_name (
4442 GTK_ACTION (menu_tool_action), "mail-reply-all");
4444 g_signal_connect (
4445 menu_tool_action, "activate",
4446 G_CALLBACK (action_mail_reply_group_cb), reader);
4448 gtk_action_group_add_action_with_accel (
4449 action_group, GTK_ACTION (menu_tool_action), "<Control>g");
4451 /* Add the other actions the normal way. */
4452 gtk_action_group_add_actions (
4453 action_group, mail_reader_entries,
4454 G_N_ELEMENTS (mail_reader_entries), reader);
4455 e_action_group_add_popup_actions (
4456 action_group, mail_reader_popup_entries,
4457 G_N_ELEMENTS (mail_reader_popup_entries));
4458 gtk_action_group_add_toggle_actions (
4459 action_group, mail_reader_toggle_entries,
4460 G_N_ELEMENTS (mail_reader_toggle_entries), reader);
4462 mail_reader_init_charset_actions (reader, action_group);
4464 /* Add EMailReader actions for Search Folders. The action group
4465 * should be made invisible if Search Folders are disabled. */
4467 action_group = e_mail_reader_get_action_group (
4468 reader, E_MAIL_READER_ACTION_GROUP_SEARCH_FOLDERS);
4470 gtk_action_group_add_actions (
4471 action_group, mail_reader_search_folder_entries,
4472 G_N_ELEMENTS (mail_reader_search_folder_entries), reader);
4474 display = e_mail_reader_get_mail_display (reader);
4476 /* Bind GObject properties to GSettings keys. */
4478 settings = e_util_ref_settings ("org.gnome.evolution.mail");
4480 action_name = "mail-caret-mode";
4481 action = e_mail_reader_get_action (reader, action_name);
4482 g_settings_bind (
4483 settings, "caret-mode",
4484 action, "active", G_SETTINGS_BIND_DEFAULT);
4486 action_name = "mail-show-all-headers";
4487 action = e_mail_reader_get_action (reader, action_name);
4488 g_settings_bind (
4489 settings, "show-all-headers",
4490 action, "active", G_SETTINGS_BIND_DEFAULT);
4492 /* Mode change when viewing message source is ignored. */
4493 if (e_mail_display_get_mode (display) == E_MAIL_FORMATTER_MODE_SOURCE ||
4494 e_mail_display_get_mode (display) == E_MAIL_FORMATTER_MODE_RAW) {
4495 gtk_action_set_sensitive (action, FALSE);
4496 gtk_action_set_visible (action, FALSE);
4499 g_object_unref (settings);
4501 /* Fine tuning. */
4503 action_name = "mail-delete";
4504 action = e_mail_reader_get_action (reader, action_name);
4505 gtk_action_set_short_label (action, _("Delete"));
4507 action_name = "mail-forward";
4508 action = e_mail_reader_get_action (reader, action_name);
4509 gtk_action_set_is_important (action, TRUE);
4511 action_name = "mail-reply-group";
4512 action = e_mail_reader_get_action (reader, action_name);
4513 gtk_action_set_is_important (action, TRUE);
4515 action_name = "mail-next";
4516 action = e_mail_reader_get_action (reader, action_name);
4517 gtk_action_set_short_label (action, _("Next"));
4519 action_name = "mail-previous";
4520 action = e_mail_reader_get_action (reader, action_name);
4521 gtk_action_set_short_label (action, _("Previous"));
4523 action_name = "mail-reply-all";
4524 action = e_mail_reader_get_action (reader, action_name);
4525 gtk_action_set_is_important (action, TRUE);
4527 action_name = "mail-reply-sender";
4528 action = e_mail_reader_get_action (reader, action_name);
4529 gtk_action_set_is_important (action, TRUE);
4530 gtk_action_set_short_label (action, _("Reply"));
4532 action_name = "add-to-address-book";
4533 action = e_mail_display_get_action (display, action_name);
4534 g_signal_connect (
4535 action, "activate",
4536 G_CALLBACK (action_add_to_address_book_cb), reader);
4538 action_name = "send-reply";
4539 action = e_mail_display_get_action (display, action_name);
4540 g_signal_connect (
4541 action, "activate",
4542 G_CALLBACK (action_mail_reply_recipient_cb), reader);
4544 action_name = "search-folder-recipient";
4545 action = e_mail_display_get_action (display, action_name);
4546 g_signal_connect (
4547 action, "activate",
4548 G_CALLBACK (action_search_folder_recipient_cb), reader);
4550 action_name = "search-folder-sender";
4551 action = e_mail_display_get_action (display, action_name);
4552 g_signal_connect (
4553 action, "activate",
4554 G_CALLBACK (action_search_folder_sender_cb), reader);
4556 #ifndef G_OS_WIN32
4557 /* Lockdown integration. */
4559 settings = e_util_ref_settings ("org.gnome.desktop.lockdown");
4561 action_name = "mail-print";
4562 action = e_mail_reader_get_action (reader, action_name);
4563 g_settings_bind (
4564 settings, "disable-printing",
4565 action, "visible",
4566 G_SETTINGS_BIND_GET |
4567 G_SETTINGS_BIND_NO_SENSITIVITY |
4568 G_SETTINGS_BIND_INVERT_BOOLEAN);
4570 action_name = "mail-print-preview";
4571 action = e_mail_reader_get_action (reader, action_name);
4572 g_settings_bind (
4573 settings, "disable-printing",
4574 action, "visible",
4575 G_SETTINGS_BIND_GET |
4576 G_SETTINGS_BIND_NO_SENSITIVITY |
4577 G_SETTINGS_BIND_INVERT_BOOLEAN);
4579 action_name = "mail-save-as";
4580 action = e_mail_reader_get_action (reader, action_name);
4581 g_settings_bind (
4582 settings, "disable-save-to-disk",
4583 action, "visible",
4584 G_SETTINGS_BIND_GET |
4585 G_SETTINGS_BIND_NO_SENSITIVITY |
4586 G_SETTINGS_BIND_INVERT_BOOLEAN);
4588 g_object_unref (settings);
4589 #endif
4591 /* Bind properties. */
4593 action_name = "mail-caret-mode";
4594 action = e_mail_reader_get_action (reader, action_name);
4596 e_binding_bind_property (
4597 action, "active",
4598 display, "caret-mode",
4599 G_BINDING_BIDIRECTIONAL |
4600 G_BINDING_SYNC_CREATE);
4602 connect_signals:
4604 if (!connect_signals)
4605 return;
4607 /* Connect signals. */
4608 g_signal_connect_swapped (
4609 display, "key-press-event",
4610 G_CALLBACK (mail_reader_key_press_event_cb), reader);
4612 g_signal_connect_swapped (
4613 display, "load-changed",
4614 G_CALLBACK (mail_reader_load_changed_cb), reader);
4616 g_signal_connect_swapped (
4617 message_list, "message-selected",
4618 G_CALLBACK (mail_reader_message_selected_cb), reader);
4620 /* re-schedule mark-as-seen,... */
4621 g_signal_connect_swapped (
4622 message_list, "cursor-change",
4623 G_CALLBACK (mail_reader_message_cursor_change_cb), reader);
4625 /* but do not mark-as-seen if... */
4626 g_signal_connect_swapped (
4627 message_list, "tree-drag-begin",
4628 G_CALLBACK (discard_timeout_mark_seen_cb), reader);
4630 g_signal_connect_swapped (
4631 message_list, "tree-drag-end",
4632 G_CALLBACK (discard_timeout_mark_seen_cb), reader);
4634 g_signal_connect_swapped (
4635 message_list, "right-click",
4636 G_CALLBACK (discard_timeout_mark_seen_cb), reader);
4638 g_signal_connect_swapped (
4639 e_mail_reader_get_preview_pane (reader), "notify::visible",
4640 G_CALLBACK (mail_reader_preview_pane_visible_changed_cb), reader);
4642 g_signal_connect_after (
4643 message_list, "message-list-built",
4644 G_CALLBACK (mail_reader_message_list_built_cb), reader);
4646 g_signal_connect_swapped (
4647 message_list, "double-click",
4648 G_CALLBACK (mail_reader_double_click_cb), reader);
4650 g_signal_connect_swapped (
4651 message_list, "key-press",
4652 G_CALLBACK (mail_reader_key_press_cb), reader);
4654 g_signal_connect_swapped (
4655 message_list, "selection-change",
4656 G_CALLBACK (e_mail_reader_changed), reader);
4659 void
4660 e_mail_reader_changed (EMailReader *reader)
4662 MessageList *message_list;
4664 g_return_if_fail (E_IS_MAIL_READER (reader));
4666 g_signal_emit (reader, signals[CHANGED], 0);
4668 message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
4670 if (!message_list || message_list_selected_count (message_list) != 1)
4671 mail_reader_remove_followup_alert (reader);
4674 guint32
4675 e_mail_reader_check_state (EMailReader *reader)
4677 EShell *shell;
4678 GPtrArray *uids;
4679 CamelFolder *folder;
4680 CamelStore *store = NULL;
4681 EMailBackend *backend;
4682 ESourceRegistry *registry;
4683 EMailSession *mail_session;
4684 EMailAccountStore *account_store;
4685 const gchar *tag;
4686 gboolean can_clear_flags = FALSE;
4687 gboolean can_flag_completed = FALSE;
4688 gboolean can_flag_for_followup = FALSE;
4689 gboolean has_attachments = FALSE;
4690 gboolean has_deleted = FALSE;
4691 gboolean has_ignore_thread = FALSE;
4692 gboolean has_notignore_thread = FALSE;
4693 gboolean has_important = FALSE;
4694 gboolean has_junk = FALSE;
4695 gboolean has_not_junk = FALSE;
4696 gboolean has_read = FALSE;
4697 gboolean has_undeleted = FALSE;
4698 gboolean has_unimportant = FALSE;
4699 gboolean has_unread = FALSE;
4700 gboolean has_mail_note = FALSE;
4701 gboolean have_enabled_account = FALSE;
4702 gboolean drafts_or_outbox = FALSE;
4703 gboolean is_mailing_list;
4704 gboolean is_junk_folder = FALSE;
4705 gboolean is_vtrash_folder = FALSE;
4706 gboolean archive_folder_set = FALSE;
4707 guint32 state = 0;
4708 guint ii;
4710 g_return_val_if_fail (E_IS_MAIL_READER (reader), 0);
4712 backend = e_mail_reader_get_backend (reader);
4713 shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
4714 registry = e_shell_get_registry (shell);
4715 mail_session = e_mail_backend_get_session (backend);
4716 account_store = e_mail_ui_session_get_account_store (
4717 E_MAIL_UI_SESSION (mail_session));
4719 folder = e_mail_reader_ref_folder (reader);
4720 uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
4722 if (folder != NULL) {
4723 gchar *archive_folder;
4724 guint32 folder_flags;
4726 store = camel_folder_get_parent_store (folder);
4727 folder_flags = camel_folder_get_flags (folder);
4728 is_junk_folder = (folder_flags & CAMEL_FOLDER_IS_JUNK) != 0;
4729 is_vtrash_folder = (camel_store_get_flags (store) & CAMEL_STORE_VTRASH) != 0 && (folder_flags & CAMEL_FOLDER_IS_TRASH) != 0;
4730 drafts_or_outbox =
4731 em_utils_folder_is_drafts (registry, folder) ||
4732 em_utils_folder_is_outbox (registry, folder);
4734 archive_folder = em_utils_get_archive_folder_uri_from_folder (folder, backend, uids, TRUE);
4735 if (archive_folder && *archive_folder)
4736 archive_folder_set = TRUE;
4738 g_free (archive_folder);
4741 /* Initialize this flag based on whether there are any
4742 * messages selected. We will update it in the loop. */
4743 is_mailing_list = (uids->len > 0);
4745 for (ii = 0; ii < uids->len; ii++) {
4746 CamelMessageInfo *info;
4747 const gchar *string;
4748 guint32 flags;
4750 info = camel_folder_get_message_info (
4751 folder, uids->pdata[ii]);
4752 if (info == NULL)
4753 continue;
4755 if (camel_message_info_get_user_flag (info, E_MAIL_NOTES_USER_FLAG))
4756 has_mail_note = TRUE;
4758 flags = camel_message_info_get_flags (info);
4760 if (flags & CAMEL_MESSAGE_SEEN)
4761 has_read = TRUE;
4762 else
4763 has_unread = TRUE;
4765 if (flags & CAMEL_MESSAGE_ATTACHMENTS)
4766 has_attachments = TRUE;
4768 if (drafts_or_outbox) {
4769 has_junk = FALSE;
4770 has_not_junk = FALSE;
4771 } else {
4772 guint32 bitmask;
4774 /* XXX Strictly speaking, this logic is correct.
4775 * Problem is there's nothing in the message
4776 * list that indicates whether a message is
4777 * already marked "Not Junk". So the user may
4778 * think the "Not Junk" button is enabling and
4779 * disabling itself randomly as he reads mail. */
4781 if (flags & CAMEL_MESSAGE_JUNK)
4782 has_junk = TRUE;
4783 if (flags & CAMEL_MESSAGE_NOTJUNK)
4784 has_not_junk = TRUE;
4786 bitmask = CAMEL_MESSAGE_JUNK | CAMEL_MESSAGE_NOTJUNK;
4788 /* If neither junk flag is set, the
4789 * message can be marked either way. */
4790 if ((flags & bitmask) == 0) {
4791 has_junk = TRUE;
4792 has_not_junk = TRUE;
4796 if (flags & CAMEL_MESSAGE_DELETED)
4797 has_deleted = TRUE;
4798 else
4799 has_undeleted = TRUE;
4801 if (flags & CAMEL_MESSAGE_FLAGGED)
4802 has_important = TRUE;
4803 else
4804 has_unimportant = TRUE;
4806 tag = camel_message_info_get_user_tag (info, "follow-up");
4807 if (tag != NULL && *tag != '\0') {
4808 can_clear_flags = TRUE;
4809 tag = camel_message_info_get_user_tag (
4810 info, "completed-on");
4811 if (tag == NULL || *tag == '\0')
4812 can_flag_completed = TRUE;
4813 } else
4814 can_flag_for_followup = TRUE;
4816 string = camel_message_info_get_mlist (info);
4817 is_mailing_list &= (string != NULL && *string != '\0');
4819 has_ignore_thread = has_ignore_thread ||
4820 camel_message_info_get_user_flag (info, "ignore-thread");
4821 has_notignore_thread = has_notignore_thread ||
4822 !camel_message_info_get_user_flag (info, "ignore-thread");
4824 g_clear_object (&info);
4827 have_enabled_account =
4828 e_mail_account_store_have_enabled_service (
4829 account_store, CAMEL_TYPE_STORE);
4831 if (have_enabled_account)
4832 state |= E_MAIL_READER_HAVE_ENABLED_ACCOUNT;
4833 if (uids->len == 1)
4834 state |= E_MAIL_READER_SELECTION_SINGLE;
4835 if (uids->len > 1)
4836 state |= E_MAIL_READER_SELECTION_MULTIPLE;
4837 if (!drafts_or_outbox && uids->len == 1)
4838 state |= E_MAIL_READER_SELECTION_CAN_ADD_SENDER;
4839 if (can_clear_flags)
4840 state |= E_MAIL_READER_SELECTION_FLAG_CLEAR;
4841 if (can_flag_completed)
4842 state |= E_MAIL_READER_SELECTION_FLAG_COMPLETED;
4843 if (can_flag_for_followup)
4844 state |= E_MAIL_READER_SELECTION_FLAG_FOLLOWUP;
4845 if (has_attachments)
4846 state |= E_MAIL_READER_SELECTION_HAS_ATTACHMENTS;
4847 if (has_deleted)
4848 state |= E_MAIL_READER_SELECTION_HAS_DELETED;
4849 if (has_ignore_thread)
4850 state |= E_MAIL_READER_SELECTION_HAS_IGNORE_THREAD;
4851 if (has_notignore_thread)
4852 state |= E_MAIL_READER_SELECTION_HAS_NOTIGNORE_THREAD;
4853 if (has_important)
4854 state |= E_MAIL_READER_SELECTION_HAS_IMPORTANT;
4855 if (has_junk)
4856 state |= E_MAIL_READER_SELECTION_HAS_JUNK;
4857 if (has_not_junk)
4858 state |= E_MAIL_READER_SELECTION_HAS_NOT_JUNK;
4859 if (has_read)
4860 state |= E_MAIL_READER_SELECTION_HAS_READ;
4861 if (has_undeleted)
4862 state |= E_MAIL_READER_SELECTION_HAS_UNDELETED;
4863 if (has_unimportant)
4864 state |= E_MAIL_READER_SELECTION_HAS_UNIMPORTANT;
4865 if (has_unread)
4866 state |= E_MAIL_READER_SELECTION_HAS_UNREAD;
4867 if (is_mailing_list)
4868 state |= E_MAIL_READER_SELECTION_IS_MAILING_LIST;
4869 if (is_junk_folder)
4870 state |= E_MAIL_READER_FOLDER_IS_JUNK;
4871 if (is_vtrash_folder)
4872 state |= E_MAIL_READER_FOLDER_IS_VTRASH;
4873 if (archive_folder_set)
4874 state |= E_MAIL_READER_FOLDER_ARCHIVE_FOLDER_SET;
4875 if (has_mail_note)
4876 state |= E_MAIL_READER_SELECTION_HAS_MAIL_NOTE;
4878 g_clear_object (&folder);
4879 g_ptr_array_unref (uids);
4881 return state;
4884 EActivity *
4885 e_mail_reader_new_activity (EMailReader *reader)
4887 EActivity *activity;
4888 EMailBackend *backend;
4889 EAlertSink *alert_sink;
4890 GCancellable *cancellable;
4892 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
4894 activity = e_activity_new ();
4896 alert_sink = e_mail_reader_get_alert_sink (reader);
4897 e_activity_set_alert_sink (activity, alert_sink);
4899 cancellable = camel_operation_new ();
4900 e_activity_set_cancellable (activity, cancellable);
4901 g_object_unref (cancellable);
4903 backend = e_mail_reader_get_backend (reader);
4904 e_shell_backend_add_activity (E_SHELL_BACKEND (backend), activity);
4906 return activity;
4909 void
4910 e_mail_reader_update_actions (EMailReader *reader,
4911 guint32 state)
4913 g_return_if_fail (E_IS_MAIL_READER (reader));
4915 g_signal_emit (reader, signals[UPDATE_ACTIONS], 0, state);
4918 GtkAction *
4919 e_mail_reader_get_action (EMailReader *reader,
4920 const gchar *action_name)
4922 GtkAction *action = NULL;
4923 gint ii;
4925 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
4926 g_return_val_if_fail (action_name != NULL, NULL);
4928 for (ii = 0; ii < E_MAIL_READER_NUM_ACTION_GROUPS; ii++) {
4929 GtkActionGroup *group;
4931 group = e_mail_reader_get_action_group (reader, ii);
4932 action = gtk_action_group_get_action (group, action_name);
4934 if (action != NULL)
4935 break;
4938 if (action == NULL)
4939 g_critical (
4940 "%s: action '%s' not found", G_STRFUNC, action_name);
4942 return action;
4945 GtkActionGroup *
4946 e_mail_reader_get_action_group (EMailReader *reader,
4947 EMailReaderActionGroup group)
4949 EMailReaderInterface *iface;
4951 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
4953 iface = E_MAIL_READER_GET_INTERFACE (reader);
4954 g_return_val_if_fail (iface->get_action_group != NULL, NULL);
4956 return iface->get_action_group (reader, group);
4959 EAlertSink *
4960 e_mail_reader_get_alert_sink (EMailReader *reader)
4962 EMailReaderInterface *iface;
4964 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
4966 iface = E_MAIL_READER_GET_INTERFACE (reader);
4967 g_return_val_if_fail (iface->get_alert_sink != NULL, NULL);
4969 return iface->get_alert_sink (reader);
4972 EMailBackend *
4973 e_mail_reader_get_backend (EMailReader *reader)
4975 EMailReaderInterface *iface;
4977 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
4979 iface = E_MAIL_READER_GET_INTERFACE (reader);
4980 g_return_val_if_fail (iface->get_backend != NULL, NULL);
4982 return iface->get_backend (reader);
4985 EMailDisplay *
4986 e_mail_reader_get_mail_display (EMailReader *reader)
4988 EMailReaderInterface *iface;
4990 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
4992 iface = E_MAIL_READER_GET_INTERFACE (reader);
4993 g_return_val_if_fail (iface->get_mail_display != NULL, NULL);
4995 return iface->get_mail_display (reader);
4998 gboolean
4999 e_mail_reader_get_hide_deleted (EMailReader *reader)
5001 EMailReaderInterface *iface;
5003 g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE);
5005 iface = E_MAIL_READER_GET_INTERFACE (reader);
5006 g_return_val_if_fail (iface->get_hide_deleted != NULL, FALSE);
5008 return iface->get_hide_deleted (reader);
5011 GtkWidget *
5012 e_mail_reader_get_message_list (EMailReader *reader)
5014 EMailReaderInterface *iface;
5016 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
5018 iface = E_MAIL_READER_GET_INTERFACE (reader);
5019 g_return_val_if_fail (iface->get_message_list != NULL, NULL);
5021 return iface->get_message_list (reader);
5024 static void
5025 e_mail_reader_popup_menu_deactivate_cb (GtkMenu *popup_menu,
5026 EMailReader *reader)
5028 g_return_if_fail (GTK_IS_MENU (popup_menu));
5030 g_signal_handlers_disconnect_by_func (popup_menu, e_mail_reader_popup_menu_deactivate_cb, reader);
5031 gtk_menu_detach (popup_menu);
5034 GtkMenu *
5035 e_mail_reader_get_popup_menu (EMailReader *reader)
5037 EMailReaderInterface *iface;
5038 GtkMenu *menu;
5040 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
5042 iface = E_MAIL_READER_GET_INTERFACE (reader);
5043 g_return_val_if_fail (iface->get_popup_menu != NULL, NULL);
5045 menu = iface->get_popup_menu (reader);
5046 if (!gtk_menu_get_attach_widget (GTK_MENU (menu))) {
5047 gtk_menu_attach_to_widget (GTK_MENU (menu),
5048 GTK_WIDGET (reader),
5049 NULL);
5050 g_signal_connect (
5051 menu, "deactivate",
5052 G_CALLBACK (e_mail_reader_popup_menu_deactivate_cb), reader);
5055 return menu;
5058 EPreviewPane *
5059 e_mail_reader_get_preview_pane (EMailReader *reader)
5061 EMailReaderInterface *iface;
5063 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
5065 iface = E_MAIL_READER_GET_INTERFACE (reader);
5066 g_return_val_if_fail (iface->get_preview_pane != NULL, NULL);
5068 return iface->get_preview_pane (reader);
5071 GPtrArray *
5072 e_mail_reader_get_selected_uids (EMailReader *reader)
5074 EMailReaderInterface *iface;
5076 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
5078 iface = E_MAIL_READER_GET_INTERFACE (reader);
5079 g_return_val_if_fail (iface->get_selected_uids != NULL, NULL);
5081 return iface->get_selected_uids (reader);
5084 GPtrArray *
5085 e_mail_reader_get_selected_uids_with_collapsed_threads (EMailReader *reader)
5087 EMailReaderInterface *iface;
5089 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
5091 iface = E_MAIL_READER_GET_INTERFACE (reader);
5092 g_return_val_if_fail (iface->get_selected_uids_with_collapsed_threads != NULL, NULL);
5094 return iface->get_selected_uids_with_collapsed_threads (reader);
5097 GtkWindow *
5098 e_mail_reader_get_window (EMailReader *reader)
5100 EMailReaderInterface *iface;
5102 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
5104 iface = E_MAIL_READER_GET_INTERFACE (reader);
5105 g_return_val_if_fail (iface->get_window != NULL, NULL);
5107 return iface->get_window (reader);
5110 CamelFolder *
5111 e_mail_reader_ref_folder (EMailReader *reader)
5113 EMailReaderInterface *iface;
5115 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
5117 iface = E_MAIL_READER_GET_INTERFACE (reader);
5118 g_return_val_if_fail (iface->ref_folder != NULL, NULL);
5120 return iface->ref_folder (reader);
5123 void
5124 e_mail_reader_set_folder (EMailReader *reader,
5125 CamelFolder *folder)
5127 EMailReaderInterface *iface;
5129 g_return_if_fail (E_IS_MAIL_READER (reader));
5131 iface = E_MAIL_READER_GET_INTERFACE (reader);
5132 g_return_if_fail (iface->set_folder != NULL);
5134 iface->set_folder (reader, folder);
5137 void
5138 e_mail_reader_set_message (EMailReader *reader,
5139 const gchar *message_uid)
5141 EMailReaderInterface *iface;
5143 g_return_if_fail (E_IS_MAIL_READER (reader));
5145 iface = E_MAIL_READER_GET_INTERFACE (reader);
5146 g_return_if_fail (iface->set_message != NULL);
5148 iface->set_message (reader, message_uid);
5151 guint
5152 e_mail_reader_open_selected_mail (EMailReader *reader)
5154 EMailReaderInterface *iface;
5156 g_return_val_if_fail (E_IS_MAIL_READER (reader), 0);
5158 iface = E_MAIL_READER_GET_INTERFACE (reader);
5159 g_return_val_if_fail (iface->open_selected_mail != NULL, 0);
5161 return iface->open_selected_mail (reader);
5164 EMailForwardStyle
5165 e_mail_reader_get_forward_style (EMailReader *reader)
5167 EMailReaderPrivate *priv;
5169 g_return_val_if_fail (E_IS_MAIL_READER (reader), 0);
5171 priv = E_MAIL_READER_GET_PRIVATE (reader);
5173 return priv->forward_style;
5176 void
5177 e_mail_reader_set_forward_style (EMailReader *reader,
5178 EMailForwardStyle style)
5180 EMailReaderPrivate *priv;
5182 g_return_if_fail (E_IS_MAIL_READER (reader));
5184 priv = E_MAIL_READER_GET_PRIVATE (reader);
5186 if (priv->forward_style == style)
5187 return;
5189 priv->forward_style = style;
5191 g_object_notify (G_OBJECT (reader), "forward-style");
5194 gboolean
5195 e_mail_reader_get_group_by_threads (EMailReader *reader)
5197 EMailReaderPrivate *priv;
5199 g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE);
5201 priv = E_MAIL_READER_GET_PRIVATE (reader);
5203 return priv->group_by_threads;
5206 void
5207 e_mail_reader_set_group_by_threads (EMailReader *reader,
5208 gboolean group_by_threads)
5210 EMailReaderPrivate *priv;
5212 g_return_if_fail (E_IS_MAIL_READER (reader));
5214 priv = E_MAIL_READER_GET_PRIVATE (reader);
5216 if (priv->group_by_threads == group_by_threads)
5217 return;
5219 priv->group_by_threads = group_by_threads;
5221 g_object_notify (G_OBJECT (reader), "group-by-threads");
5224 EMailReplyStyle
5225 e_mail_reader_get_reply_style (EMailReader *reader)
5227 EMailReaderPrivate *priv;
5229 g_return_val_if_fail (E_IS_MAIL_READER (reader), 0);
5231 priv = E_MAIL_READER_GET_PRIVATE (reader);
5233 return priv->reply_style;
5236 void
5237 e_mail_reader_set_reply_style (EMailReader *reader,
5238 EMailReplyStyle style)
5240 EMailReaderPrivate *priv;
5242 g_return_if_fail (E_IS_MAIL_READER (reader));
5244 priv = E_MAIL_READER_GET_PRIVATE (reader);
5246 if (priv->reply_style == style)
5247 return;
5249 priv->reply_style = style;
5251 g_object_notify (G_OBJECT (reader), "reply-style");
5254 gboolean
5255 e_mail_reader_get_mark_seen_always (EMailReader *reader)
5257 EMailReaderPrivate *priv;
5259 g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE);
5261 priv = E_MAIL_READER_GET_PRIVATE (reader);
5263 return priv->mark_seen_always;
5266 void
5267 e_mail_reader_set_mark_seen_always (EMailReader *reader,
5268 gboolean mark_seen_always)
5270 EMailReaderPrivate *priv;
5272 g_return_if_fail (E_IS_MAIL_READER (reader));
5274 priv = E_MAIL_READER_GET_PRIVATE (reader);
5276 if (priv->mark_seen_always == mark_seen_always)
5277 return;
5279 priv->mark_seen_always = mark_seen_always;
5281 g_object_notify (G_OBJECT (reader), "mark-seen-always");
5284 gboolean
5285 e_mail_reader_get_delete_selects_previous (EMailReader *reader)
5287 EMailReaderPrivate *priv;
5289 g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE);
5291 priv = E_MAIL_READER_GET_PRIVATE (reader);
5293 return priv->delete_selects_previous;
5296 void
5297 e_mail_reader_set_delete_selects_previous (EMailReader *reader,
5298 gboolean delete_selects_previous)
5300 EMailReaderPrivate *priv;
5302 g_return_if_fail (E_IS_MAIL_READER (reader));
5304 priv = E_MAIL_READER_GET_PRIVATE (reader);
5306 if (priv->delete_selects_previous == delete_selects_previous)
5307 return;
5309 priv->delete_selects_previous = delete_selects_previous;
5311 g_object_notify (G_OBJECT (reader), "delete-selects-previous");
5314 void
5315 e_mail_reader_create_charset_menu (EMailReader *reader,
5316 GtkUIManager *ui_manager,
5317 guint merge_id)
5319 GtkAction *action;
5320 const gchar *action_name;
5321 const gchar *path;
5322 GSList *list;
5324 g_return_if_fail (E_IS_MAIL_READER (reader));
5325 g_return_if_fail (GTK_IS_UI_MANAGER (ui_manager));
5327 action_name = "mail-charset-default";
5328 action = e_mail_reader_get_action (reader, action_name);
5329 g_return_if_fail (action != NULL);
5331 list = gtk_radio_action_get_group (GTK_RADIO_ACTION (action));
5332 list = g_slist_copy (list);
5333 list = g_slist_remove (list, action);
5334 list = g_slist_sort (list, (GCompareFunc) e_action_compare_by_label);
5336 path = "/main-menu/view-menu/mail-message-view-actions/mail-encoding-menu";
5338 while (list != NULL) {
5339 action = list->data;
5341 gtk_ui_manager_add_ui (
5342 ui_manager, merge_id, path,
5343 gtk_action_get_name (action),
5344 gtk_action_get_name (action),
5345 GTK_UI_MANAGER_AUTO, FALSE);
5347 list = g_slist_delete_link (list, list);
5350 gtk_ui_manager_ensure_update (ui_manager);
5353 void
5354 e_mail_reader_show_search_bar (EMailReader *reader)
5356 g_return_if_fail (E_IS_MAIL_READER (reader));
5358 g_signal_emit (reader, signals[SHOW_SEARCH_BAR], 0);
5361 void
5362 e_mail_reader_avoid_next_mark_as_seen (EMailReader *reader)
5364 EMailReaderPrivate *priv;
5365 MessageList *message_list;
5367 g_return_if_fail (reader != NULL);
5369 priv = E_MAIL_READER_GET_PRIVATE (reader);
5370 g_return_if_fail (priv != NULL);
5372 message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
5373 g_return_if_fail (message_list != NULL);
5375 priv->avoid_next_mark_as_seen = TRUE;
5378 void
5379 e_mail_reader_unset_folder_just_selected (EMailReader *reader)
5381 EMailReaderPrivate *priv;
5383 g_return_if_fail (reader != NULL);
5385 priv = E_MAIL_READER_GET_PRIVATE (reader);
5386 g_return_if_fail (priv != NULL);
5388 priv->folder_was_just_selected = FALSE;
5392 * e_mail_reader_composer_created:
5393 * @reader: an #EMailReader
5394 * @composer: an #EMsgComposer
5395 * @message: the source #CamelMimeMessage, or %NULL
5397 * Emits a #EMailReader::composer-created signal to indicate the @composer
5398 * window was created in response to a user action on @reader. Examples of
5399 * such actions include replying, forwarding, and composing a new message.
5400 * If applicable, the source @message (i.e. the message being replied to or
5401 * forwarded) should be included.
5403 void
5404 e_mail_reader_composer_created (EMailReader *reader,
5405 EMsgComposer *composer,
5406 CamelMimeMessage *message)
5408 g_return_if_fail (E_IS_MAIL_READER (reader));
5409 g_return_if_fail (E_IS_MSG_COMPOSER (composer));
5411 if (message != NULL)
5412 g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
5414 g_signal_emit (
5415 reader, signals[COMPOSER_CREATED], 0, composer, message);
5418 static void
5419 e_mail_reader_load_remote_content_clicked_cb (GtkButton *button,
5420 EMailReader *reader)
5422 EMailDisplay *mail_display;
5424 g_return_if_fail (E_IS_MAIL_READER (reader));
5426 mail_display = e_mail_reader_get_mail_display (reader);
5428 /* This causes reload, thus also alert removal */
5429 e_mail_display_load_images (mail_display);
5432 static GList *
5433 e_mail_reader_get_from_mails (EMailDisplay *mail_display)
5435 EMailPartList *part_list;
5436 CamelMimeMessage *message;
5437 CamelInternetAddress *from;
5438 GList *mails = NULL;
5440 g_return_val_if_fail (E_IS_MAIL_DISPLAY (mail_display), NULL);
5442 part_list = e_mail_display_get_part_list (mail_display);
5443 if (!part_list)
5444 return NULL;
5446 message = e_mail_part_list_get_message (part_list);
5447 if (!message)
5448 return NULL;
5450 from = camel_mime_message_get_from (message);
5451 if (from) {
5452 GHashTable *domains;
5453 GHashTableIter iter;
5454 gpointer key, value;
5455 gint ii, len;
5457 domains = g_hash_table_new (camel_strcase_hash, camel_strcase_equal);
5459 len = camel_address_length (CAMEL_ADDRESS (from));
5460 for (ii = 0; ii < len; ii++) {
5461 const gchar *mail = NULL;
5463 if (!camel_internet_address_get (from, ii, NULL, &mail))
5464 break;
5466 if (mail && *mail) {
5467 const gchar *at;
5469 mails = g_list_prepend (mails, g_strdup (mail));
5471 at = strchr (mail, '@');
5472 if (at && at != mail && at[1])
5473 g_hash_table_insert (domains, (gpointer) at, NULL);
5477 g_hash_table_iter_init (&iter, domains);
5478 while (g_hash_table_iter_next (&iter, &key, &value)) {
5479 const gchar *domain = key;
5481 mails = g_list_prepend (mails, g_strdup (domain));
5484 g_hash_table_destroy (domains);
5487 return g_list_reverse (mails);
5490 static void
5491 e_mail_reader_remote_content_menu_deactivate_cb (GtkMenuShell *popup_menu,
5492 GtkToggleButton *toggle_button)
5494 g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle_button));
5496 gtk_toggle_button_set_active (toggle_button, FALSE);
5497 gtk_menu_detach (GTK_MENU (popup_menu));
5500 #define REMOTE_CONTENT_KEY_IS_MAIL "remote-content-key-is-mail"
5501 #define REMOTE_CONTENT_KEY_VALUE "remote-content-key-value"
5503 static void
5504 e_mail_reader_remote_content_menu_activate_cb (GObject *item,
5505 EMailReader *reader)
5507 EMailDisplay *mail_display;
5508 EMailRemoteContent *remote_content;
5509 gboolean is_mail;
5510 const gchar *value;
5512 g_return_if_fail (GTK_IS_MENU_ITEM (item));
5513 g_return_if_fail (E_IS_MAIL_READER (reader));
5515 is_mail = GPOINTER_TO_INT (g_object_get_data (item, REMOTE_CONTENT_KEY_IS_MAIL)) == 1;
5516 value = g_object_get_data (item, REMOTE_CONTENT_KEY_VALUE);
5518 g_return_if_fail (value && *value);
5520 mail_display = e_mail_reader_get_mail_display (reader);
5521 if (!mail_display)
5522 return;
5524 remote_content = e_mail_display_ref_remote_content (mail_display);
5525 if (!remote_content)
5526 return;
5528 if (is_mail)
5529 e_mail_remote_content_add_mail (remote_content, value);
5530 else
5531 e_mail_remote_content_add_site (remote_content, value);
5533 g_clear_object (&remote_content);
5535 e_mail_display_reload (mail_display);
5538 static void
5539 e_mail_reader_remote_content_disable_activate_cb (GObject *item,
5540 EMailReader *reader)
5542 EMailDisplay *mail_display;
5543 GSettings *settings;
5545 g_return_if_fail (E_IS_MAIL_READER (reader));
5547 settings = e_util_ref_settings ("org.gnome.evolution.mail");
5548 g_settings_set_boolean (settings, "notify-remote-content", FALSE);
5549 g_clear_object (&settings);
5551 mail_display = e_mail_reader_get_mail_display (reader);
5552 if (mail_display)
5553 e_mail_display_reload (mail_display);
5556 static void
5557 e_mail_reader_add_remote_content_menu_item (EMailReader *reader,
5558 GtkWidget *popup_menu,
5559 const gchar *label,
5560 gboolean is_mail,
5561 const gchar *value)
5563 GtkWidget *item;
5564 GObject *object;
5566 g_return_if_fail (E_IS_MAIL_READER (reader));
5567 g_return_if_fail (GTK_IS_MENU (popup_menu));
5568 g_return_if_fail (label != NULL);
5569 g_return_if_fail (value != NULL);
5571 item = gtk_menu_item_new_with_label (label);
5572 object = G_OBJECT (item);
5574 g_object_set_data (object, REMOTE_CONTENT_KEY_IS_MAIL, is_mail ? GINT_TO_POINTER (1) : NULL);
5575 g_object_set_data_full (object, REMOTE_CONTENT_KEY_VALUE, g_strdup (value), g_free);
5577 g_signal_connect (item, "activate", G_CALLBACK (e_mail_reader_remote_content_menu_activate_cb), reader);
5579 gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), item);
5582 static void
5583 e_mail_reader_show_remote_content_popup (EMailReader *reader,
5584 GdkEventButton *event,
5585 GtkToggleButton *toggle_button)
5587 EMailDisplay *mail_display;
5588 GList *mails, *sites, *link;
5589 GtkWidget *popup_menu = NULL;
5591 g_return_if_fail (E_IS_MAIL_READER (reader));
5593 mail_display = e_mail_reader_get_mail_display (reader);
5594 mails = e_mail_reader_get_from_mails (mail_display);
5595 sites = e_mail_display_get_skipped_remote_content_sites (mail_display);
5597 for (link = mails; link; link = g_list_next (link)) {
5598 const gchar *mail = link->data;
5599 gchar *label;
5601 if (!mail || !*mail)
5602 continue;
5604 if (!popup_menu)
5605 popup_menu = gtk_menu_new ();
5607 if (*mail == '@')
5608 label = g_strdup_printf (_("Allow remote content for anyone from %s"), mail);
5609 else
5610 label = g_strdup_printf (_("Allow remote content for %s"), mail);
5612 e_mail_reader_add_remote_content_menu_item (reader, popup_menu, label, TRUE, mail);
5614 g_free (label);
5617 for (link = sites; link; link = g_list_next (link)) {
5618 const gchar *site = link->data;
5619 gchar *label;
5621 if (!site || !*site)
5622 continue;
5624 if (!popup_menu)
5625 popup_menu = gtk_menu_new ();
5627 label = g_strdup_printf (_("Allow remote content from %s"), site);
5629 e_mail_reader_add_remote_content_menu_item (reader, popup_menu, label, FALSE, site);
5631 g_free (label);
5634 g_list_free_full (mails, g_free);
5635 g_list_free_full (sites, g_free);
5637 if (popup_menu) {
5638 GtkWidget *box = gtk_widget_get_parent (GTK_WIDGET (toggle_button));
5639 GtkWidget *item;
5641 item = gtk_separator_menu_item_new ();
5642 gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), item);
5644 item = gtk_menu_item_new_with_label (_("Do not show this message again"));
5645 gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), item);
5646 g_signal_connect (item, "activate", G_CALLBACK (e_mail_reader_remote_content_disable_activate_cb), reader);
5648 gtk_toggle_button_set_active (toggle_button, TRUE);
5650 g_signal_connect (
5651 popup_menu, "deactivate",
5652 G_CALLBACK (e_mail_reader_remote_content_menu_deactivate_cb), toggle_button);
5654 gtk_widget_show_all (popup_menu);
5656 gtk_menu_attach_to_widget (GTK_MENU (popup_menu), box, NULL);
5658 g_object_set (popup_menu,
5659 "anchor-hints", (GDK_ANCHOR_FLIP_Y |
5660 GDK_ANCHOR_SLIDE |
5661 GDK_ANCHOR_RESIZE),
5662 NULL);
5664 gtk_menu_popup_at_widget (GTK_MENU (popup_menu),
5665 box,
5666 GDK_GRAVITY_SOUTH_WEST,
5667 GDK_GRAVITY_NORTH_WEST,
5668 (const GdkEvent *) event);
5672 static gboolean
5673 e_mail_reader_options_remote_content_button_press_cb (GtkToggleButton *toggle_button,
5674 GdkEventButton *event,
5675 EMailReader *reader)
5677 g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE);
5679 if (event && event->button == 1) {
5680 e_mail_reader_show_remote_content_popup (reader, event, toggle_button);
5681 return TRUE;
5684 return FALSE;
5687 static GtkWidget *
5688 e_mail_reader_create_remote_content_alert_button (EMailReader *reader)
5690 GtkWidget *box, *button, *arrow;
5692 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
5694 gtk_style_context_add_class (gtk_widget_get_style_context (box), "linked");
5696 button = gtk_button_new_with_label (_("Load remote content"));
5697 gtk_container_add (GTK_CONTAINER (box), button);
5699 g_signal_connect (button, "clicked",
5700 G_CALLBACK (e_mail_reader_load_remote_content_clicked_cb), reader);
5702 button = gtk_toggle_button_new ();
5703 gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
5705 g_signal_connect (button, "button-press-event",
5706 G_CALLBACK (e_mail_reader_options_remote_content_button_press_cb), reader);
5708 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
5709 gtk_container_add (GTK_CONTAINER (button), arrow);
5711 gtk_widget_show_all (box);
5713 return box;
5716 static void
5717 mail_reader_display_load_changed_cb (EMailDisplay *mail_display,
5718 WebKitLoadEvent load_event,
5719 EMailReader *reader)
5721 EMailReaderPrivate *priv;
5723 g_return_if_fail (E_IS_MAIL_DISPLAY (mail_display));
5724 g_return_if_fail (E_IS_MAIL_READER (reader));
5726 priv = E_MAIL_READER_GET_PRIVATE (reader);
5727 g_return_if_fail (priv != NULL);
5729 if (load_event == WEBKIT_LOAD_STARTED) {
5730 if (priv->remote_content_alert)
5731 e_alert_response (priv->remote_content_alert, GTK_RESPONSE_CLOSE);
5732 return;
5735 if (load_event != WEBKIT_LOAD_FINISHED)
5736 return;
5738 if (!e_mail_display_has_skipped_remote_content_sites (mail_display))
5739 return;
5741 if (!priv->remote_content_alert) {
5742 EPreviewPane *preview_pane;
5743 GtkWidget *button;
5744 EAlert *alert;
5746 alert = e_alert_new ("mail:remote-content-info", NULL);
5747 button = e_mail_reader_create_remote_content_alert_button (reader);
5748 e_alert_add_widget (alert, button); /* button is consumed by the alert */
5749 preview_pane = e_mail_reader_get_preview_pane (reader);
5750 e_alert_sink_submit_alert (E_ALERT_SINK (preview_pane), alert);
5752 priv->remote_content_alert = alert;
5753 g_object_add_weak_pointer (G_OBJECT (priv->remote_content_alert), &priv->remote_content_alert);
5755 g_object_unref (alert);
5760 * e_mail_reader_connect_remote_content:
5761 * @reader: an #EMailReader
5763 * Connects signal handlers to manage remote content download around
5764 * the internal #EMailDisplay.
5766 void
5767 e_mail_reader_connect_remote_content (EMailReader *reader)
5769 EMailDisplay *mail_display;
5771 g_return_if_fail (E_IS_MAIL_READER (reader));
5773 mail_display = e_mail_reader_get_mail_display (reader);
5774 g_return_if_fail (E_IS_MAIL_DISPLAY (mail_display));
5776 g_signal_connect (mail_display, "load-changed",
5777 G_CALLBACK (mail_reader_display_load_changed_cb), reader);