Bug 262328 - Selecting collapsed threads only selects the first message
[evolution.git] / src / mail / e-mail-reader.c
blobbead18232367e16c3e4da5a3587842bcecb2891f
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_group_cb (GtkAction *action,
1481 EMailReader *reader)
1483 GSettings *settings;
1484 gboolean reply_list;
1485 guint32 state;
1486 const gchar *key;
1488 state = e_mail_reader_check_state (reader);
1490 settings = e_util_ref_settings ("org.gnome.evolution.mail");
1492 key = "composer-group-reply-to-list";
1493 reply_list = g_settings_get_boolean (settings, key);
1495 g_object_unref (settings);
1497 if (reply_list && (state & E_MAIL_READER_SELECTION_IS_MAILING_LIST)) {
1498 e_mail_reader_reply_to_message (
1499 reader, NULL, E_MAIL_REPLY_TO_LIST);
1500 } else
1501 action_mail_reply_all_cb (action, reader);
1504 static void
1505 action_mail_reply_list_cb (GtkAction *action,
1506 EMailReader *reader)
1508 e_mail_reader_reply_to_message (reader, NULL, E_MAIL_REPLY_TO_LIST);
1511 static gboolean
1512 message_is_list_administrative (CamelMimeMessage *message)
1514 const gchar *header;
1516 header = camel_medium_get_header (
1517 CAMEL_MEDIUM (message), "X-List-Administrivia");
1518 if (header == NULL)
1519 return FALSE;
1521 while (*header == ' ' || *header == '\t')
1522 header++;
1524 return g_ascii_strncasecmp (header, "yes", 3) == 0;
1527 static void
1528 action_mail_reply_sender_check (CamelFolder *folder,
1529 GAsyncResult *result,
1530 EMailReaderClosure *closure)
1532 EAlertSink *alert_sink;
1533 CamelMimeMessage *message;
1534 EMailReplyType type = E_MAIL_REPLY_TO_SENDER;
1535 GSettings *settings;
1536 gboolean ask_ignore_list_reply_to;
1537 gboolean ask_list_reply_to;
1538 gboolean munged_list_message;
1539 gboolean active;
1540 const gchar *key;
1541 GError *local_error = NULL;
1543 alert_sink = e_activity_get_alert_sink (closure->activity);
1545 message = camel_folder_get_message_finish (
1546 folder, result, &local_error);
1548 /* Sanity check. */
1549 g_return_if_fail (
1550 ((message != NULL) && (local_error == NULL)) ||
1551 ((message == NULL) && (local_error != NULL)));
1553 if (e_activity_handle_cancellation (closure->activity, local_error)) {
1554 mail_reader_closure_free (closure);
1555 g_error_free (local_error);
1556 return;
1558 } else if (local_error != NULL) {
1559 e_alert_submit (
1560 alert_sink, "mail:no-retrieve-message",
1561 local_error->message, NULL);
1562 mail_reader_closure_free (closure);
1563 g_error_free (local_error);
1564 return;
1567 settings = e_util_ref_settings ("org.gnome.evolution.mail");
1569 key = "composer-ignore-list-reply-to";
1570 ask_ignore_list_reply_to = g_settings_get_boolean (settings, key);
1572 key = "prompt-on-list-reply-to";
1573 ask_list_reply_to = g_settings_get_boolean (settings, key);
1575 munged_list_message = em_utils_is_munged_list_message (message);
1577 if (message_is_list_administrative (message)) {
1578 /* Do not ask for messages which are list administrative,
1579 * like list confirmation messages. */
1580 } else if (ask_ignore_list_reply_to || !munged_list_message) {
1581 /* Don't do the "Are you sure you want to reply in private?"
1582 * pop-up if it's a Reply-To: munged list message... unless
1583 * we're ignoring munging. */
1584 GtkWidget *dialog;
1585 GtkWidget *check;
1586 GtkWidget *container;
1587 gint response;
1589 dialog = e_alert_dialog_new_for_args (
1590 e_mail_reader_get_window (closure->reader),
1591 "mail:ask-list-private-reply", NULL);
1593 container = e_alert_dialog_get_content_area (
1594 E_ALERT_DIALOG (dialog));
1596 /* Check buttons */
1597 check = gtk_check_button_new_with_mnemonic (
1598 _("_Do not ask me again."));
1599 gtk_box_pack_start (
1600 GTK_BOX (container), check, FALSE, FALSE, 0);
1601 gtk_widget_show (check);
1603 response = gtk_dialog_run (GTK_DIALOG (dialog));
1605 active = gtk_toggle_button_get_active (
1606 GTK_TOGGLE_BUTTON (check));
1607 if (active) {
1608 key = "prompt-on-private-list-reply";
1609 g_settings_set_boolean (settings, key, FALSE);
1612 gtk_widget_destroy (dialog);
1614 if (response == GTK_RESPONSE_YES)
1615 type = E_MAIL_REPLY_TO_ALL;
1616 else if (response == GTK_RESPONSE_OK)
1617 type = E_MAIL_REPLY_TO_LIST;
1618 else if (response == GTK_RESPONSE_CANCEL ||
1619 response == GTK_RESPONSE_DELETE_EVENT) {
1620 goto exit;
1623 } else if (ask_list_reply_to) {
1624 GtkWidget *dialog;
1625 GtkWidget *container;
1626 GtkWidget *check_again;
1627 GtkWidget *check_always_ignore;
1628 gint response;
1630 dialog = e_alert_dialog_new_for_args (
1631 e_mail_reader_get_window (closure->reader),
1632 "mail:ask-list-honour-reply-to", NULL);
1634 container = e_alert_dialog_get_content_area (
1635 E_ALERT_DIALOG (dialog));
1637 check_again = gtk_check_button_new_with_mnemonic (
1638 _("_Do not ask me again."));
1639 gtk_box_pack_start (
1640 GTK_BOX (container), check_again, FALSE, FALSE, 0);
1641 gtk_widget_show (check_again);
1643 check_always_ignore = gtk_check_button_new_with_mnemonic (
1644 _("_Always ignore Reply-To: for mailing lists."));
1645 gtk_box_pack_start (
1646 GTK_BOX (container), check_always_ignore,
1647 FALSE, FALSE, 0);
1648 gtk_widget_show (check_always_ignore);
1650 response = gtk_dialog_run (GTK_DIALOG (dialog));
1652 active = gtk_toggle_button_get_active (
1653 GTK_TOGGLE_BUTTON (check_again));
1654 if (active) {
1655 key = "prompt-on-list-reply-to";
1656 g_settings_set_boolean (settings, key, FALSE);
1659 key = "composer-ignore-list-reply-to";
1660 active = gtk_toggle_button_get_active (
1661 GTK_TOGGLE_BUTTON (check_always_ignore));
1662 g_settings_set_boolean (settings, key, active);
1664 gtk_widget_destroy (dialog);
1666 switch (response) {
1667 case GTK_RESPONSE_NO:
1668 type = E_MAIL_REPLY_TO_FROM;
1669 break;
1670 case GTK_RESPONSE_OK:
1671 type = E_MAIL_REPLY_TO_LIST;
1672 break;
1673 case GTK_RESPONSE_CANCEL:
1674 case GTK_RESPONSE_DELETE_EVENT:
1675 goto exit;
1676 default:
1677 break;
1681 e_mail_reader_reply_to_message (closure->reader, message, type);
1683 exit:
1684 g_object_unref (settings);
1685 g_object_unref (message);
1687 mail_reader_closure_free (closure);
1690 static void
1691 action_mail_reply_sender_cb (GtkAction *action,
1692 EMailReader *reader)
1694 GSettings *settings;
1695 gboolean ask_list_reply_to;
1696 gboolean ask_private_list_reply;
1697 gboolean ask;
1698 guint32 state;
1699 const gchar *key;
1701 state = e_mail_reader_check_state (reader);
1703 settings = e_util_ref_settings ("org.gnome.evolution.mail");
1705 key = "prompt-on-list-reply-to";
1706 ask_list_reply_to = g_settings_get_boolean (settings, key);
1708 key = "prompt-on-private-list-reply";
1709 ask_private_list_reply = g_settings_get_boolean (settings, key);
1711 g_object_unref (settings);
1713 ask = (ask_private_list_reply || ask_list_reply_to);
1715 if (ask && (state & E_MAIL_READER_SELECTION_IS_MAILING_LIST)) {
1716 EActivity *activity;
1717 GCancellable *cancellable;
1718 EMailReaderClosure *closure;
1719 CamelFolder *folder;
1720 GtkWidget *message_list;
1721 const gchar *message_uid;
1723 message_list = e_mail_reader_get_message_list (reader);
1724 message_uid = MESSAGE_LIST (message_list)->cursor_uid;
1725 g_return_if_fail (message_uid != NULL);
1727 activity = e_mail_reader_new_activity (reader);
1728 cancellable = e_activity_get_cancellable (activity);
1730 closure = g_slice_new0 (EMailReaderClosure);
1731 closure->activity = activity;
1732 closure->reader = g_object_ref (reader);
1734 folder = e_mail_reader_ref_folder (reader);
1736 camel_folder_get_message (
1737 folder, message_uid, G_PRIORITY_DEFAULT,
1738 cancellable, (GAsyncReadyCallback)
1739 action_mail_reply_sender_check, closure);
1741 g_clear_object (&folder);
1743 return;
1746 e_mail_reader_reply_to_message (reader, NULL, E_MAIL_REPLY_TO_SENDER);
1749 static void
1750 action_mail_reply_recipient_cb (GtkAction *action,
1751 EMailReader *reader)
1753 e_mail_reader_reply_to_message (reader, NULL, E_MAIL_REPLY_TO_RECIPIENT);
1756 static void
1757 action_mail_save_as_cb (GtkAction *action,
1758 EMailReader *reader)
1760 e_mail_reader_save_messages (reader);
1763 static void
1764 action_mail_search_folder_from_mailing_list_cb (GtkAction *action,
1765 EMailReader *reader)
1767 e_mail_reader_create_vfolder_from_selected (reader, AUTO_MLIST);
1770 static void
1771 action_mail_search_folder_from_recipients_cb (GtkAction *action,
1772 EMailReader *reader)
1774 e_mail_reader_create_vfolder_from_selected (reader, AUTO_TO);
1777 static void
1778 action_mail_search_folder_from_sender_cb (GtkAction *action,
1779 EMailReader *reader)
1781 e_mail_reader_create_vfolder_from_selected (reader, AUTO_FROM);
1784 static void
1785 action_mail_search_folder_from_subject_cb (GtkAction *action,
1786 EMailReader *reader)
1788 e_mail_reader_create_vfolder_from_selected (reader, AUTO_SUBJECT);
1791 static void
1792 action_mail_show_all_headers_cb (GtkToggleAction *action,
1793 EMailReader *reader)
1795 EMailDisplay *display;
1796 EMailFormatterMode mode;
1798 display = e_mail_reader_get_mail_display (reader);
1800 /* Ignore action when viewing message source. */
1801 mode = e_mail_display_get_mode (display);
1802 if (mode == E_MAIL_FORMATTER_MODE_SOURCE)
1803 return;
1804 if (mode == E_MAIL_FORMATTER_MODE_RAW)
1805 return;
1807 if (gtk_toggle_action_get_active (action))
1808 mode = E_MAIL_FORMATTER_MODE_ALL_HEADERS;
1809 else
1810 mode = E_MAIL_FORMATTER_MODE_NORMAL;
1812 e_mail_display_set_mode (display, mode);
1815 static void
1816 mail_source_retrieved (GObject *source_object,
1817 GAsyncResult *result,
1818 gpointer user_data)
1820 EMailReaderClosure *closure;
1821 CamelMimeMessage *message;
1822 EMailDisplay *display;
1823 GError *error = NULL;
1825 closure = (EMailReaderClosure *) user_data;
1826 display = e_mail_reader_get_mail_display (closure->reader);
1828 message = camel_folder_get_message_finish (
1829 CAMEL_FOLDER (source_object), result, &error);
1831 /* Sanity check. */
1832 g_return_if_fail (
1833 ((message != NULL) && (error == NULL)) ||
1834 ((message == NULL) && (error != NULL)));
1836 if (message != NULL) {
1837 mail_reader_set_display_formatter_for_message (
1838 closure->reader, display,
1839 closure->message_uid, message,
1840 CAMEL_FOLDER (source_object));
1841 g_object_unref (message);
1842 } else {
1843 gchar *status;
1845 status = g_strdup_printf (
1846 "%s<br>%s",
1847 _("Failed to retrieve message:"),
1848 error->message);
1849 e_mail_display_set_status (display, status);
1850 g_free (status);
1852 g_error_free (error);
1855 e_activity_set_state (closure->activity, E_ACTIVITY_COMPLETED);
1857 mail_reader_closure_free (closure);
1860 static void
1861 action_mail_show_source_cb (GtkAction *action,
1862 EMailReader *reader)
1864 EMailDisplay *display;
1865 EMailBackend *backend;
1866 GtkWidget *browser;
1867 CamelFolder *folder;
1868 GPtrArray *uids;
1869 const gchar *message_uid;
1870 gchar *string;
1871 EActivity *activity;
1872 GCancellable *cancellable;
1873 EMailReaderClosure *closure;
1874 MessageList *ml;
1876 backend = e_mail_reader_get_backend (reader);
1877 folder = e_mail_reader_ref_folder (reader);
1878 uids = e_mail_reader_get_selected_uids (reader);
1879 g_return_if_fail (uids != NULL && uids->len == 1);
1880 message_uid = g_ptr_array_index (uids, 0);
1882 browser = e_mail_browser_new (backend, E_MAIL_FORMATTER_MODE_SOURCE);
1883 ml = MESSAGE_LIST (e_mail_reader_get_message_list (E_MAIL_READER (browser)));
1885 message_list_freeze (ml);
1886 e_mail_reader_set_folder (E_MAIL_READER (browser), folder);
1887 e_mail_reader_set_message (E_MAIL_READER (browser), message_uid);
1888 message_list_thaw (ml);
1890 display = e_mail_reader_get_mail_display (E_MAIL_READER (browser));
1892 string = g_strdup_printf (_("Retrieving message “%s”"), message_uid);
1893 e_mail_display_set_part_list (display, NULL);
1894 e_mail_display_set_status (display, string);
1895 gtk_widget_show (browser);
1897 activity = e_mail_reader_new_activity (reader);
1898 e_activity_set_text (activity, string);
1899 cancellable = e_activity_get_cancellable (activity);
1900 g_free (string);
1902 closure = g_slice_new0 (EMailReaderClosure);
1903 closure->reader = g_object_ref (browser);
1904 closure->activity = g_object_ref (activity);
1905 closure->message_uid = g_strdup (message_uid);
1907 camel_folder_get_message (
1908 folder, message_uid, G_PRIORITY_DEFAULT,
1909 cancellable, mail_source_retrieved, closure);
1911 g_object_unref (activity);
1913 g_ptr_array_unref (uids);
1915 g_clear_object (&folder);
1918 static void
1919 action_mail_toggle_important_cb (GtkAction *action,
1920 EMailReader *reader)
1922 CamelFolder *folder;
1923 GPtrArray *uids;
1924 guint ii;
1926 folder = e_mail_reader_ref_folder (reader);
1927 uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
1929 camel_folder_freeze (folder);
1931 for (ii = 0; ii < uids->len; ii++) {
1932 guint32 flags;
1934 flags = camel_folder_get_message_flags (
1935 folder, uids->pdata[ii]);
1936 flags ^= CAMEL_MESSAGE_FLAGGED;
1937 if (flags & CAMEL_MESSAGE_FLAGGED)
1938 flags &= ~CAMEL_MESSAGE_DELETED;
1940 camel_folder_set_message_flags (
1941 folder, uids->pdata[ii], CAMEL_MESSAGE_FLAGGED |
1942 CAMEL_MESSAGE_DELETED, flags);
1945 camel_folder_thaw (folder);
1947 g_clear_object (&folder);
1948 g_ptr_array_unref (uids);
1951 static void
1952 action_mail_undelete_cb (GtkAction *action,
1953 EMailReader *reader)
1955 guint32 mask = CAMEL_MESSAGE_DELETED;
1956 guint32 set = 0;
1958 e_mail_reader_mark_selected (reader, mask, set);
1961 static void
1962 action_mail_zoom_100_cb (GtkAction *action,
1963 EMailReader *reader)
1965 EMailDisplay *display;
1967 display = e_mail_reader_get_mail_display (reader);
1969 e_web_view_zoom_100 (E_WEB_VIEW (display));
1972 static void
1973 action_mail_zoom_in_cb (GtkAction *action,
1974 EMailReader *reader)
1976 EMailDisplay *display;
1978 display = e_mail_reader_get_mail_display (reader);
1980 e_web_view_zoom_in (E_WEB_VIEW (display));
1983 static void
1984 action_mail_zoom_out_cb (GtkAction *action,
1985 EMailReader *reader)
1987 EMailDisplay *display;
1989 display = e_mail_reader_get_mail_display (reader);
1991 e_web_view_zoom_out (E_WEB_VIEW (display));
1994 static void
1995 action_search_folder_recipient_cb (GtkAction *action,
1996 EMailReader *reader)
1998 EMailBackend *backend;
1999 EMailSession *session;
2000 EWebView *web_view;
2001 CamelURL *curl;
2002 const gchar *uri;
2004 /* This action is defined in EMailDisplay. */
2006 web_view = E_WEB_VIEW (e_mail_reader_get_mail_display (reader));
2008 uri = e_web_view_get_selected_uri (web_view);
2009 g_return_if_fail (uri != NULL);
2011 curl = camel_url_new (uri, NULL);
2012 g_return_if_fail (curl != NULL);
2014 backend = e_mail_reader_get_backend (reader);
2015 session = e_mail_backend_get_session (backend);
2017 if (curl->path != NULL && *curl->path != '\0') {
2018 CamelFolder *folder;
2019 CamelInternetAddress *inet_addr;
2021 folder = e_mail_reader_ref_folder (reader);
2023 inet_addr = camel_internet_address_new ();
2024 camel_address_decode (CAMEL_ADDRESS (inet_addr), curl->path);
2025 vfolder_gui_add_from_address (
2026 session, inet_addr, AUTO_TO, folder);
2027 g_object_unref (inet_addr);
2029 g_clear_object (&folder);
2032 camel_url_free (curl);
2035 static void
2036 action_search_folder_sender_cb (GtkAction *action,
2037 EMailReader *reader)
2039 EMailBackend *backend;
2040 EMailSession *session;
2041 EWebView *web_view;
2042 CamelURL *curl;
2043 const gchar *uri;
2045 /* This action is defined in EMailDisplay. */
2047 web_view = E_WEB_VIEW (e_mail_reader_get_mail_display (reader));
2049 uri = e_web_view_get_selected_uri (web_view);
2050 g_return_if_fail (uri != NULL);
2052 curl = camel_url_new (uri, NULL);
2053 g_return_if_fail (curl != NULL);
2055 backend = e_mail_reader_get_backend (reader);
2056 session = e_mail_backend_get_session (backend);
2058 if (curl->path != NULL && *curl->path != '\0') {
2059 CamelFolder *folder;
2060 CamelInternetAddress *inet_addr;
2062 folder = e_mail_reader_ref_folder (reader);
2064 inet_addr = camel_internet_address_new ();
2065 camel_address_decode (CAMEL_ADDRESS (inet_addr), curl->path);
2066 vfolder_gui_add_from_address (
2067 session, inet_addr, AUTO_FROM, folder);
2068 g_object_unref (inet_addr);
2070 g_clear_object (&folder);
2073 camel_url_free (curl);
2076 static GtkActionEntry mail_reader_entries[] = {
2078 { "mail-add-sender",
2079 NULL,
2080 N_("A_dd Sender to Address Book"),
2081 NULL,
2082 N_("Add sender to address book"),
2083 G_CALLBACK (action_mail_add_sender_cb) },
2085 { "mail-archive",
2086 "mail-archive",
2087 N_("_Archive..."),
2088 "<Alt><Control>a",
2089 N_("Move selected messages to the Archive folder for the account"),
2090 G_CALLBACK (action_mail_archive_cb) },
2092 { "mail-check-for-junk",
2093 "mail-mark-junk",
2094 N_("Check for _Junk"),
2095 "<Control><Alt>j",
2096 N_("Filter the selected messages for junk status"),
2097 G_CALLBACK (action_mail_check_for_junk_cb) },
2099 { "mail-copy",
2100 "mail-copy",
2101 N_("_Copy to Folder..."),
2102 "<Shift><Control>y",
2103 N_("Copy selected messages to another folder"),
2104 G_CALLBACK (action_mail_copy_cb) },
2106 { "mail-delete",
2107 "user-trash",
2108 N_("_Delete Message"),
2109 "<Control>d",
2110 N_("Mark the selected messages for deletion"),
2111 G_CALLBACK (action_mail_delete_cb) },
2113 { "mail-add-note",
2114 "evolution-memos",
2115 N_("_Add note..."),
2116 NULL,
2117 N_("Add a note for the selected message"),
2118 G_CALLBACK (action_mail_edit_note_cb) },
2120 { "mail-delete-note",
2121 NULL,
2122 N_("Delete no_te"),
2123 NULL,
2124 N_("Delete the note for the selected message"),
2125 G_CALLBACK (action_mail_delete_note_cb) },
2127 { "mail-edit-note",
2128 "evolution-memos",
2129 N_("_Edit note..."),
2130 NULL,
2131 N_("Edit a note for the selected message"),
2132 G_CALLBACK (action_mail_edit_note_cb) },
2134 { "mail-filter-rule-for-mailing-list",
2135 NULL,
2136 N_("Create a Filter Rule for Mailing _List..."),
2137 NULL,
2138 N_("Create a rule to filter messages to this mailing list"),
2139 G_CALLBACK (action_mail_filter_on_mailing_list_cb) },
2141 { "mail-filter-rule-for-recipients",
2142 NULL,
2143 N_("Create a Filter Rule for _Recipients..."),
2144 NULL,
2145 N_("Create a rule to filter messages to these recipients"),
2146 G_CALLBACK (action_mail_filter_on_recipients_cb) },
2148 { "mail-filter-rule-for-sender",
2149 NULL,
2150 N_("Create a Filter Rule for Se_nder..."),
2151 NULL,
2152 N_("Create a rule to filter messages from this sender"),
2153 G_CALLBACK (action_mail_filter_on_sender_cb) },
2155 { "mail-filter-rule-for-subject",
2156 NULL,
2157 N_("Create a Filter Rule for _Subject..."),
2158 NULL,
2159 N_("Create a rule to filter messages with this subject"),
2160 G_CALLBACK (action_mail_filter_on_subject_cb) },
2162 { "mail-filters-apply",
2163 "stock_mail-filters-apply",
2164 N_("A_pply Filters"),
2165 "<Control>y",
2166 N_("Apply filter rules to the selected messages"),
2167 G_CALLBACK (action_mail_filters_apply_cb) },
2169 { "mail-find",
2170 "edit-find",
2171 N_("_Find in Message..."),
2172 "<Shift><Control>f",
2173 N_("Search for text in the body of the displayed message"),
2174 G_CALLBACK (action_mail_find_cb) },
2176 { "mail-flag-clear",
2177 NULL,
2178 N_("_Clear Flag"),
2179 NULL,
2180 N_("Remove the follow-up flag from the selected messages"),
2181 G_CALLBACK (action_mail_flag_clear_cb) },
2183 { "mail-flag-completed",
2184 NULL,
2185 N_("_Flag Completed"),
2186 NULL,
2187 N_("Set the follow-up flag to completed on the selected messages"),
2188 G_CALLBACK (action_mail_flag_completed_cb) },
2190 { "mail-flag-for-followup",
2191 "stock_mail-flag-for-followup",
2192 N_("Follow _Up..."),
2193 "<Shift><Control>g",
2194 N_("Flag the selected messages for follow-up"),
2195 G_CALLBACK (action_mail_flag_for_followup_cb) },
2197 { "mail-forward-attached",
2198 NULL,
2199 N_("_Attached"),
2200 NULL,
2201 N_("Forward the selected message to someone as an attachment"),
2202 G_CALLBACK (action_mail_forward_attached_cb) },
2204 { "mail-forward-attached-full",
2205 NULL,
2206 N_("Forward As _Attached"),
2207 NULL,
2208 N_("Forward the selected message to someone as an attachment"),
2209 G_CALLBACK (action_mail_forward_attached_cb) },
2211 { "mail-forward-inline",
2212 NULL,
2213 N_("_Inline"),
2214 NULL,
2215 N_("Forward the selected message in the body of a new message"),
2216 G_CALLBACK (action_mail_forward_inline_cb) },
2218 { "mail-forward-inline-full",
2219 NULL,
2220 N_("Forward As _Inline"),
2221 NULL,
2222 N_("Forward the selected message in the body of a new message"),
2223 G_CALLBACK (action_mail_forward_inline_cb) },
2225 { "mail-forward-quoted",
2226 NULL,
2227 N_("_Quoted"),
2228 NULL,
2229 N_("Forward the selected message quoted like a reply"),
2230 G_CALLBACK (action_mail_forward_quoted_cb) },
2232 { "mail-forward-quoted-full",
2233 NULL,
2234 N_("Forward As _Quoted"),
2235 NULL,
2236 N_("Forward the selected message quoted like a reply"),
2237 G_CALLBACK (action_mail_forward_quoted_cb) },
2239 { "mail-load-images",
2240 "image-x-generic",
2241 N_("_Load Images"),
2242 "<Control>i",
2243 N_("Force images in HTML mail to be loaded"),
2244 G_CALLBACK (action_mail_load_images_cb) },
2246 { "mail-mark-ignore-thread-sub",
2247 NULL,
2248 N_("_Ignore Subthread"),
2249 NULL,
2250 N_("Mark new mails in a subthread as read automatically"),
2251 G_CALLBACK (action_mail_mark_ignore_thread_sub_cb) },
2253 { "mail-mark-ignore-thread-whole",
2254 NULL,
2255 N_("_Ignore Thread"),
2256 NULL,
2257 N_("Mark new mails in this thread as read automatically"),
2258 G_CALLBACK (action_mail_mark_ignore_thread_whole_cb) },
2260 { "mail-mark-important",
2261 "mail-mark-important",
2262 N_("_Important"),
2263 NULL,
2264 N_("Mark the selected messages as important"),
2265 G_CALLBACK (action_mail_mark_important_cb) },
2267 { "mail-mark-junk",
2268 "mail-mark-junk",
2269 N_("_Junk"),
2270 "<Control>j",
2271 N_("Mark the selected messages as junk"),
2272 G_CALLBACK (action_mail_mark_junk_cb) },
2274 { "mail-mark-notjunk",
2275 "mail-mark-notjunk",
2276 N_("_Not Junk"),
2277 "<Shift><Control>j",
2278 N_("Mark the selected messages as not being junk"),
2279 G_CALLBACK (action_mail_mark_notjunk_cb) },
2281 { "mail-mark-read",
2282 "mail-mark-read",
2283 N_("_Read"),
2284 "<Control>k",
2285 N_("Mark the selected messages as having been read"),
2286 G_CALLBACK (action_mail_mark_read_cb) },
2288 { "mail-mark-unignore-thread-sub",
2289 NULL,
2290 N_("Do not _Ignore Subthread"),
2291 NULL,
2292 N_("Do not mark new mails in a subthread as read automatically"),
2293 G_CALLBACK (action_mail_mark_unignore_thread_sub_cb) },
2295 { "mail-mark-unignore-thread-whole",
2296 NULL,
2297 N_("Do not _Ignore Thread"),
2298 NULL,
2299 N_("Do not mark new mails in this thread as read automatically"),
2300 G_CALLBACK (action_mail_mark_unignore_thread_whole_cb) },
2302 { "mail-mark-unimportant",
2303 NULL,
2304 N_("Uni_mportant"),
2305 NULL,
2306 N_("Mark the selected messages as unimportant"),
2307 G_CALLBACK (action_mail_mark_unimportant_cb) },
2309 { "mail-mark-unread",
2310 "mail-mark-unread",
2311 N_("_Unread"),
2312 "<Shift><Control>k",
2313 N_("Mark the selected messages as not having been read"),
2314 G_CALLBACK (action_mail_mark_unread_cb) },
2316 { "mail-message-edit",
2317 NULL,
2318 N_("_Edit as New Message..."),
2319 NULL,
2320 N_("Open the selected messages in the composer for editing"),
2321 G_CALLBACK (action_mail_message_edit_cb) },
2323 { "mail-message-new",
2324 "mail-message-new",
2325 N_("Compose _New Message"),
2326 "<Shift><Control>m",
2327 N_("Open a window for composing a mail message"),
2328 G_CALLBACK (action_mail_message_new_cb) },
2330 { "mail-message-open",
2331 NULL,
2332 N_("_Open in New Window"),
2333 "<Control>o",
2334 N_("Open the selected messages in a new window"),
2335 G_CALLBACK (action_mail_message_open_cb) },
2337 { "mail-move",
2338 "mail-move",
2339 N_("_Move to Folder..."),
2340 "<Shift><Control>v",
2341 N_("Move selected messages to another folder"),
2342 G_CALLBACK (action_mail_move_cb) },
2344 { "mail-next",
2345 "go-next",
2346 N_("_Next Message"),
2347 "<Control>Page_Down",
2348 N_("Display the next message"),
2349 G_CALLBACK (action_mail_next_cb) },
2351 { "mail-next-important",
2352 NULL,
2353 N_("Next _Important Message"),
2354 NULL,
2355 N_("Display the next important message"),
2356 G_CALLBACK (action_mail_next_important_cb) },
2358 { "mail-next-thread",
2359 NULL,
2360 N_("Next _Thread"),
2361 NULL,
2362 N_("Display the next thread"),
2363 G_CALLBACK (action_mail_next_thread_cb) },
2365 { "mail-next-unread",
2366 "go-jump",
2367 N_("Next _Unread Message"),
2368 "<Control>bracketright",
2369 N_("Display the next unread message"),
2370 G_CALLBACK (action_mail_next_unread_cb) },
2372 { "mail-previous",
2373 "go-previous",
2374 N_("_Previous Message"),
2375 "<Control>Page_Up",
2376 N_("Display the previous message"),
2377 G_CALLBACK (action_mail_previous_cb) },
2379 { "mail-previous-important",
2380 NULL,
2381 N_("Pr_evious Important Message"),
2382 NULL,
2383 N_("Display the previous important message"),
2384 G_CALLBACK (action_mail_previous_important_cb) },
2386 { "mail-previous-thread",
2387 NULL,
2388 N_("Previous T_hread"),
2389 NULL,
2390 N_("Display the previous thread"),
2391 G_CALLBACK (action_mail_previous_thread_cb) },
2393 { "mail-previous-unread",
2394 NULL,
2395 N_("P_revious Unread Message"),
2396 "<Control>bracketleft",
2397 N_("Display the previous unread message"),
2398 G_CALLBACK (action_mail_previous_unread_cb) },
2400 { "mail-print",
2401 "document-print",
2402 N_("_Print..."),
2403 "<Control>p",
2404 N_("Print this message"),
2405 G_CALLBACK (action_mail_print_cb) },
2407 { "mail-print-preview",
2408 "document-print-preview",
2409 N_("Pre_view..."),
2410 NULL,
2411 N_("Preview the message to be printed"),
2412 G_CALLBACK (action_mail_print_preview_cb) },
2414 { "mail-redirect",
2415 NULL,
2416 N_("Re_direct"),
2417 NULL,
2418 N_("Redirect (bounce) the selected message to someone"),
2419 G_CALLBACK (action_mail_redirect_cb) },
2421 { "mail-remove-attachments",
2422 "edit-delete",
2423 N_("Remo_ve Attachments"),
2424 NULL,
2425 N_("Remove attachments"),
2426 G_CALLBACK (action_mail_remove_attachments_cb) },
2428 { "mail-remove-duplicates",
2429 NULL,
2430 N_("Remove Du_plicate Messages"),
2431 NULL,
2432 N_("Checks selected messages for duplicates"),
2433 G_CALLBACK (action_mail_remove_duplicates_cb) },
2435 { "mail-reply-all",
2436 NULL,
2437 N_("Reply to _All"),
2438 "<Shift><Control>r",
2439 N_("Compose a reply to all the recipients of the selected message"),
2440 G_CALLBACK (action_mail_reply_all_cb) },
2442 { "mail-reply-list",
2443 NULL,
2444 N_("Reply to _List"),
2445 "<Control>l",
2446 N_("Compose a reply to the mailing list of the selected message"),
2447 G_CALLBACK (action_mail_reply_list_cb) },
2449 { "mail-reply-sender",
2450 "mail-reply-sender",
2451 N_("_Reply to Sender"),
2452 "<Control>r",
2453 N_("Compose a reply to the sender of the selected message"),
2454 G_CALLBACK (action_mail_reply_sender_cb) },
2456 { "mail-save-as",
2457 "document-save-as",
2458 N_("_Save as mbox..."),
2459 "<Control>s",
2460 N_("Save selected messages as an mbox file"),
2461 G_CALLBACK (action_mail_save_as_cb) },
2463 { "mail-show-source",
2464 NULL,
2465 N_("_Message Source"),
2466 "<Control>u",
2467 N_("Show the raw email source of the message"),
2468 G_CALLBACK (action_mail_show_source_cb) },
2470 { "mail-toggle-important",
2471 NULL,
2472 NULL, /* No menu item; key press only */
2473 NULL,
2474 NULL,
2475 G_CALLBACK (action_mail_toggle_important_cb) },
2477 { "mail-undelete",
2478 NULL,
2479 N_("_Undelete Message"),
2480 "<Shift><Control>d",
2481 N_("Undelete the selected messages"),
2482 G_CALLBACK (action_mail_undelete_cb) },
2484 { "mail-zoom-100",
2485 "zoom-original",
2486 N_("_Normal Size"),
2487 "<Control>0",
2488 N_("Reset the text to its original size"),
2489 G_CALLBACK (action_mail_zoom_100_cb) },
2491 { "mail-zoom-in",
2492 "zoom-in",
2493 N_("_Zoom In"),
2494 "<Control>plus",
2495 N_("Increase the text size"),
2496 G_CALLBACK (action_mail_zoom_in_cb) },
2498 { "mail-zoom-out",
2499 "zoom-out",
2500 N_("Zoom _Out"),
2501 "<Control>minus",
2502 N_("Decrease the text size"),
2503 G_CALLBACK (action_mail_zoom_out_cb) },
2505 /*** Menus ***/
2507 { "mail-create-menu",
2508 NULL,
2509 N_("Cre_ate"),
2510 NULL,
2511 NULL,
2512 NULL },
2514 { "mail-encoding-menu",
2515 NULL,
2516 N_("Ch_aracter Encoding"),
2517 NULL,
2518 NULL,
2519 NULL },
2521 { "mail-forward-as-menu",
2522 NULL,
2523 N_("F_orward As"),
2524 NULL,
2525 NULL,
2526 NULL },
2528 { "mail-reply-group-menu",
2529 NULL,
2530 N_("_Group Reply"),
2531 NULL,
2532 NULL,
2533 NULL },
2535 { "mail-goto-menu",
2536 NULL,
2537 N_("_Go To"),
2538 NULL,
2539 NULL,
2540 NULL },
2542 { "mail-mark-as-menu",
2543 NULL,
2544 N_("Mar_k As"),
2545 NULL,
2546 NULL,
2547 NULL },
2549 { "mail-message-menu",
2550 NULL,
2551 N_("_Message"),
2552 NULL,
2553 NULL,
2554 NULL },
2556 { "mail-zoom-menu",
2557 NULL,
2558 N_("_Zoom"),
2559 NULL,
2560 NULL,
2561 NULL }
2564 static GtkActionEntry mail_reader_search_folder_entries[] = {
2566 { "mail-search-folder-from-mailing-list",
2567 NULL,
2568 N_("Create a Search Folder from Mailing _List..."),
2569 NULL,
2570 N_("Create a search folder for this mailing list"),
2571 G_CALLBACK (action_mail_search_folder_from_mailing_list_cb) },
2573 { "mail-search-folder-from-recipients",
2574 NULL,
2575 N_("Create a Search Folder from Recipien_ts..."),
2576 NULL,
2577 N_("Create a search folder for these recipients"),
2578 G_CALLBACK (action_mail_search_folder_from_recipients_cb) },
2580 { "mail-search-folder-from-sender",
2581 NULL,
2582 N_("Create a Search Folder from Sen_der..."),
2583 NULL,
2584 N_("Create a search folder for this sender"),
2585 G_CALLBACK (action_mail_search_folder_from_sender_cb) },
2587 { "mail-search-folder-from-subject",
2588 NULL,
2589 N_("Create a Search Folder from S_ubject..."),
2590 NULL,
2591 N_("Create a search folder for this subject"),
2592 G_CALLBACK (action_mail_search_folder_from_subject_cb) },
2595 static EPopupActionEntry mail_reader_popup_entries[] = {
2597 { "mail-popup-archive",
2598 NULL,
2599 "mail-archive" },
2601 { "mail-popup-copy",
2602 NULL,
2603 "mail-copy" },
2605 { "mail-popup-delete",
2606 NULL,
2607 "mail-delete" },
2609 { "mail-popup-add-note",
2610 NULL,
2611 "mail-add-note" },
2613 { "mail-popup-delete-note",
2614 NULL,
2615 "mail-delete-note" },
2617 { "mail-popup-edit-note",
2618 NULL,
2619 "mail-edit-note" },
2621 { "mail-popup-flag-clear",
2622 NULL,
2623 "mail-flag-clear" },
2625 { "mail-popup-flag-completed",
2626 NULL,
2627 "mail-flag-completed" },
2629 { "mail-popup-flag-for-followup",
2630 N_("Mark for Follo_w Up..."),
2631 "mail-flag-for-followup" },
2633 { "mail-popup-forward",
2634 NULL,
2635 "mail-forward" },
2637 { "mail-popup-mark-ignore-thread-sub",
2638 N_("_Ignore Subthread"),
2639 "mail-mark-ignore-thread-sub" },
2641 { "mail-popup-mark-ignore-thread-whole",
2642 N_("_Ignore Thread"),
2643 "mail-mark-ignore-thread-whole" },
2645 { "mail-popup-mark-important",
2646 N_("Mark as _Important"),
2647 "mail-mark-important" },
2649 { "mail-popup-mark-junk",
2650 N_("Mark as _Junk"),
2651 "mail-mark-junk" },
2653 { "mail-popup-mark-notjunk",
2654 N_("Mark as _Not Junk"),
2655 "mail-mark-notjunk" },
2657 { "mail-popup-mark-read",
2658 N_("Mar_k as Read"),
2659 "mail-mark-read" },
2661 { "mail-popup-mark-unignore-thread-sub",
2662 N_("Do not _Ignore Subthread"),
2663 "mail-mark-unignore-thread-sub" },
2665 { "mail-popup-mark-unignore-thread-whole",
2666 N_("Do not _Ignore Thread"),
2667 "mail-mark-unignore-thread-whole" },
2669 { "mail-popup-mark-unimportant",
2670 N_("Mark as Uni_mportant"),
2671 "mail-mark-unimportant" },
2673 { "mail-popup-mark-unread",
2674 N_("Mark as _Unread"),
2675 "mail-mark-unread" },
2677 { "mail-popup-message-edit",
2678 NULL,
2679 "mail-message-edit" },
2681 { "mail-popup-move",
2682 NULL,
2683 "mail-move" },
2685 { "mail-popup-print",
2686 NULL,
2687 "mail-print" },
2689 { "mail-popup-remove-attachments",
2690 NULL,
2691 "mail-remove-attachments" },
2693 { "mail-popup-remove-duplicates",
2694 NULL,
2695 "mail-remove-duplicates" },
2697 { "mail-popup-reply-all",
2698 NULL,
2699 "mail-reply-all" },
2701 { "mail-popup-reply-sender",
2702 NULL,
2703 "mail-reply-sender" },
2705 { "mail-popup-save-as",
2706 NULL,
2707 "mail-save-as" },
2709 { "mail-popup-undelete",
2710 NULL,
2711 "mail-undelete" }
2714 static GtkToggleActionEntry mail_reader_toggle_entries[] = {
2716 { "mail-caret-mode",
2717 NULL,
2718 N_("_Caret Mode"),
2719 "F7",
2720 N_("Show a blinking cursor in the body of displayed messages"),
2721 NULL, /* No callback required */
2722 FALSE },
2724 { "mail-show-all-headers",
2725 NULL,
2726 N_("All Message _Headers"),
2727 NULL,
2728 N_("Show messages with all email headers"),
2729 G_CALLBACK (action_mail_show_all_headers_cb),
2730 FALSE }
2733 static void
2734 mail_reader_double_click_cb (EMailReader *reader,
2735 gint row,
2736 ETreePath path,
2737 gint col,
2738 GdkEvent *event)
2740 GtkAction *action;
2742 /* Ignore double clicks on columns that handle their own state. */
2743 if (MESSAGE_LIST_COLUMN_IS_ACTIVE (col))
2744 return;
2746 action = e_mail_reader_get_action (reader, "mail-message-open");
2747 gtk_action_activate (action);
2750 static gboolean
2751 mail_reader_key_press_event_cb (EMailReader *reader,
2752 GdkEventKey *event)
2754 GtkAction *action;
2755 const gchar *action_name;
2757 if (!gtk_widget_has_focus (GTK_WIDGET (reader))) {
2758 EMailDisplay *display;
2760 display = e_mail_reader_get_mail_display (reader);
2761 if (e_web_view_get_need_input (E_WEB_VIEW (display)) &&
2762 gtk_widget_has_focus (GTK_WIDGET (display)))
2763 return FALSE;
2766 if ((event->state & GDK_CONTROL_MASK) != 0)
2767 goto ctrl;
2769 /* <keyval> alone */
2770 switch (event->keyval) {
2771 case GDK_KEY_Delete:
2772 case GDK_KEY_KP_Delete:
2773 action_name = "mail-delete";
2774 break;
2776 case GDK_KEY_Return:
2777 case GDK_KEY_KP_Enter:
2778 case GDK_KEY_ISO_Enter:
2779 if (E_IS_MAIL_BROWSER (reader))
2780 return FALSE;
2782 action_name = "mail-message-open";
2783 break;
2785 case GDK_KEY_period:
2786 case GDK_KEY_bracketright:
2787 action_name = "mail-next-unread";
2788 break;
2790 case GDK_KEY_comma:
2791 case GDK_KEY_bracketleft:
2792 action_name = "mail-previous-unread";
2793 break;
2795 #ifdef HAVE_XFREE
2796 case XF86XK_Reply:
2797 action_name = "mail-reply-all";
2798 break;
2800 case XF86XK_MailForward:
2801 action_name = "mail-forward";
2802 break;
2803 #endif
2805 case GDK_KEY_exclam:
2806 action_name = "mail-toggle-important";
2807 break;
2809 case GDK_KEY_ZoomIn:
2810 action_name = "mail-zoom-in";
2811 break;
2813 case GDK_KEY_ZoomOut:
2814 action_name = "mail-zoom-out";
2815 break;
2817 default:
2818 return FALSE;
2821 goto exit;
2823 ctrl:
2825 /* Ctrl + <keyval> */
2826 switch (event->keyval) {
2827 case GDK_KEY_period:
2828 action_name = "mail-next-unread";
2829 break;
2831 case GDK_KEY_comma:
2832 action_name = "mail-previous-unread";
2833 break;
2835 case GDK_KEY_equal:
2836 case GDK_KEY_KP_Add:
2837 action_name = "mail-zoom-in";
2838 break;
2840 case GDK_KEY_KP_Subtract:
2841 action_name = "mail-zoom-out";
2842 break;
2844 default:
2845 return FALSE;
2848 exit:
2849 action = e_mail_reader_get_action (reader, action_name);
2850 gtk_action_activate (action);
2852 return TRUE;
2855 static gint
2856 mail_reader_key_press_cb (EMailReader *reader,
2857 gint row,
2858 ETreePath path,
2859 gint col,
2860 GdkEvent *event)
2862 return mail_reader_key_press_event_cb (reader, &event->key);
2865 static gboolean
2866 mail_reader_message_seen_cb (gpointer user_data)
2868 EMailReaderClosure *closure = user_data;
2869 EMailReader *reader;
2870 GtkWidget *message_list;
2871 EMailPartList *parts;
2872 EMailDisplay *display;
2873 CamelMimeMessage *message;
2874 const gchar *current_uid;
2875 const gchar *message_uid;
2876 gboolean uid_is_current = TRUE;
2878 reader = closure->reader;
2879 message_uid = closure->message_uid;
2881 display = e_mail_reader_get_mail_display (reader);
2882 parts = e_mail_display_get_part_list (display);
2883 message_list = e_mail_reader_get_message_list (reader);
2885 g_return_val_if_fail (IS_MESSAGE_LIST (message_list), FALSE);
2887 /* zero the timeout id now, if it was not rescheduled */
2888 if (g_source_get_id (g_main_current_source ()) == MESSAGE_LIST (message_list)->seen_id)
2889 MESSAGE_LIST (message_list)->seen_id = 0;
2891 if (e_tree_is_dragging (E_TREE (message_list)))
2892 return FALSE;
2894 current_uid = MESSAGE_LIST (message_list)->cursor_uid;
2895 uid_is_current &= (g_strcmp0 (current_uid, message_uid) == 0);
2897 if (parts != NULL)
2898 message = e_mail_part_list_get_message (parts);
2899 else
2900 message = NULL;
2902 if (uid_is_current && message != NULL)
2903 g_signal_emit (
2904 reader, signals[MESSAGE_SEEN], 0,
2905 message_uid, message);
2907 return FALSE;
2910 static void
2911 schedule_timeout_mark_seen (EMailReader *reader)
2913 EMailReaderPrivate *priv;
2914 MessageList *message_list;
2916 g_return_if_fail (E_IS_MAIL_READER (reader));
2918 priv = E_MAIL_READER_GET_PRIVATE (reader);
2920 message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
2921 g_return_if_fail (message_list != NULL);
2923 if (message_list->cursor_uid) {
2924 EMailReaderClosure *timeout_closure;
2926 if (message_list->seen_id > 0) {
2927 g_source_remove (message_list->seen_id);
2928 message_list->seen_id = 0;
2931 timeout_closure = g_slice_new0 (EMailReaderClosure);
2932 timeout_closure->reader = g_object_ref (reader);
2933 timeout_closure->message_uid = g_strdup (message_list->cursor_uid);
2935 MESSAGE_LIST (message_list)->seen_id =
2936 e_named_timeout_add_full (
2937 G_PRIORITY_DEFAULT, priv->schedule_mark_seen_interval,
2938 mail_reader_message_seen_cb,
2939 timeout_closure, (GDestroyNotify)
2940 mail_reader_closure_free);
2944 static void
2945 mail_reader_load_changed_cb (EMailReader *reader,
2946 WebKitLoadEvent event,
2947 EMailDisplay *display)
2949 EMailReaderPrivate *priv;
2951 if (event != WEBKIT_LOAD_FINISHED)
2952 return;
2954 priv = E_MAIL_READER_GET_PRIVATE (reader);
2955 if (priv->schedule_mark_seen &&
2956 E_IS_MAIL_VIEW (reader) &&
2957 e_mail_display_get_part_list (display) &&
2958 e_mail_view_get_preview_visible (E_MAIL_VIEW (reader))) {
2959 if (priv->folder_was_just_selected)
2960 priv->folder_was_just_selected = FALSE;
2961 else
2962 schedule_timeout_mark_seen (reader);
2966 static gboolean
2967 maybe_schedule_timeout_mark_seen (EMailReader *reader)
2969 EMailReaderPrivate *priv;
2970 MessageList *message_list;
2971 GSettings *settings;
2972 gboolean schedule_timeout;
2973 gint timeout_interval;
2974 const gchar *message_uid;
2976 message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
2978 message_uid = message_list->cursor_uid;
2979 if (message_uid == NULL ||
2980 e_tree_is_dragging (E_TREE (message_list)))
2981 return FALSE;
2983 settings = e_util_ref_settings ("org.gnome.evolution.mail");
2985 /* FIXME These should be EMailReader properties. */
2986 schedule_timeout =
2987 (message_uid != NULL) &&
2988 g_settings_get_boolean (settings, "mark-seen");
2989 timeout_interval = g_settings_get_int (settings, "mark-seen-timeout");
2991 g_object_unref (settings);
2993 if (message_list->seen_id > 0) {
2994 g_source_remove (message_list->seen_id);
2995 message_list->seen_id = 0;
2998 priv = E_MAIL_READER_GET_PRIVATE (reader);
2999 priv->schedule_mark_seen = schedule_timeout;
3000 priv->schedule_mark_seen_interval = timeout_interval;
3002 return schedule_timeout;
3005 static gboolean
3006 discard_timeout_mark_seen_cb (EMailReader *reader)
3008 EMailReaderPrivate *priv;
3009 MessageList *message_list;
3011 g_return_val_if_fail (reader != NULL, FALSE);
3013 priv = E_MAIL_READER_GET_PRIVATE (reader);
3014 priv->schedule_mark_seen = FALSE;
3016 message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
3017 g_return_val_if_fail (message_list != NULL, FALSE);
3019 if (message_list->seen_id > 0) {
3020 g_source_remove (message_list->seen_id);
3021 message_list->seen_id = 0;
3024 return FALSE;
3028 static void
3029 mail_reader_preview_pane_visible_changed_cb (EMailReader *reader,
3030 GParamSpec *param,
3031 GtkWidget *widget)
3033 g_return_if_fail (E_IS_MAIL_READER (reader));
3034 g_return_if_fail (GTK_IS_WIDGET (widget));
3036 if (!gtk_widget_get_visible (widget))
3037 discard_timeout_mark_seen_cb (reader);
3040 static void
3041 mail_reader_remove_followup_alert (EMailReader *reader)
3043 EMailReaderPrivate *priv;
3045 g_return_if_fail (E_IS_MAIL_READER (reader));
3047 priv = E_MAIL_READER_GET_PRIVATE (reader);
3048 if (!priv)
3049 return;
3051 if (priv->followup_alert)
3052 e_alert_response (priv->followup_alert, GTK_RESPONSE_OK);
3055 static void
3056 mail_reader_manage_followup_flag (EMailReader *reader,
3057 CamelFolder *folder,
3058 const gchar *message_uid)
3060 EMailReaderPrivate *priv;
3061 CamelMessageInfo *info;
3062 const gchar *followup, *completed_on, *due_by;
3063 time_t date;
3064 gchar *date_str = NULL;
3065 gboolean alert_added = FALSE;
3067 g_return_if_fail (E_IS_MAIL_READER (reader));
3068 g_return_if_fail (CAMEL_IS_FOLDER (folder));
3069 g_return_if_fail (message_uid != NULL);
3071 priv = E_MAIL_READER_GET_PRIVATE (reader);
3072 if (!priv)
3073 return;
3075 info = camel_folder_get_message_info (folder, message_uid);
3076 if (!info)
3077 return;
3079 followup = camel_message_info_get_user_tag (info, "follow-up");
3080 if (followup && *followup) {
3081 EPreviewPane *preview_pane;
3082 const gchar *alert_tag;
3083 EAlert *alert;
3085 completed_on = camel_message_info_get_user_tag (info, "completed-on");
3086 due_by = camel_message_info_get_user_tag (info, "due-by");
3088 if (completed_on && *completed_on) {
3089 alert_tag = "mail:follow-up-completed-info";
3090 date = camel_header_decode_date (completed_on, NULL);
3091 date_str = e_datetime_format_format ("mail", "header", DTFormatKindDateTime, date);
3092 } else if (due_by && *due_by) {
3093 time_t now;
3095 alert_tag = "mail:follow-up-dueby-info";
3096 date = camel_header_decode_date (due_by, NULL);
3097 date_str = e_datetime_format_format ("mail", "header", DTFormatKindDateTime, date);
3099 now = time (NULL);
3100 if (now > date)
3101 alert_tag = "mail:follow-up-overdue-error";
3102 } else {
3103 alert_tag = "mail:follow-up-flag-info";
3106 alert = e_alert_new (alert_tag, followup, date_str ? date_str : "???", NULL);
3108 g_free (date_str);
3110 preview_pane = e_mail_reader_get_preview_pane (reader);
3111 e_alert_sink_submit_alert (E_ALERT_SINK (preview_pane), alert);
3113 alert_added = TRUE;
3115 mail_reader_remove_followup_alert (reader);
3116 priv->followup_alert = alert;
3117 g_object_add_weak_pointer (G_OBJECT (priv->followup_alert), &priv->followup_alert);
3119 g_object_unref (alert);
3122 g_clear_object (&info);
3124 if (!alert_added)
3125 mail_reader_remove_followup_alert (reader);
3128 static void
3129 mail_reader_message_loaded_cb (CamelFolder *folder,
3130 GAsyncResult *result,
3131 EMailReaderClosure *closure)
3133 EMailReader *reader;
3134 EMailReaderPrivate *priv;
3135 CamelMimeMessage *message = NULL;
3136 GtkWidget *message_list;
3137 const gchar *message_uid;
3138 GError *error = NULL;
3140 reader = closure->reader;
3141 message_uid = closure->message_uid;
3143 priv = E_MAIL_READER_GET_PRIVATE (reader);
3145 /* If the private struct is NULL, the EMailReader was destroyed
3146 * while we were loading the message and we're likely holding the
3147 * last reference. Nothing to do but drop the reference.
3148 * FIXME Use a GWeakRef instead of this hack. */
3149 if (priv == NULL) {
3150 mail_reader_closure_free (closure);
3151 return;
3154 message = camel_folder_get_message_finish (folder, result, &error);
3156 /* If the user picked a different message in the time it took
3157 * to fetch this message, then don't bother rendering it. */
3158 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
3159 g_clear_error (&error);
3160 goto exit;
3163 message_list = e_mail_reader_get_message_list (reader);
3165 if (message_list == NULL) {
3166 /* For cases where message fetching took so long that
3167 * user closed the message window before this was called. */
3168 goto exit;
3171 if (message != NULL) {
3172 mail_reader_manage_followup_flag (reader, folder, message_uid);
3174 g_signal_emit (
3175 reader, signals[MESSAGE_LOADED], 0,
3176 message_uid, message);
3179 exit:
3180 if (error != NULL) {
3181 EPreviewPane *preview_pane;
3182 EWebView *web_view;
3184 preview_pane = e_mail_reader_get_preview_pane (reader);
3185 web_view = e_preview_pane_get_web_view (preview_pane);
3187 if (g_error_matches (error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_UNAVAILABLE) &&
3188 CAMEL_IS_OFFLINE_FOLDER (folder) &&
3189 camel_service_get_connection_status (CAMEL_SERVICE (camel_folder_get_parent_store (folder))) != CAMEL_SERVICE_CONNECTED)
3190 e_alert_submit (
3191 E_ALERT_SINK (web_view),
3192 "mail:no-retrieve-message-offline",
3193 NULL);
3194 else
3195 e_alert_submit (
3196 E_ALERT_SINK (web_view),
3197 "mail:no-retrieve-message",
3198 error->message, NULL);
3201 g_clear_error (&error);
3203 mail_reader_closure_free (closure);
3205 g_clear_object (&message);
3208 static gboolean
3209 mail_reader_message_selected_timeout_cb (gpointer user_data)
3211 EMailReader *reader;
3212 EMailReaderPrivate *priv;
3213 EMailDisplay *display;
3214 GtkWidget *message_list;
3215 const gchar *cursor_uid;
3216 const gchar *format_uid;
3217 EMailPartList *parts;
3219 reader = E_MAIL_READER (user_data);
3220 priv = E_MAIL_READER_GET_PRIVATE (reader);
3222 message_list = e_mail_reader_get_message_list (reader);
3223 display = e_mail_reader_get_mail_display (reader);
3224 parts = e_mail_display_get_part_list (display);
3226 cursor_uid = MESSAGE_LIST (message_list)->cursor_uid;
3227 if (parts != NULL)
3228 format_uid = e_mail_part_list_get_message_uid (parts);
3229 else
3230 format_uid = NULL;
3232 if (MESSAGE_LIST (message_list)->last_sel_single) {
3233 GtkWidget *widget;
3234 gboolean display_visible;
3235 gboolean selected_uid_changed;
3237 /* Decide whether to download the full message now. */
3238 widget = GTK_WIDGET (display);
3239 display_visible = gtk_widget_get_mapped (widget);
3241 selected_uid_changed = (g_strcmp0 (cursor_uid, format_uid) != 0);
3243 if (display_visible && selected_uid_changed) {
3244 EMailReaderClosure *closure;
3245 GCancellable *cancellable;
3246 CamelFolder *folder;
3247 EActivity *activity;
3248 gchar *string;
3250 string = g_strdup_printf (
3251 _("Retrieving message “%s”"), cursor_uid);
3252 e_mail_display_set_part_list (display, NULL);
3253 e_mail_display_set_status (display, string);
3254 g_free (string);
3256 activity = e_mail_reader_new_activity (reader);
3257 e_activity_set_text (activity, _("Retrieving message"));
3258 cancellable = e_activity_get_cancellable (activity);
3260 closure = g_slice_new0 (EMailReaderClosure);
3261 closure->activity = activity;
3262 closure->reader = g_object_ref (reader);
3263 closure->message_uid = g_strdup (cursor_uid);
3265 folder = e_mail_reader_ref_folder (reader);
3267 camel_folder_get_message (
3268 folder, cursor_uid, G_PRIORITY_DEFAULT,
3269 cancellable, (GAsyncReadyCallback)
3270 mail_reader_message_loaded_cb, closure);
3272 g_clear_object (&folder);
3274 if (priv->retrieving_message != NULL)
3275 g_object_unref (priv->retrieving_message);
3276 priv->retrieving_message = g_object_ref (cancellable);
3278 } else {
3279 e_mail_display_set_part_list (display, NULL);
3282 priv->message_selected_timeout_id = 0;
3284 return FALSE;
3287 static void
3288 mail_reader_message_selected_cb (EMailReader *reader,
3289 const gchar *message_uid)
3291 EMailReaderPrivate *priv;
3292 MessageList *message_list;
3294 priv = E_MAIL_READER_GET_PRIVATE (reader);
3296 /* Cancel the previous message retrieval activity. */
3297 g_cancellable_cancel (priv->retrieving_message);
3299 /* Cancel the message selected timer. */
3300 if (priv->message_selected_timeout_id > 0) {
3301 g_source_remove (priv->message_selected_timeout_id);
3302 priv->message_selected_timeout_id = 0;
3305 if (priv->folder_was_just_selected && message_uid) {
3306 if (priv->did_try_to_open_message)
3307 priv->folder_was_just_selected = FALSE;
3308 else
3309 priv->did_try_to_open_message = TRUE;
3312 message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
3313 if (message_list) {
3314 EMailPartList *parts;
3315 const gchar *cursor_uid, *format_uid;
3317 parts = e_mail_display_get_part_list (e_mail_reader_get_mail_display (reader));
3319 cursor_uid = MESSAGE_LIST (message_list)->cursor_uid;
3320 if (parts != NULL)
3321 format_uid = e_mail_part_list_get_message_uid (parts);
3322 else
3323 format_uid = NULL;
3325 /* It can happen when the message was loaded that quickly that
3326 it was delivered before this callback. */
3327 if (g_strcmp0 (cursor_uid, format_uid) == 0) {
3328 e_mail_reader_changed (reader);
3329 return;
3333 /* Cancel the seen timer. */
3334 if (message_list != NULL && message_list->seen_id) {
3335 g_source_remove (message_list->seen_id);
3336 message_list->seen_id = 0;
3339 if (message_list_selected_count (message_list) != 1) {
3340 EMailDisplay *display;
3342 display = e_mail_reader_get_mail_display (reader);
3343 e_mail_display_set_part_list (display, NULL);
3344 e_web_view_clear (E_WEB_VIEW (display));
3346 } else if (priv->folder_was_just_selected) {
3347 /* Skip the timeout if we're restoring the previous message
3348 * selection. The timeout is there for when we're scrolling
3349 * rapidly through the message list. */
3350 mail_reader_message_selected_timeout_cb (reader);
3352 } else {
3353 priv->message_selected_timeout_id = e_named_timeout_add (
3354 100, mail_reader_message_selected_timeout_cb, reader);
3357 e_mail_reader_changed (reader);
3360 static void
3361 mail_reader_message_cursor_change_cb (EMailReader *reader)
3363 MessageList *message_list;
3364 EMailReaderPrivate *priv;
3366 g_return_if_fail (reader != NULL);
3368 priv = E_MAIL_READER_GET_PRIVATE (reader);
3369 g_return_if_fail (priv != NULL);
3371 message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
3372 g_return_if_fail (message_list != NULL);
3374 if (message_list->seen_id == 0 &&
3375 E_IS_MAIL_VIEW (reader) &&
3376 e_mail_view_get_preview_visible (E_MAIL_VIEW (reader)) &&
3377 !priv->avoid_next_mark_as_seen)
3378 maybe_schedule_timeout_mark_seen (reader);
3381 static void
3382 mail_reader_emit_folder_loaded (EMailReader *reader)
3384 EMailReaderPrivate *priv;
3385 MessageList *message_list;
3387 priv = E_MAIL_READER_GET_PRIVATE (reader);
3388 message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
3390 if (priv && (message_list_count (message_list) <= 0 ||
3391 message_list_selected_count (message_list) <= 0))
3392 priv->avoid_next_mark_as_seen = FALSE;
3394 g_signal_emit (reader, signals[FOLDER_LOADED], 0);
3397 static void
3398 mail_reader_message_list_built_cb (MessageList *message_list,
3399 EMailReader *reader)
3401 EMailReaderPrivate *priv;
3403 priv = E_MAIL_READER_GET_PRIVATE (reader);
3404 mail_reader_emit_folder_loaded (reader);
3406 /* No cursor_uid means that there will not be emitted any
3407 "cursor-changed" and "message-selected" signal, thus
3408 unset the "just selected folder" flag */
3409 if (!message_list->cursor_uid)
3410 priv->folder_was_just_selected = FALSE;
3413 static EAlertSink *
3414 mail_reader_get_alert_sink (EMailReader *reader)
3416 EPreviewPane *preview_pane;
3418 preview_pane = e_mail_reader_get_preview_pane (reader);
3420 if (!gtk_widget_is_visible (GTK_WIDGET (preview_pane))) {
3421 GtkWindow *window;
3423 window = e_mail_reader_get_window (reader);
3425 if (E_IS_SHELL_WINDOW (window))
3426 return E_ALERT_SINK (window);
3429 return E_ALERT_SINK (preview_pane);
3432 static GPtrArray *
3433 mail_reader_get_selected_uids (EMailReader *reader)
3435 GtkWidget *message_list;
3437 message_list = e_mail_reader_get_message_list (reader);
3439 return message_list_get_selected (MESSAGE_LIST (message_list));
3442 static GPtrArray *
3443 mail_reader_get_selected_uids_with_collapsed_threads (EMailReader *reader)
3445 GtkWidget *message_list;
3447 message_list = e_mail_reader_get_message_list (reader);
3449 return message_list_get_selected_with_collapsed_threads (MESSAGE_LIST (message_list));
3452 static CamelFolder *
3453 mail_reader_ref_folder (EMailReader *reader)
3455 GtkWidget *message_list;
3457 message_list = e_mail_reader_get_message_list (reader);
3459 return message_list_ref_folder (MESSAGE_LIST (message_list));
3462 static void
3463 mail_reader_set_folder (EMailReader *reader,
3464 CamelFolder *folder)
3466 EMailReaderPrivate *priv;
3467 EMailDisplay *display;
3468 CamelFolder *previous_folder;
3469 GtkWidget *message_list;
3470 EMailBackend *backend;
3471 EShell *shell;
3472 gboolean sync_folder;
3474 priv = E_MAIL_READER_GET_PRIVATE (reader);
3476 display = e_mail_reader_get_mail_display (reader);
3477 message_list = e_mail_reader_get_message_list (reader);
3479 previous_folder = e_mail_reader_ref_folder (reader);
3481 backend = e_mail_reader_get_backend (reader);
3482 shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
3484 /* Only synchronize the real folder if we're online. */
3485 sync_folder =
3486 (previous_folder != NULL) &&
3487 (CAMEL_IS_VEE_FOLDER (previous_folder) ||
3488 e_shell_get_online (shell));
3489 if (sync_folder)
3490 mail_sync_folder (previous_folder, TRUE, NULL, NULL);
3492 /* Skip the rest if we're already viewing the folder. */
3493 if (folder != previous_folder) {
3494 e_web_view_clear (E_WEB_VIEW (display));
3496 priv->folder_was_just_selected = (folder != NULL) && !priv->mark_seen_always;
3497 priv->did_try_to_open_message = FALSE;
3499 /* This is to make sure any post-poned changes in Search
3500 * Folders will be propagated on folder selection. */
3501 if (CAMEL_IS_VEE_FOLDER (folder))
3502 mail_sync_folder (folder, FALSE, NULL, NULL);
3504 message_list_set_folder (MESSAGE_LIST (message_list), folder);
3506 mail_reader_emit_folder_loaded (reader);
3509 g_clear_object (&previous_folder);
3512 static void
3513 mail_reader_set_message (EMailReader *reader,
3514 const gchar *message_uid)
3516 GtkWidget *message_list;
3517 EMailReaderPrivate *priv;
3519 priv = E_MAIL_READER_GET_PRIVATE (reader);
3521 /* For a case when the preview panel had been disabled */
3522 priv->folder_was_just_selected = FALSE;
3524 message_list = e_mail_reader_get_message_list (reader);
3526 message_list_select_uid (
3527 MESSAGE_LIST (message_list), message_uid, FALSE);
3530 static void
3531 mail_reader_folder_loaded (EMailReader *reader)
3533 guint32 state;
3535 state = e_mail_reader_check_state (reader);
3536 e_mail_reader_update_actions (reader, state);
3539 static void
3540 set_mail_display_part_list (GObject *object,
3541 GAsyncResult *result,
3542 gpointer user_data)
3544 EMailPartList *part_list;
3545 EMailReader *reader;
3546 EMailDisplay *display;
3547 GError *local_error = NULL;
3549 reader = E_MAIL_READER (object);
3550 display = e_mail_reader_get_mail_display (reader);
3552 part_list = e_mail_reader_parse_message_finish (reader, result, &local_error);
3554 if (local_error) {
3555 g_warn_if_fail (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED));
3557 g_clear_error (&local_error);
3558 return;
3561 e_mail_display_set_part_list (display, part_list);
3562 e_mail_display_load (display, NULL);
3564 /* Remove the reference added when parts list was
3565 * created, so that only owners are EMailDisplays. */
3566 g_object_unref (part_list);
3569 static void
3570 mail_reader_set_display_formatter_for_message (EMailReader *reader,
3571 EMailDisplay *display,
3572 const gchar *message_uid,
3573 CamelMimeMessage *message,
3574 CamelFolder *folder)
3576 CamelObjectBag *registry;
3577 EMailPartList *parts;
3578 EMailReaderPrivate *priv;
3579 gchar *mail_uri;
3581 priv = E_MAIL_READER_GET_PRIVATE (reader);
3582 mail_uri = e_mail_part_build_uri (folder, message_uid, NULL, NULL);
3583 registry = e_mail_part_list_get_registry ();
3584 parts = camel_object_bag_peek (registry, mail_uri);
3585 g_free (mail_uri);
3587 if (parts == NULL) {
3588 e_mail_reader_parse_message (
3589 reader, folder, message_uid, message,
3590 priv->retrieving_message,
3591 set_mail_display_part_list, NULL);
3592 } else {
3593 e_mail_display_set_part_list (display, parts);
3594 e_mail_display_load (display, NULL);
3595 g_object_unref (parts);
3599 static void
3600 mail_reader_message_loaded (EMailReader *reader,
3601 const gchar *message_uid,
3602 CamelMimeMessage *message)
3604 EMailReaderPrivate *priv;
3605 GtkWidget *message_list;
3606 EMailBackend *backend;
3607 CamelFolder *folder;
3608 EMailDisplay *display;
3609 EShellBackend *shell_backend;
3610 EShell *shell;
3611 EMEvent *event;
3612 EMEventTargetMessage *target;
3613 GError *error = NULL;
3615 priv = E_MAIL_READER_GET_PRIVATE (reader);
3617 folder = e_mail_reader_ref_folder (reader);
3618 backend = e_mail_reader_get_backend (reader);
3619 display = e_mail_reader_get_mail_display (reader);
3620 message_list = e_mail_reader_get_message_list (reader);
3622 shell_backend = E_SHELL_BACKEND (backend);
3623 shell = e_shell_backend_get_shell (shell_backend);
3625 /** @Event: message.reading
3626 * @Title: Viewing a message
3627 * @Target: EMEventTargetMessage
3629 * message.reading is emitted whenever a user views a message.
3631 event = em_event_peek ();
3632 target = em_event_target_new_message (
3633 event, folder, message, message_uid, 0, NULL);
3634 e_event_emit (
3635 (EEvent *) event, "message.reading",
3636 (EEventTarget *) target);
3638 mail_reader_set_display_formatter_for_message (
3639 reader, display, message_uid, message, folder);
3641 /* Reset the shell view icon. */
3642 e_shell_event (shell, "mail-icon", (gpointer) "evolution-mail");
3644 if (MESSAGE_LIST (message_list)->seen_id > 0) {
3645 g_source_remove (MESSAGE_LIST (message_list)->seen_id);
3646 MESSAGE_LIST (message_list)->seen_id = 0;
3649 /* Determine whether to mark the message as read. */
3650 if (message != NULL &&
3651 !priv->avoid_next_mark_as_seen &&
3652 maybe_schedule_timeout_mark_seen (reader)) {
3653 g_clear_error (&error);
3654 } else if (error != NULL) {
3655 e_alert_submit (
3656 E_ALERT_SINK (display),
3657 "mail:no-retrieve-message",
3658 error->message, NULL);
3659 g_error_free (error);
3662 priv->avoid_next_mark_as_seen = FALSE;
3664 g_clear_object (&folder);
3667 static void
3668 mail_reader_message_seen (EMailReader *reader,
3669 const gchar *message_uid,
3670 CamelMimeMessage *message)
3672 CamelFolder *folder;
3673 guint32 mask, set;
3675 mask = CAMEL_MESSAGE_SEEN;
3676 set = CAMEL_MESSAGE_SEEN;
3678 folder = e_mail_reader_ref_folder (reader);
3679 camel_folder_set_message_flags (folder, message_uid, mask, set);
3680 g_clear_object (&folder);
3683 static void
3684 mail_reader_show_search_bar (EMailReader *reader)
3686 EPreviewPane *preview_pane;
3688 preview_pane = e_mail_reader_get_preview_pane (reader);
3689 e_preview_pane_show_search_bar (preview_pane);
3692 static void
3693 mail_reader_update_actions (EMailReader *reader,
3694 guint32 state)
3696 GtkAction *action;
3697 const gchar *action_name;
3698 gboolean sensitive;
3700 /* Be descriptive. */
3701 gboolean any_messages_selected;
3702 gboolean enable_flag_clear;
3703 gboolean enable_flag_completed;
3704 gboolean enable_flag_for_followup;
3705 gboolean have_enabled_account;
3706 gboolean multiple_messages_selected;
3707 gboolean selection_has_attachment_messages;
3708 gboolean selection_has_deleted_messages;
3709 gboolean selection_has_ignore_thread_messages;
3710 gboolean selection_has_notignore_thread_messages;
3711 gboolean selection_has_important_messages;
3712 gboolean selection_has_junk_messages;
3713 gboolean selection_has_not_junk_messages;
3714 gboolean selection_has_read_messages;
3715 gboolean selection_has_undeleted_messages;
3716 gboolean selection_has_unimportant_messages;
3717 gboolean selection_has_unread_messages;
3718 gboolean selection_has_mail_note;
3719 gboolean selection_is_mailing_list;
3720 gboolean single_message_selected;
3721 gboolean first_message_selected = FALSE;
3722 gboolean last_message_selected = FALSE;
3724 have_enabled_account =
3725 (state & E_MAIL_READER_HAVE_ENABLED_ACCOUNT);
3726 single_message_selected =
3727 (state & E_MAIL_READER_SELECTION_SINGLE);
3728 multiple_messages_selected =
3729 (state & E_MAIL_READER_SELECTION_MULTIPLE);
3730 /* FIXME Missing CAN_ADD_SENDER */
3731 enable_flag_clear =
3732 (state & E_MAIL_READER_SELECTION_FLAG_CLEAR);
3733 enable_flag_completed =
3734 (state & E_MAIL_READER_SELECTION_FLAG_COMPLETED);
3735 enable_flag_for_followup =
3736 (state & E_MAIL_READER_SELECTION_FLAG_FOLLOWUP);
3737 selection_has_attachment_messages =
3738 (state & E_MAIL_READER_SELECTION_HAS_ATTACHMENTS);
3739 selection_has_deleted_messages =
3740 (state & E_MAIL_READER_SELECTION_HAS_DELETED);
3741 selection_has_ignore_thread_messages =
3742 (state & E_MAIL_READER_SELECTION_HAS_IGNORE_THREAD);
3743 selection_has_notignore_thread_messages =
3744 (state & E_MAIL_READER_SELECTION_HAS_NOTIGNORE_THREAD);
3745 selection_has_important_messages =
3746 (state & E_MAIL_READER_SELECTION_HAS_IMPORTANT);
3747 selection_has_junk_messages =
3748 (state & E_MAIL_READER_SELECTION_HAS_JUNK);
3749 selection_has_not_junk_messages =
3750 (state & E_MAIL_READER_SELECTION_HAS_NOT_JUNK);
3751 selection_has_read_messages =
3752 (state & E_MAIL_READER_SELECTION_HAS_READ);
3753 selection_has_undeleted_messages =
3754 (state & E_MAIL_READER_SELECTION_HAS_UNDELETED);
3755 selection_has_unimportant_messages =
3756 (state & E_MAIL_READER_SELECTION_HAS_UNIMPORTANT);
3757 selection_has_unread_messages =
3758 (state & E_MAIL_READER_SELECTION_HAS_UNREAD);
3759 selection_has_mail_note =
3760 (state & E_MAIL_READER_SELECTION_HAS_MAIL_NOTE);
3761 selection_is_mailing_list =
3762 (state & E_MAIL_READER_SELECTION_IS_MAILING_LIST);
3764 any_messages_selected =
3765 (single_message_selected || multiple_messages_selected);
3767 if (any_messages_selected) {
3768 MessageList *message_list;
3769 gint row = -1, count = -1;
3770 ETreeTableAdapter *etta;
3771 ETreePath node = NULL;
3773 message_list = MESSAGE_LIST (
3774 e_mail_reader_get_message_list (reader));
3775 etta = e_tree_get_table_adapter (E_TREE (message_list));
3777 if (message_list->cursor_uid != NULL)
3778 node = g_hash_table_lookup (
3779 message_list->uid_nodemap,
3780 message_list->cursor_uid);
3782 if (node != NULL) {
3783 row = e_tree_table_adapter_row_of_node (etta, node);
3784 count = e_table_model_row_count (E_TABLE_MODEL (etta));
3787 first_message_selected = row <= 0;
3788 last_message_selected = row < 0 || row + 1 >= count;
3791 action_name = "mail-add-sender";
3792 sensitive = single_message_selected;
3793 action = e_mail_reader_get_action (reader, action_name);
3794 gtk_action_set_sensitive (action, sensitive);
3796 action_name = "mail-archive";
3797 sensitive = any_messages_selected && (state & E_MAIL_READER_FOLDER_ARCHIVE_FOLDER_SET) != 0;
3798 action = e_mail_reader_get_action (reader, action_name);
3799 gtk_action_set_sensitive (action, sensitive);
3801 action_name = "mail-check-for-junk";
3802 sensitive = any_messages_selected;
3803 action = e_mail_reader_get_action (reader, action_name);
3804 gtk_action_set_sensitive (action, sensitive);
3806 action_name = "mail-copy";
3807 sensitive = any_messages_selected;
3808 action = e_mail_reader_get_action (reader, action_name);
3809 gtk_action_set_sensitive (action, sensitive);
3811 action_name = "mail-create-menu";
3812 sensitive = single_message_selected;
3813 action = e_mail_reader_get_action (reader, action_name);
3814 gtk_action_set_sensitive (action, sensitive);
3816 /* If a single message is selected, let the user hit delete to
3817 * advance the cursor even if the message is already deleted. */
3818 action_name = "mail-delete";
3819 sensitive =
3820 (single_message_selected ||
3821 selection_has_undeleted_messages) &&
3822 (state & E_MAIL_READER_FOLDER_IS_VTRASH) == 0;
3823 action = e_mail_reader_get_action (reader, action_name);
3824 gtk_action_set_sensitive (action, sensitive);
3826 action_name = "mail-add-note";
3827 sensitive = single_message_selected && !selection_has_mail_note;
3828 action = e_mail_reader_get_action (reader, action_name);
3829 gtk_action_set_sensitive (action, sensitive);
3830 gtk_action_set_visible (action, sensitive);
3832 action_name = "mail-edit-note";
3833 sensitive = single_message_selected && selection_has_mail_note;
3834 action = e_mail_reader_get_action (reader, action_name);
3835 gtk_action_set_sensitive (action, sensitive);
3836 gtk_action_set_visible (action, sensitive);
3838 action_name = "mail-delete-note";
3839 sensitive = single_message_selected && selection_has_mail_note;
3840 action = e_mail_reader_get_action (reader, action_name);
3841 gtk_action_set_sensitive (action, sensitive);
3842 gtk_action_set_visible (action, sensitive);
3844 action_name = "mail-filters-apply";
3845 sensitive = any_messages_selected;
3846 action = e_mail_reader_get_action (reader, action_name);
3847 gtk_action_set_sensitive (action, sensitive);
3849 action_name = "mail-filter-rule-for-mailing-list";
3850 sensitive = single_message_selected && selection_is_mailing_list;
3851 action = e_mail_reader_get_action (reader, action_name);
3852 gtk_action_set_sensitive (action, sensitive);
3854 action_name = "mail-find";
3855 sensitive = single_message_selected;
3856 action = e_mail_reader_get_action (reader, action_name);
3857 gtk_action_set_sensitive (action, sensitive);
3859 action_name = "mail-flag-clear";
3860 sensitive = enable_flag_clear;
3861 action = e_mail_reader_get_action (reader, action_name);
3862 gtk_action_set_sensitive (action, sensitive);
3864 action_name = "mail-flag-completed";
3865 sensitive = enable_flag_completed;
3866 action = e_mail_reader_get_action (reader, action_name);
3867 gtk_action_set_sensitive (action, sensitive);
3869 action_name = "mail-flag-for-followup";
3870 sensitive = enable_flag_for_followup;
3871 action = e_mail_reader_get_action (reader, action_name);
3872 gtk_action_set_sensitive (action, sensitive);
3874 action_name = "mail-forward";
3875 sensitive = have_enabled_account && any_messages_selected;
3876 action = e_mail_reader_get_action (reader, action_name);
3877 gtk_action_set_sensitive (action, sensitive);
3879 action_name = "mail-forward-attached";
3880 sensitive = have_enabled_account && any_messages_selected;
3881 action = e_mail_reader_get_action (reader, action_name);
3882 gtk_action_set_sensitive (action, sensitive);
3884 action_name = "mail-forward-attached-full";
3885 sensitive = have_enabled_account && any_messages_selected;
3886 action = e_mail_reader_get_action (reader, action_name);
3887 gtk_action_set_sensitive (action, sensitive);
3889 action_name = "mail-forward-as-menu";
3890 sensitive = have_enabled_account && any_messages_selected;
3891 action = e_mail_reader_get_action (reader, action_name);
3892 gtk_action_set_sensitive (action, sensitive);
3894 action_name = "mail-forward-inline";
3895 sensitive = have_enabled_account && single_message_selected;
3896 action = e_mail_reader_get_action (reader, action_name);
3897 gtk_action_set_sensitive (action, sensitive);
3899 action_name = "mail-forward-inline-full";
3900 sensitive = have_enabled_account && single_message_selected;
3901 action = e_mail_reader_get_action (reader, action_name);
3902 gtk_action_set_sensitive (action, sensitive);
3904 action_name = "mail-forward-quoted";
3905 sensitive = have_enabled_account && single_message_selected;
3906 action = e_mail_reader_get_action (reader, action_name);
3907 gtk_action_set_sensitive (action, sensitive);
3909 action_name = "mail-forward-quoted-full";
3910 sensitive = have_enabled_account && single_message_selected;
3911 action = e_mail_reader_get_action (reader, action_name);
3912 gtk_action_set_sensitive (action, sensitive);
3914 action_name = "mail-goto-menu";
3915 sensitive = any_messages_selected;
3916 action = e_mail_reader_get_action (reader, action_name);
3917 gtk_action_set_sensitive (action, sensitive);
3919 action_name = "mail-load-images";
3920 sensitive = single_message_selected;
3921 action = e_mail_reader_get_action (reader, action_name);
3922 gtk_action_set_sensitive (action, sensitive);
3924 action_name = "mail-mark-as-menu";
3925 sensitive = any_messages_selected;
3926 action = e_mail_reader_get_action (reader, action_name);
3927 gtk_action_set_sensitive (action, sensitive);
3929 action_name = "mail-mark-ignore-thread-sub";
3930 sensitive = selection_has_notignore_thread_messages;
3931 action = e_mail_reader_get_action (reader, action_name);
3932 gtk_action_set_sensitive (action, sensitive);
3933 gtk_action_set_visible (action, sensitive);
3935 action_name = "mail-mark-ignore-thread-whole";
3936 sensitive = selection_has_notignore_thread_messages;
3937 action = e_mail_reader_get_action (reader, action_name);
3938 gtk_action_set_sensitive (action, sensitive);
3939 gtk_action_set_visible (action, sensitive);
3941 action_name = "mail-mark-important";
3942 sensitive = selection_has_unimportant_messages;
3943 action = e_mail_reader_get_action (reader, action_name);
3944 gtk_action_set_sensitive (action, sensitive);
3946 action_name = "mail-mark-junk";
3947 sensitive = selection_has_not_junk_messages;
3948 action = e_mail_reader_get_action (reader, action_name);
3949 gtk_action_set_sensitive (action, sensitive);
3951 action_name = "mail-mark-notjunk";
3952 sensitive = selection_has_junk_messages;
3953 action = e_mail_reader_get_action (reader, action_name);
3954 gtk_action_set_sensitive (action, sensitive);
3956 action_name = "mail-mark-read";
3957 sensitive = selection_has_unread_messages;
3958 action = e_mail_reader_get_action (reader, action_name);
3959 gtk_action_set_sensitive (action, sensitive);
3961 action_name = "mail-mark-unignore-thread-sub";
3962 sensitive = selection_has_ignore_thread_messages;
3963 action = e_mail_reader_get_action (reader, action_name);
3964 gtk_action_set_sensitive (action, sensitive);
3965 gtk_action_set_visible (action, sensitive);
3967 action_name = "mail-mark-unignore-thread-whole";
3968 sensitive = selection_has_ignore_thread_messages;
3969 action = e_mail_reader_get_action (reader, action_name);
3970 gtk_action_set_sensitive (action, sensitive);
3971 gtk_action_set_visible (action, sensitive);
3973 action_name = "mail-mark-unimportant";
3974 sensitive = selection_has_important_messages;
3975 action = e_mail_reader_get_action (reader, action_name);
3976 gtk_action_set_sensitive (action, sensitive);
3978 action_name = "mail-mark-unread";
3979 sensitive = selection_has_read_messages;
3980 action = e_mail_reader_get_action (reader, action_name);
3981 gtk_action_set_sensitive (action, sensitive);
3983 action_name = "mail-message-edit";
3984 sensitive = have_enabled_account && single_message_selected;
3985 action = e_mail_reader_get_action (reader, action_name);
3986 gtk_action_set_sensitive (action, sensitive);
3988 action_name = "mail-message-new";
3989 sensitive = have_enabled_account;
3990 action = e_mail_reader_get_action (reader, action_name);
3991 gtk_action_set_sensitive (action, sensitive);
3993 action_name = "mail-message-open";
3994 sensitive = any_messages_selected;
3995 action = e_mail_reader_get_action (reader, action_name);
3996 gtk_action_set_sensitive (action, sensitive);
3998 action_name = "mail-move";
3999 sensitive = any_messages_selected;
4000 action = e_mail_reader_get_action (reader, action_name);
4001 gtk_action_set_sensitive (action, sensitive);
4003 action_name = "mail-next";
4004 sensitive = any_messages_selected && !last_message_selected;
4005 action = e_mail_reader_get_action (reader, action_name);
4006 gtk_action_set_sensitive (action, sensitive);
4008 action_name = "mail-next-important";
4009 sensitive = single_message_selected;
4010 action = e_mail_reader_get_action (reader, action_name);
4011 gtk_action_set_sensitive (action, sensitive);
4013 action_name = "mail-next-thread";
4014 sensitive = single_message_selected && !last_message_selected;
4015 action = e_mail_reader_get_action (reader, action_name);
4016 gtk_action_set_sensitive (action, sensitive);
4018 action_name = "mail-next-unread";
4019 sensitive = any_messages_selected;
4020 action = e_mail_reader_get_action (reader, action_name);
4021 gtk_action_set_sensitive (action, sensitive);
4023 action_name = "mail-previous";
4024 sensitive = any_messages_selected && !first_message_selected;
4025 action = e_mail_reader_get_action (reader, action_name);
4026 gtk_action_set_sensitive (action, sensitive);
4028 action_name = "mail-previous-important";
4029 sensitive = single_message_selected;
4030 action = e_mail_reader_get_action (reader, action_name);
4031 gtk_action_set_sensitive (action, sensitive);
4033 action_name = "mail-previous-unread";
4034 sensitive = any_messages_selected;
4035 action = e_mail_reader_get_action (reader, action_name);
4036 gtk_action_set_sensitive (action, sensitive);
4038 action_name = "mail-previous-thread";
4039 sensitive = any_messages_selected && !first_message_selected;
4040 action = e_mail_reader_get_action (reader, action_name);
4041 gtk_action_set_sensitive (action, sensitive);
4043 action_name = "mail-print";
4044 sensitive = single_message_selected;
4045 action = e_mail_reader_get_action (reader, action_name);
4046 gtk_action_set_sensitive (action, sensitive);
4048 action_name = "mail-print-preview";
4049 sensitive = single_message_selected;
4050 action = e_mail_reader_get_action (reader, action_name);
4051 gtk_action_set_sensitive (action, sensitive);
4053 action_name = "mail-redirect";
4054 sensitive = have_enabled_account && single_message_selected;
4055 action = e_mail_reader_get_action (reader, action_name);
4056 gtk_action_set_sensitive (action, sensitive);
4058 action_name = "mail-remove-attachments";
4059 sensitive = any_messages_selected && selection_has_attachment_messages;
4060 action = e_mail_reader_get_action (reader, action_name);
4061 gtk_action_set_sensitive (action, sensitive);
4063 action_name = "mail-remove-duplicates";
4064 sensitive = multiple_messages_selected;
4065 action = e_mail_reader_get_action (reader, action_name);
4066 gtk_action_set_sensitive (action, sensitive);
4068 action_name = "mail-reply-all";
4069 sensitive = have_enabled_account && single_message_selected;
4070 action = e_mail_reader_get_action (reader, action_name);
4071 gtk_action_set_sensitive (action, sensitive);
4073 action_name = "mail-reply-group";
4074 sensitive = have_enabled_account && single_message_selected;
4075 action = e_mail_reader_get_action (reader, action_name);
4076 gtk_action_set_sensitive (action, sensitive);
4078 action_name = "mail-reply-group-menu";
4079 sensitive = have_enabled_account && any_messages_selected;
4080 action = e_mail_reader_get_action (reader, action_name);
4081 gtk_action_set_sensitive (action, sensitive);
4083 action_name = "mail-reply-list";
4084 sensitive = have_enabled_account && single_message_selected &&
4085 selection_is_mailing_list;
4086 action = e_mail_reader_get_action (reader, action_name);
4087 gtk_action_set_sensitive (action, sensitive);
4089 action_name = "mail-reply-sender";
4090 sensitive = have_enabled_account && single_message_selected;
4091 action = e_mail_reader_get_action (reader, action_name);
4092 gtk_action_set_sensitive (action, sensitive);
4094 action_name = "mail-save-as";
4095 sensitive = any_messages_selected;
4096 action = e_mail_reader_get_action (reader, action_name);
4097 gtk_action_set_sensitive (action, sensitive);
4099 action_name = "mail-show-source";
4100 sensitive = single_message_selected;
4101 action = e_mail_reader_get_action (reader, action_name);
4102 gtk_action_set_sensitive (action, sensitive);
4104 action_name = "mail-undelete";
4105 sensitive = selection_has_deleted_messages;
4106 action = e_mail_reader_get_action (reader, action_name);
4107 gtk_action_set_sensitive (action, sensitive);
4109 action_name = "mail-zoom-100";
4110 sensitive = single_message_selected;
4111 action = e_mail_reader_get_action (reader, action_name);
4112 gtk_action_set_sensitive (action, sensitive);
4114 action_name = "mail-zoom-in";
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-zoom-out";
4120 sensitive = single_message_selected;
4121 action = e_mail_reader_get_action (reader, action_name);
4122 gtk_action_set_sensitive (action, sensitive);
4125 static void
4126 mail_reader_init_charset_actions (EMailReader *reader,
4127 GtkActionGroup *action_group)
4129 GtkRadioAction *default_action;
4130 GSList *radio_group;
4132 radio_group = e_charset_add_radio_actions (
4133 action_group, "mail-charset-", NULL,
4134 G_CALLBACK (action_mail_charset_cb), reader);
4136 /* XXX Add a tooltip! */
4137 default_action = gtk_radio_action_new (
4138 "mail-charset-default", _("Default"), NULL, NULL, -1);
4140 gtk_radio_action_set_group (default_action, radio_group);
4142 g_signal_connect (
4143 default_action, "changed",
4144 G_CALLBACK (action_mail_charset_cb), reader);
4146 gtk_action_group_add_action (
4147 action_group, GTK_ACTION (default_action));
4149 gtk_radio_action_set_current_value (default_action, -1);
4152 static void
4153 e_mail_reader_default_init (EMailReaderInterface *iface)
4155 quark_private = g_quark_from_static_string ("e-mail-reader-private");
4157 iface->get_alert_sink = mail_reader_get_alert_sink;
4158 iface->get_selected_uids = mail_reader_get_selected_uids;
4159 iface->get_selected_uids_with_collapsed_threads = mail_reader_get_selected_uids_with_collapsed_threads;
4160 iface->ref_folder = mail_reader_ref_folder;
4161 iface->set_folder = mail_reader_set_folder;
4162 iface->set_message = mail_reader_set_message;
4163 iface->open_selected_mail = e_mail_reader_open_selected;
4164 iface->folder_loaded = mail_reader_folder_loaded;
4165 iface->message_loaded = mail_reader_message_loaded;
4166 iface->message_seen = mail_reader_message_seen;
4167 iface->show_search_bar = mail_reader_show_search_bar;
4168 iface->update_actions = mail_reader_update_actions;
4170 g_object_interface_install_property (
4171 iface,
4172 g_param_spec_enum (
4173 "forward-style",
4174 "Forward Style",
4175 "How to forward messages",
4176 E_TYPE_MAIL_FORWARD_STYLE,
4177 E_MAIL_FORWARD_STYLE_ATTACHED,
4178 G_PARAM_READWRITE));
4180 g_object_interface_install_property (
4181 iface,
4182 g_param_spec_boolean (
4183 "group-by-threads",
4184 "Group by Threads",
4185 "Whether to group messages by threads",
4186 FALSE,
4187 G_PARAM_READWRITE));
4189 g_object_interface_install_property (
4190 iface,
4191 g_param_spec_enum (
4192 "reply-style",
4193 "Reply Style",
4194 "How to reply to messages",
4195 E_TYPE_MAIL_REPLY_STYLE,
4196 E_MAIL_REPLY_STYLE_QUOTED,
4197 G_PARAM_READWRITE));
4199 g_object_interface_install_property (
4200 iface,
4201 g_param_spec_boolean (
4202 "mark-seen-always",
4203 "Mark Seen Always",
4204 "Whether to mark unread message seen even after folder change",
4205 FALSE,
4206 G_PARAM_READWRITE));
4208 g_object_interface_install_property (
4209 iface,
4210 g_param_spec_boolean (
4211 "delete-selects-previous",
4212 "Delete Selects Previous",
4213 "Whether go to the previous message after message deletion",
4214 FALSE,
4215 G_PARAM_READWRITE));
4217 signals[CHANGED] = g_signal_new (
4218 "changed",
4219 G_OBJECT_CLASS_TYPE (iface),
4220 G_SIGNAL_RUN_FIRST,
4221 0, NULL, NULL,
4222 g_cclosure_marshal_VOID__VOID,
4223 G_TYPE_NONE, 0);
4225 signals[COMPOSER_CREATED] = g_signal_new (
4226 "composer-created",
4227 G_OBJECT_CLASS_TYPE (iface),
4228 G_SIGNAL_RUN_FIRST,
4229 G_STRUCT_OFFSET (EMailReaderInterface, composer_created),
4230 NULL, NULL, NULL,
4231 G_TYPE_NONE, 2,
4232 E_TYPE_MSG_COMPOSER,
4233 CAMEL_TYPE_MIME_MESSAGE);
4235 signals[FOLDER_LOADED] = g_signal_new (
4236 "folder-loaded",
4237 G_OBJECT_CLASS_TYPE (iface),
4238 G_SIGNAL_RUN_FIRST,
4239 G_STRUCT_OFFSET (EMailReaderInterface, folder_loaded),
4240 NULL, NULL,
4241 g_cclosure_marshal_VOID__VOID,
4242 G_TYPE_NONE, 0);
4244 signals[MESSAGE_LOADED] = g_signal_new (
4245 "message-loaded",
4246 G_OBJECT_CLASS_TYPE (iface),
4247 G_SIGNAL_RUN_LAST,
4248 G_STRUCT_OFFSET (EMailReaderInterface, message_loaded),
4249 NULL, NULL,
4250 e_marshal_VOID__STRING_OBJECT,
4251 G_TYPE_NONE, 2,
4252 G_TYPE_STRING,
4253 CAMEL_TYPE_MIME_MESSAGE);
4255 signals[MESSAGE_SEEN] = g_signal_new (
4256 "message-seen",
4257 G_OBJECT_CLASS_TYPE (iface),
4258 G_SIGNAL_RUN_LAST,
4259 G_STRUCT_OFFSET (EMailReaderInterface, message_seen),
4260 NULL, NULL,
4261 e_marshal_VOID__STRING_OBJECT,
4262 G_TYPE_NONE, 2,
4263 G_TYPE_STRING,
4264 CAMEL_TYPE_MIME_MESSAGE);
4266 signals[SHOW_SEARCH_BAR] = g_signal_new (
4267 "show-search-bar",
4268 G_OBJECT_CLASS_TYPE (iface),
4269 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
4270 G_STRUCT_OFFSET (EMailReaderInterface, show_search_bar),
4271 NULL, NULL,
4272 g_cclosure_marshal_VOID__VOID,
4273 G_TYPE_NONE, 0);
4275 signals[UPDATE_ACTIONS] = g_signal_new (
4276 "update-actions",
4277 G_OBJECT_CLASS_TYPE (iface),
4278 G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
4279 G_STRUCT_OFFSET (EMailReaderInterface, update_actions),
4280 NULL, NULL,
4281 g_cclosure_marshal_VOID__UINT,
4282 G_TYPE_NONE, 1,
4283 G_TYPE_UINT);
4286 void
4287 e_mail_reader_init (EMailReader *reader,
4288 gboolean init_actions,
4289 gboolean connect_signals)
4291 EMenuToolAction *menu_tool_action;
4292 GtkActionGroup *action_group;
4293 GtkWidget *message_list;
4294 GtkAction *action;
4295 const gchar *action_name;
4296 EMailDisplay *display;
4297 GSettings *settings;
4299 g_return_if_fail (E_IS_MAIL_READER (reader));
4301 message_list = e_mail_reader_get_message_list (reader);
4302 display = e_mail_reader_get_mail_display (reader);
4304 /* Initialize a private struct. */
4305 g_object_set_qdata_full (
4306 G_OBJECT (reader), quark_private,
4307 g_slice_new0 (EMailReaderPrivate),
4308 (GDestroyNotify) mail_reader_private_free);
4310 e_binding_bind_property (
4311 reader, "group-by-threads",
4312 message_list, "group-by-threads",
4313 G_BINDING_SYNC_CREATE);
4315 if (!init_actions)
4316 goto connect_signals;
4318 /* Add the "standard" EMailReader actions. */
4320 action_group = e_mail_reader_get_action_group (
4321 reader, E_MAIL_READER_ACTION_GROUP_STANDARD);
4323 /* The "mail-forward" action is special: it uses a GtkMenuToolButton
4324 * for its toolbar item type. So we have to create it separately. */
4326 menu_tool_action = e_menu_tool_action_new (
4327 "mail-forward", _("_Forward"),
4328 _("Forward the selected message to someone"));
4330 gtk_action_set_icon_name (
4331 GTK_ACTION (menu_tool_action), "mail-forward");
4333 g_signal_connect (
4334 menu_tool_action, "activate",
4335 G_CALLBACK (action_mail_forward_cb), reader);
4337 gtk_action_group_add_action_with_accel (
4338 action_group, GTK_ACTION (menu_tool_action), "<Control>f");
4340 /* Likewise the "mail-reply-group" action. */
4342 menu_tool_action = e_menu_tool_action_new (
4343 /* For Translators: "Group Reply" will reply either to a mailing list
4344 * (if possible and if that configuration option is enabled), or else
4345 * it will reply to all. The word "Group" was chosen because it covers
4346 * either of those, without too strongly implying one or the other. */
4347 "mail-reply-group", _("Group Reply"),
4348 _("Reply to the mailing list, or to all recipients"));
4350 gtk_action_set_icon_name (
4351 GTK_ACTION (menu_tool_action), "mail-reply-all");
4353 g_signal_connect (
4354 menu_tool_action, "activate",
4355 G_CALLBACK (action_mail_reply_group_cb), reader);
4357 gtk_action_group_add_action_with_accel (
4358 action_group, GTK_ACTION (menu_tool_action), "<Control>g");
4360 /* Add the other actions the normal way. */
4361 gtk_action_group_add_actions (
4362 action_group, mail_reader_entries,
4363 G_N_ELEMENTS (mail_reader_entries), reader);
4364 e_action_group_add_popup_actions (
4365 action_group, mail_reader_popup_entries,
4366 G_N_ELEMENTS (mail_reader_popup_entries));
4367 gtk_action_group_add_toggle_actions (
4368 action_group, mail_reader_toggle_entries,
4369 G_N_ELEMENTS (mail_reader_toggle_entries), reader);
4371 mail_reader_init_charset_actions (reader, action_group);
4373 /* Add EMailReader actions for Search Folders. The action group
4374 * should be made invisible if Search Folders are disabled. */
4376 action_group = e_mail_reader_get_action_group (
4377 reader, E_MAIL_READER_ACTION_GROUP_SEARCH_FOLDERS);
4379 gtk_action_group_add_actions (
4380 action_group, mail_reader_search_folder_entries,
4381 G_N_ELEMENTS (mail_reader_search_folder_entries), reader);
4383 display = e_mail_reader_get_mail_display (reader);
4385 /* Bind GObject properties to GSettings keys. */
4387 settings = e_util_ref_settings ("org.gnome.evolution.mail");
4389 action_name = "mail-caret-mode";
4390 action = e_mail_reader_get_action (reader, action_name);
4391 g_settings_bind (
4392 settings, "caret-mode",
4393 action, "active", G_SETTINGS_BIND_DEFAULT);
4395 action_name = "mail-show-all-headers";
4396 action = e_mail_reader_get_action (reader, action_name);
4397 g_settings_bind (
4398 settings, "show-all-headers",
4399 action, "active", G_SETTINGS_BIND_DEFAULT);
4401 /* Mode change when viewing message source is ignored. */
4402 if (e_mail_display_get_mode (display) == E_MAIL_FORMATTER_MODE_SOURCE ||
4403 e_mail_display_get_mode (display) == E_MAIL_FORMATTER_MODE_RAW) {
4404 gtk_action_set_sensitive (action, FALSE);
4405 gtk_action_set_visible (action, FALSE);
4408 g_object_unref (settings);
4410 /* Fine tuning. */
4412 action_name = "mail-delete";
4413 action = e_mail_reader_get_action (reader, action_name);
4414 gtk_action_set_short_label (action, _("Delete"));
4416 action_name = "mail-forward";
4417 action = e_mail_reader_get_action (reader, action_name);
4418 gtk_action_set_is_important (action, TRUE);
4420 action_name = "mail-reply-group";
4421 action = e_mail_reader_get_action (reader, action_name);
4422 gtk_action_set_is_important (action, TRUE);
4424 action_name = "mail-next";
4425 action = e_mail_reader_get_action (reader, action_name);
4426 gtk_action_set_short_label (action, _("Next"));
4428 action_name = "mail-previous";
4429 action = e_mail_reader_get_action (reader, action_name);
4430 gtk_action_set_short_label (action, _("Previous"));
4432 action_name = "mail-reply-all";
4433 action = e_mail_reader_get_action (reader, action_name);
4434 gtk_action_set_is_important (action, TRUE);
4436 action_name = "mail-reply-sender";
4437 action = e_mail_reader_get_action (reader, action_name);
4438 gtk_action_set_is_important (action, TRUE);
4439 gtk_action_set_short_label (action, _("Reply"));
4441 action_name = "add-to-address-book";
4442 action = e_mail_display_get_action (display, action_name);
4443 g_signal_connect (
4444 action, "activate",
4445 G_CALLBACK (action_add_to_address_book_cb), reader);
4447 action_name = "send-reply";
4448 action = e_mail_display_get_action (display, action_name);
4449 g_signal_connect (
4450 action, "activate",
4451 G_CALLBACK (action_mail_reply_recipient_cb), reader);
4453 action_name = "search-folder-recipient";
4454 action = e_mail_display_get_action (display, action_name);
4455 g_signal_connect (
4456 action, "activate",
4457 G_CALLBACK (action_search_folder_recipient_cb), reader);
4459 action_name = "search-folder-sender";
4460 action = e_mail_display_get_action (display, action_name);
4461 g_signal_connect (
4462 action, "activate",
4463 G_CALLBACK (action_search_folder_sender_cb), reader);
4465 #ifndef G_OS_WIN32
4466 /* Lockdown integration. */
4468 settings = e_util_ref_settings ("org.gnome.desktop.lockdown");
4470 action_name = "mail-print";
4471 action = e_mail_reader_get_action (reader, action_name);
4472 g_settings_bind (
4473 settings, "disable-printing",
4474 action, "visible",
4475 G_SETTINGS_BIND_GET |
4476 G_SETTINGS_BIND_NO_SENSITIVITY |
4477 G_SETTINGS_BIND_INVERT_BOOLEAN);
4479 action_name = "mail-print-preview";
4480 action = e_mail_reader_get_action (reader, action_name);
4481 g_settings_bind (
4482 settings, "disable-printing",
4483 action, "visible",
4484 G_SETTINGS_BIND_GET |
4485 G_SETTINGS_BIND_NO_SENSITIVITY |
4486 G_SETTINGS_BIND_INVERT_BOOLEAN);
4488 action_name = "mail-save-as";
4489 action = e_mail_reader_get_action (reader, action_name);
4490 g_settings_bind (
4491 settings, "disable-save-to-disk",
4492 action, "visible",
4493 G_SETTINGS_BIND_GET |
4494 G_SETTINGS_BIND_NO_SENSITIVITY |
4495 G_SETTINGS_BIND_INVERT_BOOLEAN);
4497 g_object_unref (settings);
4498 #endif
4500 /* Bind properties. */
4502 action_name = "mail-caret-mode";
4503 action = e_mail_reader_get_action (reader, action_name);
4505 e_binding_bind_property (
4506 action, "active",
4507 display, "caret-mode",
4508 G_BINDING_BIDIRECTIONAL |
4509 G_BINDING_SYNC_CREATE);
4511 connect_signals:
4513 if (!connect_signals)
4514 return;
4516 /* Connect signals. */
4517 g_signal_connect_swapped (
4518 display, "key-press-event",
4519 G_CALLBACK (mail_reader_key_press_event_cb), reader);
4521 g_signal_connect_swapped (
4522 display, "load-changed",
4523 G_CALLBACK (mail_reader_load_changed_cb), reader);
4525 g_signal_connect_swapped (
4526 message_list, "message-selected",
4527 G_CALLBACK (mail_reader_message_selected_cb), reader);
4529 /* re-schedule mark-as-seen,... */
4530 g_signal_connect_swapped (
4531 message_list, "cursor-change",
4532 G_CALLBACK (mail_reader_message_cursor_change_cb), reader);
4534 /* but do not mark-as-seen if... */
4535 g_signal_connect_swapped (
4536 message_list, "tree-drag-begin",
4537 G_CALLBACK (discard_timeout_mark_seen_cb), reader);
4539 g_signal_connect_swapped (
4540 message_list, "tree-drag-end",
4541 G_CALLBACK (discard_timeout_mark_seen_cb), reader);
4543 g_signal_connect_swapped (
4544 message_list, "right-click",
4545 G_CALLBACK (discard_timeout_mark_seen_cb), reader);
4547 g_signal_connect_swapped (
4548 e_mail_reader_get_preview_pane (reader), "notify::visible",
4549 G_CALLBACK (mail_reader_preview_pane_visible_changed_cb), reader);
4551 g_signal_connect_after (
4552 message_list, "message-list-built",
4553 G_CALLBACK (mail_reader_message_list_built_cb), reader);
4555 g_signal_connect_swapped (
4556 message_list, "double-click",
4557 G_CALLBACK (mail_reader_double_click_cb), reader);
4559 g_signal_connect_swapped (
4560 message_list, "key-press",
4561 G_CALLBACK (mail_reader_key_press_cb), reader);
4563 g_signal_connect_swapped (
4564 message_list, "selection-change",
4565 G_CALLBACK (e_mail_reader_changed), reader);
4568 void
4569 e_mail_reader_changed (EMailReader *reader)
4571 MessageList *message_list;
4573 g_return_if_fail (E_IS_MAIL_READER (reader));
4575 g_signal_emit (reader, signals[CHANGED], 0);
4577 message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
4579 if (!message_list || message_list_selected_count (message_list) != 1)
4580 mail_reader_remove_followup_alert (reader);
4583 guint32
4584 e_mail_reader_check_state (EMailReader *reader)
4586 EShell *shell;
4587 GPtrArray *uids;
4588 CamelFolder *folder;
4589 CamelStore *store = NULL;
4590 EMailBackend *backend;
4591 ESourceRegistry *registry;
4592 EMailSession *mail_session;
4593 EMailAccountStore *account_store;
4594 const gchar *tag;
4595 gboolean can_clear_flags = FALSE;
4596 gboolean can_flag_completed = FALSE;
4597 gboolean can_flag_for_followup = FALSE;
4598 gboolean has_attachments = FALSE;
4599 gboolean has_deleted = FALSE;
4600 gboolean has_ignore_thread = FALSE;
4601 gboolean has_notignore_thread = FALSE;
4602 gboolean has_important = FALSE;
4603 gboolean has_junk = FALSE;
4604 gboolean has_not_junk = FALSE;
4605 gboolean has_read = FALSE;
4606 gboolean has_undeleted = FALSE;
4607 gboolean has_unimportant = FALSE;
4608 gboolean has_unread = FALSE;
4609 gboolean has_mail_note = FALSE;
4610 gboolean have_enabled_account = FALSE;
4611 gboolean drafts_or_outbox = FALSE;
4612 gboolean is_mailing_list;
4613 gboolean is_junk_folder = FALSE;
4614 gboolean is_vtrash_folder = FALSE;
4615 gboolean archive_folder_set = FALSE;
4616 guint32 state = 0;
4617 guint ii;
4619 g_return_val_if_fail (E_IS_MAIL_READER (reader), 0);
4621 backend = e_mail_reader_get_backend (reader);
4622 shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
4623 registry = e_shell_get_registry (shell);
4624 mail_session = e_mail_backend_get_session (backend);
4625 account_store = e_mail_ui_session_get_account_store (
4626 E_MAIL_UI_SESSION (mail_session));
4628 folder = e_mail_reader_ref_folder (reader);
4629 uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
4631 if (folder != NULL) {
4632 gchar *archive_folder;
4633 guint32 folder_flags;
4635 store = camel_folder_get_parent_store (folder);
4636 folder_flags = camel_folder_get_flags (folder);
4637 is_junk_folder = (folder_flags & CAMEL_FOLDER_IS_JUNK) != 0;
4638 is_vtrash_folder = (camel_store_get_flags (store) & CAMEL_STORE_VTRASH) != 0 && (folder_flags & CAMEL_FOLDER_IS_TRASH) != 0;
4639 drafts_or_outbox =
4640 em_utils_folder_is_drafts (registry, folder) ||
4641 em_utils_folder_is_outbox (registry, folder);
4643 archive_folder = em_utils_get_archive_folder_uri_from_folder (folder, backend, uids, TRUE);
4644 if (archive_folder && *archive_folder)
4645 archive_folder_set = TRUE;
4647 g_free (archive_folder);
4650 /* Initialize this flag based on whether there are any
4651 * messages selected. We will update it in the loop. */
4652 is_mailing_list = (uids->len > 0);
4654 for (ii = 0; ii < uids->len; ii++) {
4655 CamelMessageInfo *info;
4656 const gchar *string;
4657 guint32 flags;
4659 info = camel_folder_get_message_info (
4660 folder, uids->pdata[ii]);
4661 if (info == NULL)
4662 continue;
4664 if (camel_message_info_get_user_flag (info, E_MAIL_NOTES_USER_FLAG))
4665 has_mail_note = TRUE;
4667 flags = camel_message_info_get_flags (info);
4669 if (flags & CAMEL_MESSAGE_SEEN)
4670 has_read = TRUE;
4671 else
4672 has_unread = TRUE;
4674 if (flags & CAMEL_MESSAGE_ATTACHMENTS)
4675 has_attachments = TRUE;
4677 if (drafts_or_outbox) {
4678 has_junk = FALSE;
4679 has_not_junk = FALSE;
4680 } else {
4681 guint32 bitmask;
4683 /* XXX Strictly speaking, this logic is correct.
4684 * Problem is there's nothing in the message
4685 * list that indicates whether a message is
4686 * already marked "Not Junk". So the user may
4687 * think the "Not Junk" button is enabling and
4688 * disabling itself randomly as he reads mail. */
4690 if (flags & CAMEL_MESSAGE_JUNK)
4691 has_junk = TRUE;
4692 if (flags & CAMEL_MESSAGE_NOTJUNK)
4693 has_not_junk = TRUE;
4695 bitmask = CAMEL_MESSAGE_JUNK | CAMEL_MESSAGE_NOTJUNK;
4697 /* If neither junk flag is set, the
4698 * message can be marked either way. */
4699 if ((flags & bitmask) == 0) {
4700 has_junk = TRUE;
4701 has_not_junk = TRUE;
4705 if (flags & CAMEL_MESSAGE_DELETED)
4706 has_deleted = TRUE;
4707 else
4708 has_undeleted = TRUE;
4710 if (flags & CAMEL_MESSAGE_FLAGGED)
4711 has_important = TRUE;
4712 else
4713 has_unimportant = TRUE;
4715 tag = camel_message_info_get_user_tag (info, "follow-up");
4716 if (tag != NULL && *tag != '\0') {
4717 can_clear_flags = TRUE;
4718 tag = camel_message_info_get_user_tag (
4719 info, "completed-on");
4720 if (tag == NULL || *tag == '\0')
4721 can_flag_completed = TRUE;
4722 } else
4723 can_flag_for_followup = TRUE;
4725 string = camel_message_info_get_mlist (info);
4726 is_mailing_list &= (string != NULL && *string != '\0');
4728 has_ignore_thread = has_ignore_thread ||
4729 camel_message_info_get_user_flag (info, "ignore-thread");
4730 has_notignore_thread = has_notignore_thread ||
4731 !camel_message_info_get_user_flag (info, "ignore-thread");
4733 g_clear_object (&info);
4736 have_enabled_account =
4737 e_mail_account_store_have_enabled_service (
4738 account_store, CAMEL_TYPE_STORE);
4740 if (have_enabled_account)
4741 state |= E_MAIL_READER_HAVE_ENABLED_ACCOUNT;
4742 if (uids->len == 1)
4743 state |= E_MAIL_READER_SELECTION_SINGLE;
4744 if (uids->len > 1)
4745 state |= E_MAIL_READER_SELECTION_MULTIPLE;
4746 if (!drafts_or_outbox && uids->len == 1)
4747 state |= E_MAIL_READER_SELECTION_CAN_ADD_SENDER;
4748 if (can_clear_flags)
4749 state |= E_MAIL_READER_SELECTION_FLAG_CLEAR;
4750 if (can_flag_completed)
4751 state |= E_MAIL_READER_SELECTION_FLAG_COMPLETED;
4752 if (can_flag_for_followup)
4753 state |= E_MAIL_READER_SELECTION_FLAG_FOLLOWUP;
4754 if (has_attachments)
4755 state |= E_MAIL_READER_SELECTION_HAS_ATTACHMENTS;
4756 if (has_deleted)
4757 state |= E_MAIL_READER_SELECTION_HAS_DELETED;
4758 if (has_ignore_thread)
4759 state |= E_MAIL_READER_SELECTION_HAS_IGNORE_THREAD;
4760 if (has_notignore_thread)
4761 state |= E_MAIL_READER_SELECTION_HAS_NOTIGNORE_THREAD;
4762 if (has_important)
4763 state |= E_MAIL_READER_SELECTION_HAS_IMPORTANT;
4764 if (has_junk)
4765 state |= E_MAIL_READER_SELECTION_HAS_JUNK;
4766 if (has_not_junk)
4767 state |= E_MAIL_READER_SELECTION_HAS_NOT_JUNK;
4768 if (has_read)
4769 state |= E_MAIL_READER_SELECTION_HAS_READ;
4770 if (has_undeleted)
4771 state |= E_MAIL_READER_SELECTION_HAS_UNDELETED;
4772 if (has_unimportant)
4773 state |= E_MAIL_READER_SELECTION_HAS_UNIMPORTANT;
4774 if (has_unread)
4775 state |= E_MAIL_READER_SELECTION_HAS_UNREAD;
4776 if (is_mailing_list)
4777 state |= E_MAIL_READER_SELECTION_IS_MAILING_LIST;
4778 if (is_junk_folder)
4779 state |= E_MAIL_READER_FOLDER_IS_JUNK;
4780 if (is_vtrash_folder)
4781 state |= E_MAIL_READER_FOLDER_IS_VTRASH;
4782 if (archive_folder_set)
4783 state |= E_MAIL_READER_FOLDER_ARCHIVE_FOLDER_SET;
4784 if (has_mail_note)
4785 state |= E_MAIL_READER_SELECTION_HAS_MAIL_NOTE;
4787 g_clear_object (&folder);
4788 g_ptr_array_unref (uids);
4790 return state;
4793 EActivity *
4794 e_mail_reader_new_activity (EMailReader *reader)
4796 EActivity *activity;
4797 EMailBackend *backend;
4798 EAlertSink *alert_sink;
4799 GCancellable *cancellable;
4801 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
4803 activity = e_activity_new ();
4805 alert_sink = e_mail_reader_get_alert_sink (reader);
4806 e_activity_set_alert_sink (activity, alert_sink);
4808 cancellable = camel_operation_new ();
4809 e_activity_set_cancellable (activity, cancellable);
4810 g_object_unref (cancellable);
4812 backend = e_mail_reader_get_backend (reader);
4813 e_shell_backend_add_activity (E_SHELL_BACKEND (backend), activity);
4815 return activity;
4818 void
4819 e_mail_reader_update_actions (EMailReader *reader,
4820 guint32 state)
4822 g_return_if_fail (E_IS_MAIL_READER (reader));
4824 g_signal_emit (reader, signals[UPDATE_ACTIONS], 0, state);
4827 GtkAction *
4828 e_mail_reader_get_action (EMailReader *reader,
4829 const gchar *action_name)
4831 GtkAction *action = NULL;
4832 gint ii;
4834 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
4835 g_return_val_if_fail (action_name != NULL, NULL);
4837 for (ii = 0; ii < E_MAIL_READER_NUM_ACTION_GROUPS; ii++) {
4838 GtkActionGroup *group;
4840 group = e_mail_reader_get_action_group (reader, ii);
4841 action = gtk_action_group_get_action (group, action_name);
4843 if (action != NULL)
4844 break;
4847 if (action == NULL)
4848 g_critical (
4849 "%s: action '%s' not found", G_STRFUNC, action_name);
4851 return action;
4854 GtkActionGroup *
4855 e_mail_reader_get_action_group (EMailReader *reader,
4856 EMailReaderActionGroup group)
4858 EMailReaderInterface *iface;
4860 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
4862 iface = E_MAIL_READER_GET_INTERFACE (reader);
4863 g_return_val_if_fail (iface->get_action_group != NULL, NULL);
4865 return iface->get_action_group (reader, group);
4868 EAlertSink *
4869 e_mail_reader_get_alert_sink (EMailReader *reader)
4871 EMailReaderInterface *iface;
4873 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
4875 iface = E_MAIL_READER_GET_INTERFACE (reader);
4876 g_return_val_if_fail (iface->get_alert_sink != NULL, NULL);
4878 return iface->get_alert_sink (reader);
4881 EMailBackend *
4882 e_mail_reader_get_backend (EMailReader *reader)
4884 EMailReaderInterface *iface;
4886 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
4888 iface = E_MAIL_READER_GET_INTERFACE (reader);
4889 g_return_val_if_fail (iface->get_backend != NULL, NULL);
4891 return iface->get_backend (reader);
4894 EMailDisplay *
4895 e_mail_reader_get_mail_display (EMailReader *reader)
4897 EMailReaderInterface *iface;
4899 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
4901 iface = E_MAIL_READER_GET_INTERFACE (reader);
4902 g_return_val_if_fail (iface->get_mail_display != NULL, NULL);
4904 return iface->get_mail_display (reader);
4907 gboolean
4908 e_mail_reader_get_hide_deleted (EMailReader *reader)
4910 EMailReaderInterface *iface;
4912 g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE);
4914 iface = E_MAIL_READER_GET_INTERFACE (reader);
4915 g_return_val_if_fail (iface->get_hide_deleted != NULL, FALSE);
4917 return iface->get_hide_deleted (reader);
4920 GtkWidget *
4921 e_mail_reader_get_message_list (EMailReader *reader)
4923 EMailReaderInterface *iface;
4925 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
4927 iface = E_MAIL_READER_GET_INTERFACE (reader);
4928 g_return_val_if_fail (iface->get_message_list != NULL, NULL);
4930 return iface->get_message_list (reader);
4933 GtkMenu *
4934 e_mail_reader_get_popup_menu (EMailReader *reader)
4936 EMailReaderInterface *iface;
4937 GtkMenu *menu;
4939 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
4941 iface = E_MAIL_READER_GET_INTERFACE (reader);
4942 g_return_val_if_fail (iface->get_popup_menu != NULL, NULL);
4944 menu = iface->get_popup_menu (reader);
4945 if (!gtk_menu_get_attach_widget (GTK_MENU (menu)))
4946 gtk_menu_attach_to_widget (GTK_MENU (menu),
4947 GTK_WIDGET (reader),
4948 NULL);
4949 return menu;
4952 EPreviewPane *
4953 e_mail_reader_get_preview_pane (EMailReader *reader)
4955 EMailReaderInterface *iface;
4957 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
4959 iface = E_MAIL_READER_GET_INTERFACE (reader);
4960 g_return_val_if_fail (iface->get_preview_pane != NULL, NULL);
4962 return iface->get_preview_pane (reader);
4965 GPtrArray *
4966 e_mail_reader_get_selected_uids (EMailReader *reader)
4968 EMailReaderInterface *iface;
4970 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
4972 iface = E_MAIL_READER_GET_INTERFACE (reader);
4973 g_return_val_if_fail (iface->get_selected_uids != NULL, NULL);
4975 return iface->get_selected_uids (reader);
4978 GPtrArray *
4979 e_mail_reader_get_selected_uids_with_collapsed_threads (EMailReader *reader)
4981 EMailReaderInterface *iface;
4983 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
4985 iface = E_MAIL_READER_GET_INTERFACE (reader);
4986 g_return_val_if_fail (iface->get_selected_uids_with_collapsed_threads != NULL, NULL);
4988 return iface->get_selected_uids_with_collapsed_threads (reader);
4991 GtkWindow *
4992 e_mail_reader_get_window (EMailReader *reader)
4994 EMailReaderInterface *iface;
4996 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
4998 iface = E_MAIL_READER_GET_INTERFACE (reader);
4999 g_return_val_if_fail (iface->get_window != NULL, NULL);
5001 return iface->get_window (reader);
5004 CamelFolder *
5005 e_mail_reader_ref_folder (EMailReader *reader)
5007 EMailReaderInterface *iface;
5009 g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
5011 iface = E_MAIL_READER_GET_INTERFACE (reader);
5012 g_return_val_if_fail (iface->ref_folder != NULL, NULL);
5014 return iface->ref_folder (reader);
5017 void
5018 e_mail_reader_set_folder (EMailReader *reader,
5019 CamelFolder *folder)
5021 EMailReaderInterface *iface;
5023 g_return_if_fail (E_IS_MAIL_READER (reader));
5025 iface = E_MAIL_READER_GET_INTERFACE (reader);
5026 g_return_if_fail (iface->set_folder != NULL);
5028 iface->set_folder (reader, folder);
5031 void
5032 e_mail_reader_set_message (EMailReader *reader,
5033 const gchar *message_uid)
5035 EMailReaderInterface *iface;
5037 g_return_if_fail (E_IS_MAIL_READER (reader));
5039 iface = E_MAIL_READER_GET_INTERFACE (reader);
5040 g_return_if_fail (iface->set_message != NULL);
5042 iface->set_message (reader, message_uid);
5045 guint
5046 e_mail_reader_open_selected_mail (EMailReader *reader)
5048 EMailReaderInterface *iface;
5050 g_return_val_if_fail (E_IS_MAIL_READER (reader), 0);
5052 iface = E_MAIL_READER_GET_INTERFACE (reader);
5053 g_return_val_if_fail (iface->open_selected_mail != NULL, 0);
5055 return iface->open_selected_mail (reader);
5058 EMailForwardStyle
5059 e_mail_reader_get_forward_style (EMailReader *reader)
5061 EMailReaderPrivate *priv;
5063 g_return_val_if_fail (E_IS_MAIL_READER (reader), 0);
5065 priv = E_MAIL_READER_GET_PRIVATE (reader);
5067 return priv->forward_style;
5070 void
5071 e_mail_reader_set_forward_style (EMailReader *reader,
5072 EMailForwardStyle style)
5074 EMailReaderPrivate *priv;
5076 g_return_if_fail (E_IS_MAIL_READER (reader));
5078 priv = E_MAIL_READER_GET_PRIVATE (reader);
5080 if (priv->forward_style == style)
5081 return;
5083 priv->forward_style = style;
5085 g_object_notify (G_OBJECT (reader), "forward-style");
5088 gboolean
5089 e_mail_reader_get_group_by_threads (EMailReader *reader)
5091 EMailReaderPrivate *priv;
5093 g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE);
5095 priv = E_MAIL_READER_GET_PRIVATE (reader);
5097 return priv->group_by_threads;
5100 void
5101 e_mail_reader_set_group_by_threads (EMailReader *reader,
5102 gboolean group_by_threads)
5104 EMailReaderPrivate *priv;
5106 g_return_if_fail (E_IS_MAIL_READER (reader));
5108 priv = E_MAIL_READER_GET_PRIVATE (reader);
5110 if (priv->group_by_threads == group_by_threads)
5111 return;
5113 priv->group_by_threads = group_by_threads;
5115 g_object_notify (G_OBJECT (reader), "group-by-threads");
5118 EMailReplyStyle
5119 e_mail_reader_get_reply_style (EMailReader *reader)
5121 EMailReaderPrivate *priv;
5123 g_return_val_if_fail (E_IS_MAIL_READER (reader), 0);
5125 priv = E_MAIL_READER_GET_PRIVATE (reader);
5127 return priv->reply_style;
5130 void
5131 e_mail_reader_set_reply_style (EMailReader *reader,
5132 EMailReplyStyle style)
5134 EMailReaderPrivate *priv;
5136 g_return_if_fail (E_IS_MAIL_READER (reader));
5138 priv = E_MAIL_READER_GET_PRIVATE (reader);
5140 if (priv->reply_style == style)
5141 return;
5143 priv->reply_style = style;
5145 g_object_notify (G_OBJECT (reader), "reply-style");
5148 gboolean
5149 e_mail_reader_get_mark_seen_always (EMailReader *reader)
5151 EMailReaderPrivate *priv;
5153 g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE);
5155 priv = E_MAIL_READER_GET_PRIVATE (reader);
5157 return priv->mark_seen_always;
5160 void
5161 e_mail_reader_set_mark_seen_always (EMailReader *reader,
5162 gboolean mark_seen_always)
5164 EMailReaderPrivate *priv;
5166 g_return_if_fail (E_IS_MAIL_READER (reader));
5168 priv = E_MAIL_READER_GET_PRIVATE (reader);
5170 if (priv->mark_seen_always == mark_seen_always)
5171 return;
5173 priv->mark_seen_always = mark_seen_always;
5175 g_object_notify (G_OBJECT (reader), "mark-seen-always");
5178 gboolean
5179 e_mail_reader_get_delete_selects_previous (EMailReader *reader)
5181 EMailReaderPrivate *priv;
5183 g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE);
5185 priv = E_MAIL_READER_GET_PRIVATE (reader);
5187 return priv->delete_selects_previous;
5190 void
5191 e_mail_reader_set_delete_selects_previous (EMailReader *reader,
5192 gboolean delete_selects_previous)
5194 EMailReaderPrivate *priv;
5196 g_return_if_fail (E_IS_MAIL_READER (reader));
5198 priv = E_MAIL_READER_GET_PRIVATE (reader);
5200 if (priv->delete_selects_previous == delete_selects_previous)
5201 return;
5203 priv->delete_selects_previous = delete_selects_previous;
5205 g_object_notify (G_OBJECT (reader), "delete-selects-previous");
5208 void
5209 e_mail_reader_create_charset_menu (EMailReader *reader,
5210 GtkUIManager *ui_manager,
5211 guint merge_id)
5213 GtkAction *action;
5214 const gchar *action_name;
5215 const gchar *path;
5216 GSList *list;
5218 g_return_if_fail (E_IS_MAIL_READER (reader));
5219 g_return_if_fail (GTK_IS_UI_MANAGER (ui_manager));
5221 action_name = "mail-charset-default";
5222 action = e_mail_reader_get_action (reader, action_name);
5223 g_return_if_fail (action != NULL);
5225 list = gtk_radio_action_get_group (GTK_RADIO_ACTION (action));
5226 list = g_slist_copy (list);
5227 list = g_slist_remove (list, action);
5228 list = g_slist_sort (list, (GCompareFunc) e_action_compare_by_label);
5230 path = "/main-menu/view-menu/mail-message-view-actions/mail-encoding-menu";
5232 while (list != NULL) {
5233 action = list->data;
5235 gtk_ui_manager_add_ui (
5236 ui_manager, merge_id, path,
5237 gtk_action_get_name (action),
5238 gtk_action_get_name (action),
5239 GTK_UI_MANAGER_AUTO, FALSE);
5241 list = g_slist_delete_link (list, list);
5244 gtk_ui_manager_ensure_update (ui_manager);
5247 void
5248 e_mail_reader_show_search_bar (EMailReader *reader)
5250 g_return_if_fail (E_IS_MAIL_READER (reader));
5252 g_signal_emit (reader, signals[SHOW_SEARCH_BAR], 0);
5255 void
5256 e_mail_reader_avoid_next_mark_as_seen (EMailReader *reader)
5258 EMailReaderPrivate *priv;
5259 MessageList *message_list;
5261 g_return_if_fail (reader != NULL);
5263 priv = E_MAIL_READER_GET_PRIVATE (reader);
5264 g_return_if_fail (priv != NULL);
5266 message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
5267 g_return_if_fail (message_list != NULL);
5269 priv->avoid_next_mark_as_seen = TRUE;
5272 void
5273 e_mail_reader_unset_folder_just_selected (EMailReader *reader)
5275 EMailReaderPrivate *priv;
5277 g_return_if_fail (reader != NULL);
5279 priv = E_MAIL_READER_GET_PRIVATE (reader);
5280 g_return_if_fail (priv != NULL);
5282 priv->folder_was_just_selected = FALSE;
5286 * e_mail_reader_composer_created:
5287 * @reader: an #EMailReader
5288 * @composer: an #EMsgComposer
5289 * @message: the source #CamelMimeMessage, or %NULL
5291 * Emits a #EMailReader::composer-created signal to indicate the @composer
5292 * window was created in response to a user action on @reader. Examples of
5293 * such actions include replying, forwarding, and composing a new message.
5294 * If applicable, the source @message (i.e. the message being replied to or
5295 * forwarded) should be included.
5297 void
5298 e_mail_reader_composer_created (EMailReader *reader,
5299 EMsgComposer *composer,
5300 CamelMimeMessage *message)
5302 g_return_if_fail (E_IS_MAIL_READER (reader));
5303 g_return_if_fail (E_IS_MSG_COMPOSER (composer));
5305 if (message != NULL)
5306 g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
5308 g_signal_emit (
5309 reader, signals[COMPOSER_CREATED], 0, composer, message);
5312 static void
5313 e_mail_reader_load_remote_content_clicked_cb (GtkButton *button,
5314 EMailReader *reader)
5316 EMailDisplay *mail_display;
5318 g_return_if_fail (E_IS_MAIL_READER (reader));
5320 mail_display = e_mail_reader_get_mail_display (reader);
5322 /* This causes reload, thus also alert removal */
5323 e_mail_display_load_images (mail_display);
5326 static GList *
5327 e_mail_reader_get_from_mails (EMailDisplay *mail_display)
5329 EMailPartList *part_list;
5330 CamelMimeMessage *message;
5331 CamelInternetAddress *from;
5332 GList *mails = NULL;
5334 g_return_val_if_fail (E_IS_MAIL_DISPLAY (mail_display), NULL);
5336 part_list = e_mail_display_get_part_list (mail_display);
5337 if (!part_list)
5338 return NULL;
5340 message = e_mail_part_list_get_message (part_list);
5341 if (!message)
5342 return NULL;
5344 from = camel_mime_message_get_from (message);
5345 if (from) {
5346 GHashTable *domains;
5347 GHashTableIter iter;
5348 gpointer key, value;
5349 gint ii, len;
5351 domains = g_hash_table_new (camel_strcase_hash, camel_strcase_equal);
5353 len = camel_address_length (CAMEL_ADDRESS (from));
5354 for (ii = 0; ii < len; ii++) {
5355 const gchar *mail = NULL;
5357 if (!camel_internet_address_get (from, ii, NULL, &mail))
5358 break;
5360 if (mail && *mail) {
5361 const gchar *at;
5363 mails = g_list_prepend (mails, g_strdup (mail));
5365 at = strchr (mail, '@');
5366 if (at && at != mail && at[1])
5367 g_hash_table_insert (domains, (gpointer) at, NULL);
5371 g_hash_table_iter_init (&iter, domains);
5372 while (g_hash_table_iter_next (&iter, &key, &value)) {
5373 const gchar *domain = key;
5375 mails = g_list_prepend (mails, g_strdup (domain));
5378 g_hash_table_destroy (domains);
5381 return g_list_reverse (mails);
5384 static void
5385 e_mail_reader_remote_content_menu_deactivate_cb (GtkMenuShell *popup_menu,
5386 GtkToggleButton *toggle_button)
5388 g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle_button));
5390 gtk_toggle_button_set_active (toggle_button, FALSE);
5391 gtk_menu_detach (GTK_MENU (popup_menu));
5394 #define REMOTE_CONTENT_KEY_IS_MAIL "remote-content-key-is-mail"
5395 #define REMOTE_CONTENT_KEY_VALUE "remote-content-key-value"
5397 static void
5398 e_mail_reader_remote_content_menu_activate_cb (GObject *item,
5399 EMailReader *reader)
5401 EMailDisplay *mail_display;
5402 EMailRemoteContent *remote_content;
5403 gboolean is_mail;
5404 const gchar *value;
5406 g_return_if_fail (GTK_IS_MENU_ITEM (item));
5407 g_return_if_fail (E_IS_MAIL_READER (reader));
5409 is_mail = GPOINTER_TO_INT (g_object_get_data (item, REMOTE_CONTENT_KEY_IS_MAIL)) == 1;
5410 value = g_object_get_data (item, REMOTE_CONTENT_KEY_VALUE);
5412 g_return_if_fail (value && *value);
5414 mail_display = e_mail_reader_get_mail_display (reader);
5415 if (!mail_display)
5416 return;
5418 remote_content = e_mail_display_ref_remote_content (mail_display);
5419 if (!remote_content)
5420 return;
5422 if (is_mail)
5423 e_mail_remote_content_add_mail (remote_content, value);
5424 else
5425 e_mail_remote_content_add_site (remote_content, value);
5427 g_clear_object (&remote_content);
5429 e_mail_display_reload (mail_display);
5432 static void
5433 e_mail_reader_remote_content_disable_activate_cb (GObject *item,
5434 EMailReader *reader)
5436 EMailDisplay *mail_display;
5437 GSettings *settings;
5439 g_return_if_fail (E_IS_MAIL_READER (reader));
5441 settings = e_util_ref_settings ("org.gnome.evolution.mail");
5442 g_settings_set_boolean (settings, "notify-remote-content", FALSE);
5443 g_clear_object (&settings);
5445 mail_display = e_mail_reader_get_mail_display (reader);
5446 if (mail_display)
5447 e_mail_display_reload (mail_display);
5450 static void
5451 e_mail_reader_add_remote_content_menu_item (EMailReader *reader,
5452 GtkWidget *popup_menu,
5453 const gchar *label,
5454 gboolean is_mail,
5455 const gchar *value)
5457 GtkWidget *item;
5458 GObject *object;
5460 g_return_if_fail (E_IS_MAIL_READER (reader));
5461 g_return_if_fail (GTK_IS_MENU (popup_menu));
5462 g_return_if_fail (label != NULL);
5463 g_return_if_fail (value != NULL);
5465 item = gtk_menu_item_new_with_label (label);
5466 object = G_OBJECT (item);
5468 g_object_set_data (object, REMOTE_CONTENT_KEY_IS_MAIL, is_mail ? GINT_TO_POINTER (1) : NULL);
5469 g_object_set_data_full (object, REMOTE_CONTENT_KEY_VALUE, g_strdup (value), g_free);
5471 g_signal_connect (item, "activate", G_CALLBACK (e_mail_reader_remote_content_menu_activate_cb), reader);
5473 gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), item);
5476 static void
5477 e_mail_reader_show_remote_content_popup (EMailReader *reader,
5478 GdkEventButton *event,
5479 GtkToggleButton *toggle_button)
5481 EMailDisplay *mail_display;
5482 GList *mails, *sites, *link;
5483 GtkWidget *popup_menu = NULL;
5485 g_return_if_fail (E_IS_MAIL_READER (reader));
5487 mail_display = e_mail_reader_get_mail_display (reader);
5488 mails = e_mail_reader_get_from_mails (mail_display);
5489 sites = e_mail_display_get_skipped_remote_content_sites (mail_display);
5491 for (link = mails; link; link = g_list_next (link)) {
5492 const gchar *mail = link->data;
5493 gchar *label;
5495 if (!mail || !*mail)
5496 continue;
5498 if (!popup_menu)
5499 popup_menu = gtk_menu_new ();
5501 if (*mail == '@')
5502 label = g_strdup_printf (_("Allow remote content for anyone from %s"), mail);
5503 else
5504 label = g_strdup_printf (_("Allow remote content for %s"), mail);
5506 e_mail_reader_add_remote_content_menu_item (reader, popup_menu, label, TRUE, mail);
5508 g_free (label);
5511 for (link = sites; link; link = g_list_next (link)) {
5512 const gchar *site = link->data;
5513 gchar *label;
5515 if (!site || !*site)
5516 continue;
5518 if (!popup_menu)
5519 popup_menu = gtk_menu_new ();
5521 label = g_strdup_printf (_("Allow remote content from %s"), site);
5523 e_mail_reader_add_remote_content_menu_item (reader, popup_menu, label, FALSE, site);
5525 g_free (label);
5528 g_list_free_full (mails, g_free);
5529 g_list_free_full (sites, g_free);
5531 if (popup_menu) {
5532 GtkWidget *box = gtk_widget_get_parent (GTK_WIDGET (toggle_button));
5533 GtkWidget *item;
5535 item = gtk_separator_menu_item_new ();
5536 gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), item);
5538 item = gtk_menu_item_new_with_label (_("Do not show this message again"));
5539 gtk_menu_shell_append (GTK_MENU_SHELL (popup_menu), item);
5540 g_signal_connect (item, "activate", G_CALLBACK (e_mail_reader_remote_content_disable_activate_cb), reader);
5542 gtk_toggle_button_set_active (toggle_button, TRUE);
5544 g_signal_connect (
5545 popup_menu, "deactivate",
5546 G_CALLBACK (e_mail_reader_remote_content_menu_deactivate_cb), toggle_button);
5548 gtk_widget_show_all (popup_menu);
5550 gtk_menu_attach_to_widget (GTK_MENU (popup_menu), box, NULL);
5552 g_object_set (popup_menu,
5553 "anchor-hints", (GDK_ANCHOR_FLIP_Y |
5554 GDK_ANCHOR_SLIDE |
5555 GDK_ANCHOR_RESIZE),
5556 NULL);
5558 gtk_menu_popup_at_widget (GTK_MENU (popup_menu),
5559 box,
5560 GDK_GRAVITY_SOUTH_WEST,
5561 GDK_GRAVITY_NORTH_WEST,
5562 (const GdkEvent *) event);
5566 static gboolean
5567 e_mail_reader_options_remote_content_button_press_cb (GtkToggleButton *toggle_button,
5568 GdkEventButton *event,
5569 EMailReader *reader)
5571 g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE);
5573 if (event && event->button == 1) {
5574 e_mail_reader_show_remote_content_popup (reader, event, toggle_button);
5575 return TRUE;
5578 return FALSE;
5581 static GtkWidget *
5582 e_mail_reader_create_remote_content_alert_button (EMailReader *reader)
5584 GtkWidget *box, *button, *arrow;
5586 box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
5588 gtk_style_context_add_class (gtk_widget_get_style_context (box), "linked");
5590 button = gtk_button_new_with_label (_("Load remote content"));
5591 gtk_container_add (GTK_CONTAINER (box), button);
5593 g_signal_connect (button, "clicked",
5594 G_CALLBACK (e_mail_reader_load_remote_content_clicked_cb), reader);
5596 button = gtk_toggle_button_new ();
5597 gtk_box_pack_start (GTK_BOX (box), button, FALSE, FALSE, 0);
5599 g_signal_connect (button, "button-press-event",
5600 G_CALLBACK (e_mail_reader_options_remote_content_button_press_cb), reader);
5602 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
5603 gtk_container_add (GTK_CONTAINER (button), arrow);
5605 gtk_widget_show_all (box);
5607 return box;
5610 static void
5611 mail_reader_display_load_changed_cb (EMailDisplay *mail_display,
5612 WebKitLoadEvent load_event,
5613 EMailReader *reader)
5615 EMailReaderPrivate *priv;
5617 g_return_if_fail (E_IS_MAIL_DISPLAY (mail_display));
5618 g_return_if_fail (E_IS_MAIL_READER (reader));
5620 priv = E_MAIL_READER_GET_PRIVATE (reader);
5621 g_return_if_fail (priv != NULL);
5623 if (load_event == WEBKIT_LOAD_STARTED) {
5624 if (priv->remote_content_alert)
5625 e_alert_response (priv->remote_content_alert, GTK_RESPONSE_CLOSE);
5626 return;
5629 if (load_event != WEBKIT_LOAD_FINISHED)
5630 return;
5632 if (!e_mail_display_has_skipped_remote_content_sites (mail_display))
5633 return;
5635 if (!priv->remote_content_alert) {
5636 EPreviewPane *preview_pane;
5637 GtkWidget *button;
5638 EAlert *alert;
5640 alert = e_alert_new ("mail:remote-content-info", NULL);
5641 button = e_mail_reader_create_remote_content_alert_button (reader);
5642 e_alert_add_widget (alert, button); /* button is consumed by the alert */
5643 preview_pane = e_mail_reader_get_preview_pane (reader);
5644 e_alert_sink_submit_alert (E_ALERT_SINK (preview_pane), alert);
5646 priv->remote_content_alert = alert;
5647 g_object_add_weak_pointer (G_OBJECT (priv->remote_content_alert), &priv->remote_content_alert);
5649 g_object_unref (alert);
5654 * e_mail_reader_connect_remote_content:
5655 * @reader: an #EMailReader
5657 * Connects signal handlers to manage remote content download around
5658 * the internal #EMailDisplay.
5660 void
5661 e_mail_reader_connect_remote_content (EMailReader *reader)
5663 EMailDisplay *mail_display;
5665 g_return_if_fail (E_IS_MAIL_READER (reader));
5667 mail_display = e_mail_reader_get_mail_display (reader);
5668 g_return_if_fail (E_IS_MAIL_DISPLAY (mail_display));
5670 g_signal_connect (mail_display, "load-changed",
5671 G_CALLBACK (mail_reader_display_load_changed_cb), reader);