1 /*
2  * e-mail-reader.c
3  *
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.
7  *
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.
12  *
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/>.
15  *
16  *
17  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
18  *
19  */
20 
21 #include "evolution-config.h"
22 
23 #include "e-mail-reader.h"
24 
25 #include <glib/gi18n.h>
26 #include <gdk/gdkkeysyms.h>
27 
28 #ifdef HAVE_XFREE
29 #include <X11/XF86keysym.h>
30 #endif
31 
32 #include <shell/e-shell-utils.h>
33 
34 #include <libemail-engine/libemail-engine.h>
35 
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>
39 
40 #include "e-mail-backend.h"
41 #include "e-mail-browser.h"
42 #include "e-mail-enumtypes.h"
43 #include "e-mail-label-action.h"
44 #include "e-mail-label-dialog.h"
45 #include "e-mail-label-list-store.h"
46 #include "e-mail-notes.h"
47 #include "e-mail-reader-utils.h"
48 #include "e-mail-remote-content-popover.h"
49 #include "e-mail-ui-session.h"
50 #include "e-mail-view.h"
51 #include "em-composer-utils.h"
52 #include "em-event.h"
53 #include "em-folder-selector.h"
54 #include "em-folder-tree.h"
55 #include "em-utils.h"
56 #include "mail-autofilter.h"
57 #include "mail-vfolder-ui.h"
58 #include "message-list.h"
59 
60 #define E_MAIL_READER_GET_PRIVATE(obj) \
61 	((EMailReaderPrivate *) g_object_get_qdata \
62 	(G_OBJECT (obj), quark_private))
63 
64 #define d(x)
65 
66 typedef struct _EMailReaderClosure EMailReaderClosure;
67 typedef struct _EMailReaderPrivate EMailReaderPrivate;
68 
69 struct _EMailReaderClosure {
70 	EMailReader *reader;
71 	EActivity *activity;
72 	CamelMimeMessage *message;
73 	CamelFolder *folder;
74 	gchar *message_uid;
75 	gboolean selection_is_html;
76 };
77 
78 struct _EMailReaderPrivate {
79 
80 	EMailForwardStyle forward_style;
81 	EMailReplyStyle reply_style;
82 
83 	/* This timer runs when the user selects a single message. */
84 	guint message_selected_timeout_id;
85 
86 	/* This allows message retrieval to be cancelled if another
87 	 * message is selected before the retrieval has completed. */
88 	GCancellable *retrieving_message;
89 
90 	/* These flags work to prevent a folder switch from
91 	 * automatically marking the message as read. We only want
92 	 * that to happen when the -user- selects a message. */
93 	guint folder_was_just_selected : 1;
94 	guint avoid_next_mark_as_seen : 1;
95 	guint did_try_to_open_message : 1;
96 
97 	guint group_by_threads : 1;
98 	guint mark_seen_always : 1;
99 	guint delete_selects_previous : 1;
100 
101 	/* to be able to start the mark_seen timeout only after
102 	 * the message is loaded into the EMailDisplay */
103 	gboolean schedule_mark_seen;
104 	guint schedule_mark_seen_interval;
105 
106 	gpointer followup_alert; /* weak pointer to an EAlert */
107 
108 	GSList *ongoing_operations; /* GCancellable * */
109 
110 	guint main_menu_label_merge_id;
111 	guint popup_menu_label_merge_id;
112 };
113 
114 enum {
115 	CHANGED,
116 	COMPOSER_CREATED,
117 	FOLDER_LOADED,
118 	MESSAGE_LOADED,
119 	MESSAGE_SEEN,
120 	SHOW_SEARCH_BAR,
121 	UPDATE_ACTIONS,
122 	LAST_SIGNAL
123 };
124 
125 /* Remembers the previously selected folder when transferring messages. */
126 static gchar *default_xfer_messages_uri;
127 
128 static GQuark quark_private;
129 static guint signals[LAST_SIGNAL];
130 
131 G_DEFINE_INTERFACE (EMailReader, e_mail_reader, G_TYPE_INITIALLY_UNOWNED)
132 
133 static void
134 mail_reader_set_display_formatter_for_message (EMailReader *reader,
135                                                EMailDisplay *display,
136                                                const gchar *message_uid,
137                                                CamelMimeMessage *message,
138                                                CamelFolder *folder);
139 
140 static void
mail_reader_closure_free(EMailReaderClosure * closure)141 mail_reader_closure_free (EMailReaderClosure *closure)
142 {
143 	g_clear_object (&closure->reader);
144 	g_clear_object (&closure->activity);
145 	g_clear_object (&closure->folder);
146 	g_clear_object (&closure->message);
147 	g_free (closure->message_uid);
148 
149 	g_slice_free (EMailReaderClosure, closure);
150 }
151 
152 static void
mail_reader_private_free(EMailReaderPrivate * priv)153 mail_reader_private_free (EMailReaderPrivate *priv)
154 {
155 	if (priv->message_selected_timeout_id > 0)
156 		g_source_remove (priv->message_selected_timeout_id);
157 
158 	if (priv->retrieving_message != NULL) {
159 		g_cancellable_cancel (priv->retrieving_message);
160 		g_object_unref (priv->retrieving_message);
161 		priv->retrieving_message = NULL;
162 	}
163 
164 	g_slice_free (EMailReaderPrivate, priv);
165 }
166 
167 static void
action_mail_add_sender_cb(GtkAction * action,EMailReader * reader)168 action_mail_add_sender_cb (GtkAction *action,
169                            EMailReader *reader)
170 {
171 	EShell *shell;
172 	EMailBackend *backend;
173 	EMailSession *session;
174 	EShellBackend *shell_backend;
175 	CamelInternetAddress *cia;
176 	CamelMessageInfo *info = NULL;
177 	CamelFolder *folder;
178 	GPtrArray *uids;
179 	const gchar *address;
180 	const gchar *message_uid;
181 
182 	folder = e_mail_reader_ref_folder (reader);
183 	backend = e_mail_reader_get_backend (reader);
184 	session = e_mail_backend_get_session (backend);
185 
186 	uids = e_mail_reader_get_selected_uids (reader);
187 	g_return_if_fail (uids != NULL && uids->len == 1);
188 	message_uid = g_ptr_array_index (uids, 0);
189 
190 	info = camel_folder_get_message_info (folder, message_uid);
191 	if (info == NULL)
192 		goto exit;
193 
194 	address = camel_message_info_get_from (info);
195 	if (address == NULL || *address == '\0')
196 		goto exit;
197 
198 	/* XXX EBookShellBackend should be listening for this
199 	 *     event.  Kind of kludgey, but works for now. */
200 	shell_backend = E_SHELL_BACKEND (backend);
201 	shell = e_shell_backend_get_shell (shell_backend);
202 	e_shell_event (shell, "contact-quick-add-email", (gpointer) address);
203 
204 	/* Remove this address from the photo cache. */
205 	cia = camel_internet_address_new ();
206 	if (camel_address_decode (CAMEL_ADDRESS (cia), address) > 0) {
207 		EPhotoCache *photo_cache;
208 		const gchar *address_only = NULL;
209 
210 		photo_cache = e_mail_ui_session_get_photo_cache (
211 			E_MAIL_UI_SESSION (session));
212 		if (camel_internet_address_get (cia, 0, NULL, &address_only))
213 			e_photo_cache_remove_photo (photo_cache, address_only);
214 	}
215 	g_object_unref (cia);
216 
217 exit:
218 	g_clear_object (&info);
219 	g_ptr_array_unref (uids);
220 
221 	g_clear_object (&folder);
222 }
223 
224 static void
action_add_to_address_book_cb(GtkAction * action,EMailReader * reader)225 action_add_to_address_book_cb (GtkAction *action,
226                                EMailReader *reader)
227 {
228 	EShell *shell;
229 	EMailBackend *backend;
230 	EMailDisplay *display;
231 	EMailSession *session;
232 	EShellBackend *shell_backend;
233 	CamelInternetAddress *cia;
234 	EPhotoCache *photo_cache;
235 	EWebView *web_view;
236 	CamelURL *curl;
237 	const gchar *uri;
238 	const gchar *address_only = NULL;
239 	gchar *email;
240 
241 	/* This action is defined in EMailDisplay. */
242 
243 	backend = e_mail_reader_get_backend (reader);
244 	session = e_mail_backend_get_session (backend);
245 
246 	display = e_mail_reader_get_mail_display (reader);
247 	if (display == NULL)
248 		return;
249 
250 	web_view = E_WEB_VIEW (display);
251 	uri = e_web_view_get_selected_uri (web_view);
252 	g_return_if_fail (uri != NULL);
253 
254 	curl = camel_url_new (uri, NULL);
255 	g_return_if_fail (curl != NULL);
256 
257 	if (curl->path == NULL || *curl->path == '\0')
258 		goto exit;
259 
260 	cia = camel_internet_address_new ();
261 	if (camel_address_decode (CAMEL_ADDRESS (cia), curl->path) < 0) {
262 		g_object_unref (cia);
263 		goto exit;
264 	}
265 
266 	/* XXX EBookShellBackend should be listening for this
267 	 *     event.  Kind of kludgey, but works for now. */
268 	shell_backend = E_SHELL_BACKEND (backend);
269 	shell = e_shell_backend_get_shell (shell_backend);
270 	email = camel_address_format (CAMEL_ADDRESS (cia));
271 	e_shell_event (shell, "contact-quick-add-email", email);
272 	g_free (email);
273 
274 	/* Remove this address from the photo cache. */
275 	photo_cache = e_mail_ui_session_get_photo_cache (
276 		E_MAIL_UI_SESSION (session));
277 	if (camel_internet_address_get (cia, 0, NULL, &address_only))
278 		e_photo_cache_remove_photo (photo_cache, address_only);
279 
280 	g_object_unref (cia);
281 
282 exit:
283 	camel_url_free (curl);
284 }
285 
286 static void
action_mail_charset_cb(GtkRadioAction * action,GtkRadioAction * current,EMailReader * reader)287 action_mail_charset_cb (GtkRadioAction *action,
288                         GtkRadioAction *current,
289                         EMailReader *reader)
290 {
291 	EMailDisplay *display;
292 	EMailFormatter *formatter;
293 
294 	if (action != current)
295 		return;
296 
297 	display = e_mail_reader_get_mail_display (reader);
298 	formatter = e_mail_display_get_formatter (display);
299 
300 	if (formatter != NULL) {
301 		const gchar *charset;
302 
303 		/* Charset for "Default" action will be NULL. */
304 		charset = g_object_get_data (G_OBJECT (action), "charset");
305 		e_mail_formatter_set_charset (formatter, charset);
306 	}
307 }
308 
309 static void
action_mail_check_for_junk_cb(GtkAction * action,EMailReader * reader)310 action_mail_check_for_junk_cb (GtkAction *action,
311                                EMailReader *reader)
312 {
313 	EMailBackend *backend;
314 	EMailSession *session;
315 	CamelFolder *folder;
316 	GPtrArray *uids;
317 
318 	folder = e_mail_reader_ref_folder (reader);
319 	backend = e_mail_reader_get_backend (reader);
320 	uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
321 
322 	session = e_mail_backend_get_session (backend);
323 
324 	mail_filter_folder (
325 		session, folder, uids,
326 		E_FILTER_SOURCE_JUNKTEST, FALSE);
327 
328 	g_clear_object (&folder);
329 	g_ptr_array_unref (uids);
330 }
331 
332 static void
mail_reader_copy_or_move_selected_messages(EMailReader * reader,gboolean is_move)333 mail_reader_copy_or_move_selected_messages (EMailReader *reader,
334 					    gboolean is_move)
335 {
336 	CamelFolder *folder;
337 	EMailBackend *backend;
338 	EMailSession *session;
339 	EMFolderSelector *selector;
340 	EMFolderTree *folder_tree;
341 	EMFolderTreeModel *model;
342 	GSettings *settings;
343 	GtkWidget *dialog;
344 	GtkWindow *window;
345 	GPtrArray *uids;
346 	const gchar *uri;
347 
348 	backend = e_mail_reader_get_backend (reader);
349 	session = e_mail_backend_get_session (backend);
350 
351 	folder = e_mail_reader_ref_folder (reader);
352 	window = e_mail_reader_get_window (reader);
353 	uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
354 
355 	model = em_folder_tree_model_get_default ();
356 
357 	dialog = em_folder_selector_new (window, model);
358 
359 	gtk_window_set_title (GTK_WINDOW (dialog), is_move ? _("Move to Folder") : _("Copy to Folder"));
360 
361 	selector = EM_FOLDER_SELECTOR (dialog);
362 	em_folder_selector_set_can_create (selector, TRUE);
363 	em_folder_selector_set_default_button_label (selector, is_move ? _("_Move") : _("C_opy"));
364 
365 	folder_tree = em_folder_selector_get_folder_tree (selector);
366 
367 	em_folder_tree_set_excluded (
368 		folder_tree,
369 		EMFT_EXCLUDE_NOSELECT |
370 		EMFT_EXCLUDE_VIRTUAL |
371 		EMFT_EXCLUDE_VTRASH);
372 
373 	settings = e_util_ref_settings ("org.gnome.evolution.mail");
374 
375 	if (!g_settings_get_boolean (settings, "copy-move-to-folder-preserve-expand"))
376 		gtk_tree_view_expand_all (GTK_TREE_VIEW (folder_tree));
377 
378 	g_clear_object (&settings);
379 
380 	em_folder_selector_maybe_collapse_archive_folders (selector);
381 
382 	if (default_xfer_messages_uri != NULL) {
383 		em_folder_tree_set_selected (
384 			folder_tree, default_xfer_messages_uri, FALSE);
385 	} else if (folder) {
386 		gchar *uri = e_mail_folder_uri_from_folder (folder);
387 
388 		if (uri) {
389 			em_folder_tree_set_selected (folder_tree, uri, FALSE);
390 			g_free (uri);
391 		}
392 	}
393 
394 	if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK)
395 		goto exit;
396 
397 	uri = em_folder_selector_get_selected_uri (selector);
398 
399 	g_free (default_xfer_messages_uri);
400 	default_xfer_messages_uri = g_strdup (uri);
401 
402 	if (uri != NULL)
403 		mail_transfer_messages (
404 			session, folder, uids,
405 			is_move, uri, 0, NULL, NULL);
406 
407 exit:
408 	gtk_widget_destroy (dialog);
409 
410 	g_clear_object (&folder);
411 	g_ptr_array_unref (uids);
412 }
413 
414 static void
mail_reader_manage_color_flag_on_selection(EMailReader * reader,const gchar * color)415 mail_reader_manage_color_flag_on_selection (EMailReader *reader,
416 					    const gchar *color)
417 {
418 	CamelFolder *folder;
419 
420 	g_return_if_fail (E_IS_MAIL_READER (reader));
421 
422 	folder = e_mail_reader_ref_folder (reader);
423 
424 	if (folder != NULL) {
425 		GPtrArray *uids;
426 		guint ii;
427 
428 		camel_folder_freeze (folder);
429 
430 		uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
431 
432 		for (ii = 0; ii < uids->len; ii++) {
433 			CamelMessageInfo *info;
434 
435 			info = camel_folder_get_message_info (folder, uids->pdata[ii]);
436 			if (info) {
437 				camel_message_info_set_user_tag (info, "color", color);
438 				g_object_unref (info);
439 			}
440 		}
441 
442 		g_ptr_array_unref (uids);
443 
444 		camel_folder_thaw (folder);
445 
446 		g_object_unref (folder);
447 	}
448 }
449 
450 static void
action_mail_color_assign_cb(GtkAction * action,EMailReader * reader)451 action_mail_color_assign_cb (GtkAction *action,
452 			     EMailReader *reader)
453 {
454 	GtkWidget *dialog;
455 
456 	dialog = gtk_color_chooser_dialog_new (NULL, e_mail_reader_get_window (reader));
457 
458 	if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
459 		GdkRGBA rgba;
460 		gchar *color;
461 
462 		gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (dialog), &rgba);
463 
464 		color = g_strdup_printf ("#%02X%02X%02X",
465 			0xFF & ((gint) (255 * rgba.red)),
466 			0xFF & ((gint) (255 * rgba.green)),
467 			0xFF & ((gint) (255 * rgba.blue)));
468 
469 		if (color) {
470 			mail_reader_manage_color_flag_on_selection (reader, color);
471 
472 			g_free (color);
473 		}
474 	}
475 
476 	gtk_widget_destroy (dialog);
477 }
478 
479 static void
action_mail_color_unset_cb(GtkAction * action,EMailReader * reader)480 action_mail_color_unset_cb (GtkAction *action,
481 			    EMailReader *reader)
482 {
483 	mail_reader_manage_color_flag_on_selection (reader, NULL);
484 }
485 
486 static void
action_mail_copy_cb(GtkAction * action,EMailReader * reader)487 action_mail_copy_cb (GtkAction *action,
488                      EMailReader *reader)
489 {
490 	mail_reader_copy_or_move_selected_messages (reader, FALSE);
491 }
492 
493 static gboolean
mail_reader_replace_vee_folder_with_real(CamelFolder ** inout_folder,const gchar * uid,gchar ** out_real_uid)494 mail_reader_replace_vee_folder_with_real (CamelFolder **inout_folder,
495 					  const gchar *uid,
496 					  gchar **out_real_uid)
497 {
498 	g_return_val_if_fail (inout_folder != NULL, FALSE);
499 	g_return_val_if_fail (CAMEL_IS_FOLDER (*inout_folder), FALSE);
500 	g_return_val_if_fail (uid != NULL, FALSE);
501 	g_return_val_if_fail (out_real_uid != NULL, FALSE);
502 
503 	*out_real_uid = NULL;
504 
505 	if (CAMEL_IS_VEE_FOLDER (*inout_folder)) {
506 		CamelMessageInfo *info;
507 
508 		info = camel_folder_get_message_info (*inout_folder, uid);
509 		if (info) {
510 			CamelFolder *real_folder;
511 
512 			real_folder = camel_vee_folder_get_location (CAMEL_VEE_FOLDER (*inout_folder), CAMEL_VEE_MESSAGE_INFO (info), out_real_uid);
513 
514 			if (real_folder && *out_real_uid) {
515 				g_object_unref (*inout_folder);
516 
517 				*inout_folder = g_object_ref (real_folder);
518 			}
519 
520 			g_object_unref (info);
521 		} else {
522 			g_warn_if_reached ();
523 		}
524 	}
525 
526 	return *out_real_uid != NULL;
527 }
528 
529 static void
action_mail_edit_note_cb(GtkAction * action,EMailReader * reader)530 action_mail_edit_note_cb (GtkAction *action,
531 			  EMailReader *reader)
532 {
533 	CamelFolder *folder;
534 	GPtrArray *uids;
535 
536 	folder = e_mail_reader_ref_folder (reader);
537 	uids = e_mail_reader_get_selected_uids (reader);
538 
539 	if (uids && uids->len == 1) {
540 		gchar *real_uid = NULL;
541 		const gchar *uid = uids->pdata[0];
542 
543 		if (mail_reader_replace_vee_folder_with_real (&folder, uid, &real_uid))
544 			uid = real_uid;
545 
546 		e_mail_notes_edit (e_mail_reader_get_window (reader), folder, uid);
547 
548 		g_free (real_uid);
549 	} else {
550 		g_warn_if_reached ();
551 	}
552 
553 	g_clear_object (&folder);
554 	g_ptr_array_unref (uids);
555 }
556 
557 typedef struct {
558 	CamelFolder *folder;
559 	gchar *uid;
560 } DeleteNoteData;
561 
562 static void
delete_note_data_free(gpointer ptr)563 delete_note_data_free (gpointer ptr)
564 {
565 	DeleteNoteData *dnd = ptr;
566 
567 	if (dnd) {
568 		g_clear_object (&dnd->folder);
569 		g_free (dnd->uid);
570 		g_slice_free (DeleteNoteData, dnd);
571 	}
572 }
573 
574 static void
mail_delete_note_thread(EAlertSinkThreadJobData * job_data,gpointer user_data,GCancellable * cancellable,GError ** error)575 mail_delete_note_thread (EAlertSinkThreadJobData *job_data,
576 			 gpointer user_data,
577 			 GCancellable *cancellable,
578 			 GError **error)
579 {
580 	DeleteNoteData *dnd = user_data;
581 
582 	g_return_if_fail (dnd != NULL);
583 	g_return_if_fail (CAMEL_IS_FOLDER (dnd->folder));
584 	g_return_if_fail (dnd->uid != NULL);
585 
586 	e_mail_notes_remove_sync (dnd->folder, dnd->uid, cancellable, error);
587 }
588 
589 static void
action_mail_delete_note_cb(GtkAction * action,EMailReader * reader)590 action_mail_delete_note_cb (GtkAction *action,
591 			    EMailReader *reader)
592 {
593 	CamelFolder *folder;
594 	GPtrArray *uids;
595 
596 	folder = e_mail_reader_ref_folder (reader);
597 	uids = e_mail_reader_get_selected_uids (reader);
598 
599 	if (uids && uids->len == 1) {
600 		DeleteNoteData *dnd;
601 		EAlertSink *alert_sink;
602 		EActivity *activity;
603 		gchar *full_display_name;
604 		gchar *real_uid = NULL;
605 		const gchar *uid = uids->pdata[0];
606 
607 		if (mail_reader_replace_vee_folder_with_real (&folder, uid, &real_uid))
608 			uid = real_uid;
609 
610 		dnd = g_slice_new0 (DeleteNoteData);
611 		dnd->folder = g_object_ref (folder);
612 		dnd->uid = g_strdup (uid);
613 
614 		full_display_name = e_mail_folder_to_full_display_name (folder, NULL);
615 		alert_sink = e_mail_reader_get_alert_sink (reader);
616 
617 		activity = e_alert_sink_submit_thread_job (alert_sink,
618 			_("Deleting message note…"),
619 			"mail:failed-delete-note",
620 			full_display_name ? full_display_name : camel_folder_get_full_name (folder),
621 			mail_delete_note_thread, dnd, delete_note_data_free);
622 
623 		if (activity)
624 			e_shell_backend_add_activity (E_SHELL_BACKEND (e_mail_reader_get_backend (reader)), activity);
625 
626 		g_clear_object (&activity);
627 		g_free (full_display_name);
628 		g_free (real_uid);
629 	} else {
630 		g_warn_if_reached ();
631 	}
632 
633 	g_clear_object (&folder);
634 	g_ptr_array_unref (uids);
635 }
636 
637 static void
action_mail_delete_cb(GtkAction * action,EMailReader * reader)638 action_mail_delete_cb (GtkAction *action,
639                        EMailReader *reader)
640 {
641 	guint32 mask = CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_DELETED;
642 	guint32 set = CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_DELETED;
643 
644 	if (!e_mail_reader_confirm_delete (reader))
645 		return;
646 
647 	/* FIXME Verify all selected messages are deletable.
648 	 *       But handle it by disabling this action. */
649 
650 	if (e_mail_reader_mark_selected (reader, mask, set) != 0 &&
651 	    !e_mail_reader_close_on_delete_or_junk (reader)) {
652 		if (e_mail_reader_get_delete_selects_previous (reader))
653 			e_mail_reader_select_previous_message (reader, FALSE);
654 		else
655 			e_mail_reader_select_next_message (reader, FALSE);
656 	}
657 }
658 
659 static void
action_mail_filter_on_mailing_list_cb(GtkAction * action,EMailReader * reader)660 action_mail_filter_on_mailing_list_cb (GtkAction *action,
661                                        EMailReader *reader)
662 {
663 	e_mail_reader_create_filter_from_selected (reader, AUTO_MLIST);
664 }
665 
666 static void
action_mail_filter_on_recipients_cb(GtkAction * action,EMailReader * reader)667 action_mail_filter_on_recipients_cb (GtkAction *action,
668                                      EMailReader *reader)
669 {
670 	e_mail_reader_create_filter_from_selected (reader, AUTO_TO);
671 }
672 
673 static void
action_mail_filter_on_sender_cb(GtkAction * action,EMailReader * reader)674 action_mail_filter_on_sender_cb (GtkAction *action,
675                                  EMailReader *reader)
676 {
677 	e_mail_reader_create_filter_from_selected (reader, AUTO_FROM);
678 }
679 
680 static void
action_mail_filter_on_subject_cb(GtkAction * action,EMailReader * reader)681 action_mail_filter_on_subject_cb (GtkAction *action,
682                                   EMailReader *reader)
683 {
684 	e_mail_reader_create_filter_from_selected (reader, AUTO_SUBJECT);
685 }
686 
687 static void
action_mail_filters_apply_cb(GtkAction * action,EMailReader * reader)688 action_mail_filters_apply_cb (GtkAction *action,
689                               EMailReader *reader)
690 {
691 	EMailBackend *backend;
692 	EMailSession *session;
693 	CamelFolder *folder;
694 	GPtrArray *uids;
695 
696 	folder = e_mail_reader_ref_folder (reader);
697 	backend = e_mail_reader_get_backend (reader);
698 	uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
699 
700 	session = e_mail_backend_get_session (backend);
701 
702 	mail_filter_folder (
703 		session, folder, uids,
704 		E_FILTER_SOURCE_DEMAND, FALSE);
705 
706 	g_clear_object (&folder);
707 	g_ptr_array_unref (uids);
708 }
709 
710 static void
action_mail_remove_attachments_cb(GtkAction * action,EMailReader * reader)711 action_mail_remove_attachments_cb (GtkAction *action,
712                                    EMailReader *reader)
713 {
714 	e_mail_reader_remove_attachments (reader);
715 }
716 
717 static void
action_mail_remove_duplicates_cb(GtkAction * action,EMailReader * reader)718 action_mail_remove_duplicates_cb (GtkAction *action,
719                                   EMailReader *reader)
720 {
721 	e_mail_reader_remove_duplicates (reader);
722 }
723 
724 static void
action_mail_find_cb(GtkAction * action,EMailReader * reader)725 action_mail_find_cb (GtkAction *action,
726                      EMailReader *reader)
727 {
728 	e_mail_reader_show_search_bar (reader);
729 }
730 
731 static void
action_mail_flag_clear_cb(GtkAction * action,EMailReader * reader)732 action_mail_flag_clear_cb (GtkAction *action,
733                            EMailReader *reader)
734 {
735 	CamelFolder *folder;
736 	GtkWindow *window;
737 	GPtrArray *uids;
738 
739 	folder = e_mail_reader_ref_folder (reader);
740 	uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
741 	window = e_mail_reader_get_window (reader);
742 
743 	em_utils_flag_for_followup_clear (window, folder, uids);
744 
745 	e_mail_reader_reload (reader);
746 
747 	g_clear_object (&folder);
748 	g_ptr_array_unref (uids);
749 }
750 
751 static void
action_mail_flag_completed_cb(GtkAction * action,EMailReader * reader)752 action_mail_flag_completed_cb (GtkAction *action,
753                                EMailReader *reader)
754 {
755 	CamelFolder *folder;
756 	GtkWindow *window;
757 	GPtrArray *uids;
758 
759 	folder = e_mail_reader_ref_folder (reader);
760 	uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
761 	window = e_mail_reader_get_window (reader);
762 
763 	em_utils_flag_for_followup_completed (window, folder, uids);
764 
765 	e_mail_reader_reload (reader);
766 
767 	g_clear_object (&folder);
768 	g_ptr_array_unref (uids);
769 }
770 
771 static void
action_mail_flag_for_followup_cb(GtkAction * action,EMailReader * reader)772 action_mail_flag_for_followup_cb (GtkAction *action,
773                                   EMailReader *reader)
774 {
775 	CamelFolder *folder;
776 	GPtrArray *uids;
777 
778 	folder = e_mail_reader_ref_folder (reader);
779 	uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
780 
781 	em_utils_flag_for_followup (reader, folder, uids);
782 
783 	e_mail_reader_reload (reader);
784 
785 	g_clear_object (&folder);
786 	g_ptr_array_unref (uids);
787 }
788 
789 static void
action_mail_forward_cb(GtkAction * action,EMailReader * reader)790 action_mail_forward_cb (GtkAction *action,
791                         EMailReader *reader)
792 {
793 	GtkWindow *window;
794 	GPtrArray *uids;
795 
796 	window = e_mail_reader_get_window (reader);
797 	uids = e_mail_reader_get_selected_uids (reader);
798 	g_return_if_fail (uids != NULL);
799 
800 	if (em_utils_ask_open_many (window, uids->len)) {
801 		CamelFolder *folder;
802 
803 		folder = e_mail_reader_ref_folder (reader);
804 
805 		e_mail_reader_forward_messages (
806 			reader, folder, uids,
807 			e_mail_reader_get_forward_style (reader));
808 
809 		g_clear_object (&folder);
810 	}
811 
812 	g_ptr_array_unref (uids);
813 }
814 
815 static void
action_mail_forward_attached_cb(GtkAction * action,EMailReader * reader)816 action_mail_forward_attached_cb (GtkAction *action,
817                                  EMailReader *reader)
818 {
819 	GtkWindow *window;
820 	GPtrArray *uids;
821 
822 	window = e_mail_reader_get_window (reader);
823 	uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
824 	g_return_if_fail (uids != NULL);
825 
826 	if (em_utils_ask_open_many (window, uids->len)) {
827 		CamelFolder *folder;
828 
829 		folder = e_mail_reader_ref_folder (reader);
830 
831 		e_mail_reader_forward_messages (
832 			reader, folder, uids,
833 			E_MAIL_FORWARD_STYLE_ATTACHED);
834 
835 		g_clear_object (&folder);
836 	}
837 
838 	g_ptr_array_unref (uids);
839 }
840 
841 static void
action_mail_forward_inline_cb(GtkAction * action,EMailReader * reader)842 action_mail_forward_inline_cb (GtkAction *action,
843                                EMailReader *reader)
844 {
845 	GtkWindow *window;
846 	GPtrArray *uids;
847 
848 	window = e_mail_reader_get_window (reader);
849 	uids = e_mail_reader_get_selected_uids (reader);
850 	g_return_if_fail (uids != NULL);
851 
852 	if (em_utils_ask_open_many (window, uids->len)) {
853 		CamelFolder *folder;
854 
855 		folder = e_mail_reader_ref_folder (reader);
856 
857 		e_mail_reader_forward_messages (
858 			reader, folder, uids,
859 			E_MAIL_FORWARD_STYLE_INLINE);
860 
861 		g_clear_object (&folder);
862 	}
863 
864 	g_ptr_array_unref (uids);
865 }
866 
867 static void
action_mail_forward_quoted_cb(GtkAction * action,EMailReader * reader)868 action_mail_forward_quoted_cb (GtkAction *action,
869                                EMailReader *reader)
870 {
871 	GtkWindow *window;
872 	GPtrArray *uids;
873 
874 	window = e_mail_reader_get_window (reader);
875 	uids = e_mail_reader_get_selected_uids (reader);
876 	g_return_if_fail (uids != NULL);
877 
878 	if (em_utils_ask_open_many (window, uids->len)) {
879 		CamelFolder *folder;
880 
881 		folder = e_mail_reader_ref_folder (reader);
882 
883 		e_mail_reader_forward_messages (
884 			reader, folder, uids,
885 			E_MAIL_FORWARD_STYLE_QUOTED);
886 
887 		g_clear_object (&folder);
888 	}
889 
890 	g_ptr_array_unref (uids);
891 }
892 
893 static void
action_mail_label_new_cb(GtkAction * action,EMailReader * reader)894 action_mail_label_new_cb (GtkAction *action,
895                           EMailReader *reader)
896 {
897 	EMailLabelDialog *label_dialog;
898 	EMailLabelListStore *label_store;
899 	EMailBackend *backend;
900 	EMailSession *session;
901 	GtkTreeModel *model;
902 	GtkTreeIter iter;
903 	GtkWidget *dialog;
904 	GPtrArray *uids;
905 	GdkColor label_color;
906 	const gchar *label_name;
907 	gchar *label_tag;
908 	gint n_children;
909 	guint ii;
910 
911 	dialog = e_mail_label_dialog_new (e_mail_reader_get_window (reader));
912 
913 	gtk_window_set_title (GTK_WINDOW (dialog), _("Add Label"));
914 
915 	if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_OK)
916 		goto exit;
917 
918 	backend = e_mail_reader_get_backend (reader);
919 	session = e_mail_backend_get_session (backend);
920 	label_store = e_mail_ui_session_get_label_store (
921 		E_MAIL_UI_SESSION (session));
922 
923 	label_dialog = E_MAIL_LABEL_DIALOG (dialog);
924 	label_name = e_mail_label_dialog_get_label_name (label_dialog);
925 	e_mail_label_dialog_get_label_color (label_dialog, &label_color);
926 
927 	e_mail_label_list_store_set (
928 		label_store, NULL, label_name, &label_color);
929 
930 	/* XXX This is awkward.  We've added a new label to the list store
931 	 *     but we don't have the new label's tag nor an iterator to use
932 	 *     to fetch it.  We know the label was appended to the store,
933 	 *     so we have to dig it out manually.  EMailLabelListStore API
934 	 *     probably needs some rethinking. */
935 	model = GTK_TREE_MODEL (label_store);
936 	n_children = gtk_tree_model_iter_n_children (model, NULL);
937 	g_warn_if_fail (gtk_tree_model_iter_nth_child (model, &iter, NULL, n_children - 1));
938 	label_tag = e_mail_label_list_store_get_tag (label_store, &iter);
939 
940 	uids = e_mail_reader_get_selected_uids (reader);
941 	if (uids) {
942 		CamelFolder *folder;
943 
944 		folder = e_mail_reader_ref_folder (reader);
945 
946 		for (ii = 0; ii < uids->len; ii++) {
947 			camel_folder_set_message_user_flag (
948 				folder, uids->pdata[ii], label_tag, TRUE);
949 		}
950 
951 		g_clear_object (&folder);
952 		g_ptr_array_unref (uids);
953 	}
954 
955 	g_free (label_tag);
956 
957  exit:
958 	gtk_widget_destroy (dialog);
959 }
960 
961 static void
action_mail_label_none_cb(GtkAction * action,EMailReader * reader)962 action_mail_label_none_cb (GtkAction *action,
963                            EMailReader *reader)
964 {
965 	EMailBackend *backend;
966 	EMailSession *session;
967 	EMailLabelListStore *label_store;
968 	CamelFolder *folder;
969 	GtkTreeIter iter;
970 	GPtrArray *uids;
971 	gboolean valid;
972 	guint ii;
973 
974 	uids = e_mail_reader_get_selected_uids (reader);
975 	if (!uids)
976 		return;
977 
978 	backend = e_mail_reader_get_backend (reader);
979 	session = e_mail_backend_get_session (backend);
980 	label_store = e_mail_ui_session_get_label_store (
981 		E_MAIL_UI_SESSION (session));
982 
983 	folder = e_mail_reader_ref_folder (reader);
984 
985 	valid = gtk_tree_model_get_iter_first (
986 		GTK_TREE_MODEL (label_store), &iter);
987 
988 	while (valid) {
989 		gchar *tag;
990 
991 		tag = e_mail_label_list_store_get_tag (label_store, &iter);
992 
993 		for (ii = 0; ii < uids->len; ii++) {
994 			camel_folder_set_message_user_flag (
995 				folder, uids->pdata[ii], tag, FALSE);
996 			camel_folder_set_message_user_tag (
997 				folder, uids->pdata[ii], "label", NULL);
998 		}
999 
1000 		g_free (tag);
1001 
1002 		valid = gtk_tree_model_iter_next (
1003 			GTK_TREE_MODEL (label_store), &iter);
1004 	}
1005 
1006 	g_clear_object (&folder);
1007 	g_ptr_array_unref (uids);
1008 }
1009 
1010 static void
action_mail_load_images_cb(GtkAction * action,EMailReader * reader)1011 action_mail_load_images_cb (GtkAction *action,
1012                             EMailReader *reader)
1013 {
1014 	EMailDisplay *display;
1015 
1016 	display = e_mail_reader_get_mail_display (reader);
1017 
1018 	e_mail_display_load_images (display);
1019 }
1020 
1021 static void
action_mail_mark_important_cb(GtkAction * action,EMailReader * reader)1022 action_mail_mark_important_cb (GtkAction *action,
1023                                EMailReader *reader)
1024 {
1025 	guint32 mask = CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_DELETED;
1026 	guint32 set = CAMEL_MESSAGE_FLAGGED;
1027 
1028 	e_mail_reader_mark_selected (reader, mask, set);
1029 }
1030 
1031 static void
action_mail_mark_junk_cb(GtkAction * action,EMailReader * reader)1032 action_mail_mark_junk_cb (GtkAction *action,
1033                           EMailReader *reader)
1034 {
1035 	guint32 mask =
1036 		CAMEL_MESSAGE_SEEN |
1037 		CAMEL_MESSAGE_JUNK |
1038 		CAMEL_MESSAGE_NOTJUNK |
1039 		CAMEL_MESSAGE_JUNK_LEARN;
1040 	guint32 set =
1041 		CAMEL_MESSAGE_SEEN |
1042 		CAMEL_MESSAGE_JUNK |
1043 		CAMEL_MESSAGE_JUNK_LEARN;
1044 
1045 	if (e_mail_reader_mark_selected (reader, mask, set) != 0 &&
1046 	    !e_mail_reader_close_on_delete_or_junk (reader)) {
1047 		if (e_mail_reader_get_delete_selects_previous (reader))
1048 			e_mail_reader_select_previous_message (reader, TRUE);
1049 		else
1050 			e_mail_reader_select_next_message (reader, TRUE);
1051 	}
1052 }
1053 
1054 static void
action_mail_mark_notjunk_cb(GtkAction * action,EMailReader * reader)1055 action_mail_mark_notjunk_cb (GtkAction *action,
1056                              EMailReader *reader)
1057 {
1058 	guint32 mask =
1059 		CAMEL_MESSAGE_JUNK |
1060 		CAMEL_MESSAGE_NOTJUNK |
1061 		CAMEL_MESSAGE_JUNK_LEARN;
1062 	guint32 set  =
1063 		CAMEL_MESSAGE_NOTJUNK |
1064 		CAMEL_MESSAGE_JUNK_LEARN;
1065 
1066 	if (e_mail_reader_mark_selected (reader, mask, set) != 0) {
1067 		if (e_mail_reader_get_delete_selects_previous (reader))
1068 			e_mail_reader_select_previous_message (reader, TRUE);
1069 		else
1070 			e_mail_reader_select_next_message (reader, TRUE);
1071 	}
1072 }
1073 
1074 static void
action_mail_mark_read_cb(GtkAction * action,EMailReader * reader)1075 action_mail_mark_read_cb (GtkAction *action,
1076                           EMailReader *reader)
1077 {
1078 	guint32 mask = CAMEL_MESSAGE_SEEN;
1079 	guint32 set = CAMEL_MESSAGE_SEEN;
1080 
1081 	e_mail_reader_mark_selected (reader, mask, set);
1082 }
1083 
1084 static void
action_mail_mark_unimportant_cb(GtkAction * action,EMailReader * reader)1085 action_mail_mark_unimportant_cb (GtkAction *action,
1086                                  EMailReader *reader)
1087 {
1088 	guint32 mask = CAMEL_MESSAGE_FLAGGED;
1089 	guint32 set = 0;
1090 
1091 	e_mail_reader_mark_selected (reader, mask, set);
1092 }
1093 
1094 static void
action_mail_mark_ignore_thread_sub_cb(GtkAction * action,EMailReader * reader)1095 action_mail_mark_ignore_thread_sub_cb (GtkAction *action,
1096 					 EMailReader *reader)
1097 {
1098 	e_mail_reader_mark_selected_ignore_thread (reader, E_IGNORE_THREAD_SUBSET_SET);
1099 }
1100 
1101 static void
action_mail_mark_unignore_thread_sub_cb(GtkAction * action,EMailReader * reader)1102 action_mail_mark_unignore_thread_sub_cb (GtkAction *action,
1103 					 EMailReader *reader)
1104 {
1105 	e_mail_reader_mark_selected_ignore_thread (reader, E_IGNORE_THREAD_SUBSET_UNSET);
1106 }
1107 
1108 static void
action_mail_mark_ignore_thread_whole_cb(GtkAction * action,EMailReader * reader)1109 action_mail_mark_ignore_thread_whole_cb (GtkAction *action,
1110 					 EMailReader *reader)
1111 {
1112 	e_mail_reader_mark_selected_ignore_thread (reader, E_IGNORE_THREAD_WHOLE_SET);
1113 }
1114 
1115 static void
action_mail_mark_unignore_thread_whole_cb(GtkAction * action,EMailReader * reader)1116 action_mail_mark_unignore_thread_whole_cb (GtkAction *action,
1117 					   EMailReader *reader)
1118 {
1119 	e_mail_reader_mark_selected_ignore_thread (reader, E_IGNORE_THREAD_WHOLE_UNSET);
1120 }
1121 
1122 static void
action_mail_mark_unread_cb(GtkAction * action,EMailReader * reader)1123 action_mail_mark_unread_cb (GtkAction *action,
1124                             EMailReader *reader)
1125 {
1126 	GtkWidget *message_list;
1127 	EMFolderTreeModel *model;
1128 	CamelFolder *folder;
1129 	guint32 mask = CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_DELETED;
1130 	guint32 set = 0;
1131 	guint n_marked;
1132 
1133 	message_list = e_mail_reader_get_message_list (reader);
1134 
1135 	n_marked = e_mail_reader_mark_selected (reader, mask, set);
1136 
1137 	if (MESSAGE_LIST (message_list)->seen_id != 0) {
1138 		g_source_remove (MESSAGE_LIST (message_list)->seen_id);
1139 		MESSAGE_LIST (message_list)->seen_id = 0;
1140 	}
1141 
1142 	folder = e_mail_reader_ref_folder (reader);
1143 
1144 	/* Notify the tree model that the user has marked messages as
1145 	 * unread so it doesn't mistake the event as new mail arriving. */
1146 	model = em_folder_tree_model_get_default ();
1147 	em_folder_tree_model_user_marked_unread (model, folder, n_marked);
1148 
1149 	g_clear_object (&folder);
1150 }
1151 
1152 static void
action_mail_message_edit_cb(GtkAction * action,EMailReader * reader)1153 action_mail_message_edit_cb (GtkAction *action,
1154                              EMailReader *reader)
1155 {
1156 	EShell *shell;
1157 	EMailBackend *backend;
1158 	ESourceRegistry *registry;
1159 	CamelFolder *folder;
1160 	GPtrArray *uids;
1161 	gboolean replace;
1162 
1163 	uids = e_mail_reader_get_selected_uids (reader);
1164 	g_return_if_fail (uids != NULL);
1165 
1166 	backend = e_mail_reader_get_backend (reader);
1167 	shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
1168 	registry = e_shell_get_registry (shell);
1169 
1170 	folder = e_mail_reader_ref_folder (reader);
1171 	replace = em_utils_folder_is_drafts (registry, folder);
1172 	e_mail_reader_edit_messages (reader, folder, uids, replace, replace);
1173 	g_clear_object (&folder);
1174 
1175 	g_ptr_array_unref (uids);
1176 }
1177 
1178 typedef struct _CreateComposerData {
1179 	EMailReader *reader;
1180 	CamelMimeMessage *message;
1181 	CamelFolder *folder;
1182 	const gchar *message_uid; /* In the Camel string pool */
1183 	gboolean is_redirect;
1184 } CreateComposerData;
1185 
1186 static void
mail_reader_new_composer_created_cb(GObject * source_object,GAsyncResult * result,gpointer user_data)1187 mail_reader_new_composer_created_cb (GObject *source_object,
1188 				     GAsyncResult *result,
1189 				     gpointer user_data)
1190 {
1191 	CreateComposerData *ccd = user_data;
1192 	EMsgComposer *composer;
1193 	GError *error = NULL;
1194 
1195 	g_return_if_fail (ccd != NULL);
1196 
1197 	composer = e_msg_composer_new_finish (result, &error);
1198 	if (error) {
1199 		g_warning ("%s: Failed to create msg composer: %s", G_STRFUNC, error->message);
1200 		g_clear_error (&error);
1201 	} else {
1202 		if (ccd->is_redirect)
1203 			em_utils_redirect_message (composer, ccd->message);
1204 		else
1205 			em_utils_compose_new_message_with_selection (composer, ccd->folder, ccd->message_uid);
1206 
1207 		e_mail_reader_composer_created (ccd->reader, composer, ccd->message);
1208 	}
1209 
1210 	g_clear_object (&ccd->reader);
1211 	g_clear_object (&ccd->message);
1212 	g_clear_object (&ccd->folder);
1213 	camel_pstring_free (ccd->message_uid);
1214 	g_slice_free (CreateComposerData, ccd);
1215 }
1216 
1217 static void
action_mail_message_new_cb(GtkAction * action,EMailReader * reader)1218 action_mail_message_new_cb (GtkAction *action,
1219                             EMailReader *reader)
1220 {
1221 	EShell *shell;
1222 	EMailBackend *backend;
1223 	EShellBackend *shell_backend;
1224 	CamelFolder *folder;
1225 	CreateComposerData *ccd;
1226 	GPtrArray *selected_uids = NULL;
1227 	const gchar *selected_uid = NULL;
1228 
1229 	folder = e_mail_reader_ref_folder (reader);
1230 	backend = e_mail_reader_get_backend (reader);
1231 
1232 	selected_uids = e_mail_reader_get_selected_uids (reader);
1233 	if (selected_uids && selected_uids->len > 0)
1234 		selected_uid = g_ptr_array_index (selected_uids, 0);
1235 
1236 	if (!selected_uid) {
1237 		GtkWidget *message_list;
1238 
1239 		message_list = e_mail_reader_get_message_list (reader);
1240 		if (message_list)
1241 			selected_uid = MESSAGE_LIST (message_list)->cursor_uid;
1242 	}
1243 
1244 	shell_backend = E_SHELL_BACKEND (backend);
1245 	shell = e_shell_backend_get_shell (shell_backend);
1246 
1247 	ccd = g_slice_new0 (CreateComposerData);
1248 	ccd->reader = g_object_ref (reader);
1249 	ccd->folder = folder;
1250 	ccd->message_uid = camel_pstring_strdup (selected_uid);
1251 	ccd->is_redirect = FALSE;
1252 
1253 	e_msg_composer_new (shell, mail_reader_new_composer_created_cb, ccd);
1254 
1255 	if (selected_uids)
1256 		g_ptr_array_unref (selected_uids);
1257 }
1258 
1259 static void
action_mail_message_open_cb(GtkAction * action,EMailReader * reader)1260 action_mail_message_open_cb (GtkAction *action,
1261                              EMailReader *reader)
1262 {
1263 	e_mail_reader_open_selected_mail (reader);
1264 }
1265 
1266 static void
action_mail_archive_cb(GtkAction * action,EMailReader * reader)1267 action_mail_archive_cb (GtkAction *action,
1268 			EMailReader *reader)
1269 {
1270 	CamelFolder *folder;
1271 	EMailBackend *backend;
1272 	EMailSession *session;
1273 	GPtrArray *uids;
1274 	gchar *archive_folder;
1275 
1276 	backend = e_mail_reader_get_backend (reader);
1277 	session = e_mail_backend_get_session (backend);
1278 
1279 	uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
1280 	g_return_if_fail (uids != NULL);
1281 
1282 	folder = e_mail_reader_ref_folder (reader);
1283 	archive_folder = em_utils_get_archive_folder_uri_from_folder (folder, backend, uids, TRUE);
1284 
1285 	if (archive_folder != NULL)
1286 		mail_transfer_messages (
1287 			session, folder, uids,
1288 			TRUE, archive_folder, 0, NULL, NULL);
1289 
1290 	g_clear_object (&folder);
1291 	g_ptr_array_unref (uids);
1292 	g_free (archive_folder);
1293 }
1294 
1295 static void
action_mail_move_cb(GtkAction * action,EMailReader * reader)1296 action_mail_move_cb (GtkAction *action,
1297                      EMailReader *reader)
1298 {
1299 	mail_reader_copy_or_move_selected_messages (reader, TRUE);
1300 }
1301 
1302 static void
action_mail_next_cb(GtkAction * action,EMailReader * reader)1303 action_mail_next_cb (GtkAction *action,
1304                      EMailReader *reader)
1305 {
1306 	GtkWidget *message_list;
1307 	MessageListSelectDirection direction;
1308 	guint32 flags, mask;
1309 
1310 	direction = MESSAGE_LIST_SELECT_NEXT;
1311 	flags = 0;
1312 	mask = 0;
1313 
1314 	message_list = e_mail_reader_get_message_list (reader);
1315 
1316 	message_list_select (
1317 		MESSAGE_LIST (message_list), direction, flags, mask);
1318 }
1319 
1320 static void
action_mail_next_important_cb(GtkAction * action,EMailReader * reader)1321 action_mail_next_important_cb (GtkAction *action,
1322                                EMailReader *reader)
1323 {
1324 	GtkWidget *message_list;
1325 	MessageListSelectDirection direction;
1326 	guint32 flags, mask;
1327 
1328 	direction = MESSAGE_LIST_SELECT_NEXT | MESSAGE_LIST_SELECT_WRAP;
1329 	flags = CAMEL_MESSAGE_FLAGGED;
1330 	mask = CAMEL_MESSAGE_FLAGGED;
1331 
1332 	message_list = e_mail_reader_get_message_list (reader);
1333 
1334 	message_list_select (
1335 		MESSAGE_LIST (message_list), direction, flags, mask);
1336 }
1337 
1338 static void
action_mail_next_thread_cb(GtkAction * action,EMailReader * reader)1339 action_mail_next_thread_cb (GtkAction *action,
1340                             EMailReader *reader)
1341 {
1342 	GtkWidget *message_list;
1343 
1344 	message_list = e_mail_reader_get_message_list (reader);
1345 
1346 	message_list_select_next_thread (MESSAGE_LIST (message_list));
1347 }
1348 
1349 static void
mail_reader_select_unread(EMailReader * reader,gboolean move_forward)1350 mail_reader_select_unread (EMailReader *reader,
1351 			   gboolean move_forward)
1352 {
1353 	GtkWidget *message_list;
1354 	MessageListSelectDirection direction;
1355 	guint32 flags, mask;
1356 
1357 	g_return_if_fail (E_IS_MAIL_READER (reader));
1358 
1359 	direction = (move_forward ? MESSAGE_LIST_SELECT_NEXT : MESSAGE_LIST_SELECT_PREVIOUS) |
1360 		    MESSAGE_LIST_SELECT_WRAP | MESSAGE_LIST_SELECT_INCLUDE_COLLAPSED;
1361 	flags = 0;
1362 	mask = CAMEL_MESSAGE_SEEN;
1363 
1364 	message_list = e_mail_reader_get_message_list (reader);
1365 
1366 	if (!message_list_select (MESSAGE_LIST (message_list), direction, flags, mask)) {
1367 		GtkWindow *window;
1368 
1369 		window = e_mail_reader_get_window (reader);
1370 		if (E_IS_SHELL_WINDOW (window)) {
1371 			EShellWindow *shell_window;
1372 			EMFolderTree *folder_tree = NULL;
1373 			const gchar *active_view;
1374 
1375 			shell_window = E_SHELL_WINDOW (window);
1376 			active_view = e_shell_window_get_active_view (shell_window);
1377 
1378 			if (g_strcmp0 (active_view, "mail") == 0) {
1379 				EShellView *shell_view;
1380 				EShellSidebar *shell_sidebar;
1381 
1382 				shell_view = e_shell_window_get_shell_view (shell_window, "mail");
1383 				shell_sidebar = e_shell_view_get_shell_sidebar (shell_view);
1384 				g_object_get (shell_sidebar, "folder-tree", &folder_tree, NULL);
1385 
1386 				if (folder_tree) {
1387 					gboolean selected;
1388 
1389 					if (move_forward)
1390 						selected = em_folder_tree_select_next_path (folder_tree, TRUE);
1391 					else
1392 						selected = em_folder_tree_select_prev_path (folder_tree, TRUE);
1393 
1394 					if (selected)
1395 						message_list_set_regen_selects_unread (MESSAGE_LIST (message_list), TRUE);
1396 				}
1397 
1398 				g_clear_object (&folder_tree);
1399 			}
1400 		}
1401 	}
1402 }
1403 
1404 static void
action_mail_next_unread_cb(GtkAction * action,EMailReader * reader)1405 action_mail_next_unread_cb (GtkAction *action,
1406                             EMailReader *reader)
1407 {
1408 	mail_reader_select_unread (reader, TRUE);
1409 }
1410 
1411 static void
action_mail_previous_cb(GtkAction * action,EMailReader * reader)1412 action_mail_previous_cb (GtkAction *action,
1413                          EMailReader *reader)
1414 {
1415 	GtkWidget *message_list;
1416 	MessageListSelectDirection direction;
1417 	guint32 flags, mask;
1418 
1419 	direction = MESSAGE_LIST_SELECT_PREVIOUS;
1420 	flags = 0;
1421 	mask = 0;
1422 
1423 	message_list = e_mail_reader_get_message_list (reader);
1424 
1425 	message_list_select (
1426 		MESSAGE_LIST (message_list), direction, flags, mask);
1427 }
1428 
1429 static void
action_mail_previous_important_cb(GtkAction * action,EMailReader * reader)1430 action_mail_previous_important_cb (GtkAction *action,
1431                                    EMailReader *reader)
1432 {
1433 	GtkWidget *message_list;
1434 	MessageListSelectDirection direction;
1435 	guint32 flags, mask;
1436 
1437 	direction = MESSAGE_LIST_SELECT_PREVIOUS | MESSAGE_LIST_SELECT_WRAP;
1438 	flags = CAMEL_MESSAGE_FLAGGED;
1439 	mask = CAMEL_MESSAGE_FLAGGED;
1440 
1441 	message_list = e_mail_reader_get_message_list (reader);
1442 
1443 	message_list_select (
1444 		MESSAGE_LIST (message_list), direction, flags, mask);
1445 }
1446 
1447 static void
action_mail_previous_thread_cb(GtkAction * action,EMailReader * reader)1448 action_mail_previous_thread_cb (GtkAction *action,
1449                                 EMailReader *reader)
1450 {
1451 	GtkWidget *message_list;
1452 
1453 	message_list = e_mail_reader_get_message_list (reader);
1454 
1455 	message_list_select_prev_thread (MESSAGE_LIST (message_list));
1456 }
1457 
1458 static void
action_mail_previous_unread_cb(GtkAction * action,EMailReader * reader)1459 action_mail_previous_unread_cb (GtkAction *action,
1460                                 EMailReader *reader)
1461 {
1462 	mail_reader_select_unread (reader, FALSE);
1463 }
1464 
1465 static void
action_mail_print_cb(GtkAction * action,EMailReader * reader)1466 action_mail_print_cb (GtkAction *action,
1467                       EMailReader *reader)
1468 {
1469 	GtkPrintOperationAction print_action;
1470 
1471 	print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG;
1472 	e_mail_reader_print (reader, print_action);
1473 }
1474 
1475 static void
action_mail_print_preview_cb(GtkAction * action,EMailReader * reader)1476 action_mail_print_preview_cb (GtkAction *action,
1477                               EMailReader *reader)
1478 {
1479 	GtkPrintOperationAction print_action;
1480 
1481 	print_action = GTK_PRINT_OPERATION_ACTION_PREVIEW;
1482 	e_mail_reader_print (reader, print_action);
1483 }
1484 
1485 static void
mail_reader_redirect_cb(CamelFolder * folder,GAsyncResult * result,EMailReaderClosure * closure)1486 mail_reader_redirect_cb (CamelFolder *folder,
1487                          GAsyncResult *result,
1488                          EMailReaderClosure *closure)
1489 {
1490 	EShell *shell;
1491 	EMailBackend *backend;
1492 	EAlertSink *alert_sink;
1493 	CamelMimeMessage *message;
1494 	CreateComposerData *ccd;
1495 	GError *error = NULL;
1496 
1497 	alert_sink = e_activity_get_alert_sink (closure->activity);
1498 
1499 	message = camel_folder_get_message_finish (folder, result, &error);
1500 
1501 	if (e_activity_handle_cancellation (closure->activity, error)) {
1502 		g_warn_if_fail (message == NULL);
1503 		mail_reader_closure_free (closure);
1504 		g_error_free (error);
1505 		return;
1506 
1507 	} else if (error != NULL) {
1508 		g_warn_if_fail (message == NULL);
1509 		e_alert_submit (
1510 			alert_sink, "mail:no-retrieve-message",
1511 			error->message, NULL);
1512 		mail_reader_closure_free (closure);
1513 		g_error_free (error);
1514 		return;
1515 	}
1516 
1517 	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
1518 
1519 	backend = e_mail_reader_get_backend (closure->reader);
1520 	shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
1521 
1522 	ccd = g_slice_new0 (CreateComposerData);
1523 	ccd->reader = g_object_ref (closure->reader);
1524 	ccd->message = message;
1525 	ccd->message_uid = camel_pstring_strdup (closure->message_uid);
1526 	ccd->is_redirect = TRUE;
1527 
1528 	e_msg_composer_new (shell, mail_reader_new_composer_created_cb, ccd);
1529 
1530 	mail_reader_closure_free (closure);
1531 }
1532 
1533 static void
action_mail_redirect_cb(GtkAction * action,EMailReader * reader)1534 action_mail_redirect_cb (GtkAction *action,
1535                          EMailReader *reader)
1536 {
1537 	EActivity *activity;
1538 	GCancellable *cancellable;
1539 	EMailReaderClosure *closure;
1540 	GtkWidget *message_list;
1541 	CamelFolder *folder;
1542 	const gchar *message_uid;
1543 
1544 	message_list = e_mail_reader_get_message_list (reader);
1545 	message_uid = MESSAGE_LIST (message_list)->cursor_uid;
1546 	g_return_if_fail (message_uid != NULL);
1547 
1548 	/* Open the message asynchronously. */
1549 
1550 	activity = e_mail_reader_new_activity (reader);
1551 	cancellable = e_activity_get_cancellable (activity);
1552 
1553 	closure = g_slice_new0 (EMailReaderClosure);
1554 	closure->activity = activity;
1555 	closure->reader = g_object_ref (reader);
1556 	closure->message_uid = g_strdup (message_uid);
1557 
1558 	folder = e_mail_reader_ref_folder (reader);
1559 
1560 	camel_folder_get_message (
1561 		folder, message_uid, G_PRIORITY_DEFAULT,
1562 		cancellable, (GAsyncReadyCallback)
1563 		mail_reader_redirect_cb, closure);
1564 
1565 	g_clear_object (&folder);
1566 }
1567 
1568 static void
action_mail_reply_all_check(CamelFolder * folder,GAsyncResult * result,EMailReaderClosure * closure)1569 action_mail_reply_all_check (CamelFolder *folder,
1570                              GAsyncResult *result,
1571                              EMailReaderClosure *closure)
1572 {
1573 	EAlertSink *alert_sink;
1574 	CamelMimeMessage *message;
1575 	CamelInternetAddress *to, *cc;
1576 	gint recip_count = 0;
1577 	EMailReplyType type = E_MAIL_REPLY_TO_ALL;
1578 	GError *error = NULL;
1579 
1580 	alert_sink = e_activity_get_alert_sink (closure->activity);
1581 
1582 	message = camel_folder_get_message_finish (folder, result, &error);
1583 
1584 	if (e_activity_handle_cancellation (closure->activity, error)) {
1585 		g_warn_if_fail (message == NULL);
1586 		mail_reader_closure_free (closure);
1587 		g_error_free (error);
1588 		return;
1589 
1590 	} else if (error != NULL) {
1591 		g_warn_if_fail (message == NULL);
1592 		e_alert_submit (
1593 			alert_sink, "mail:no-retrieve-message",
1594 			error->message, NULL);
1595 		mail_reader_closure_free (closure);
1596 		g_error_free (error);
1597 		return;
1598 	}
1599 
1600 	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
1601 
1602 	to = camel_mime_message_get_recipients (
1603 		message, CAMEL_RECIPIENT_TYPE_TO);
1604 	cc = camel_mime_message_get_recipients (
1605 		message, CAMEL_RECIPIENT_TYPE_CC);
1606 
1607 	recip_count = camel_address_length (CAMEL_ADDRESS (to));
1608 	recip_count += camel_address_length (CAMEL_ADDRESS (cc));
1609 
1610 	if (recip_count >= 15) {
1611 		GtkWidget *dialog;
1612 		GtkWidget *check;
1613 		GtkWidget *container;
1614 		gint response;
1615 
1616 		dialog = e_alert_dialog_new_for_args (
1617 			e_mail_reader_get_window (closure->reader),
1618 			"mail:ask-reply-many-recips", NULL);
1619 
1620 		container = e_alert_dialog_get_content_area (
1621 			E_ALERT_DIALOG (dialog));
1622 
1623 		/* Check buttons */
1624 		check = gtk_check_button_new_with_mnemonic (
1625 			_("_Do not ask me again."));
1626 		gtk_box_pack_start (
1627 			GTK_BOX (container), check, FALSE, FALSE, 0);
1628 		gtk_widget_show (check);
1629 
1630 		response = gtk_dialog_run (GTK_DIALOG (dialog));
1631 
1632 		if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (check))) {
1633 			GSettings *settings;
1634 			const gchar *key;
1635 
1636 			settings = e_util_ref_settings ("org.gnome.evolution.mail");
1637 
1638 			key = "prompt-on-reply-many-recips";
1639 			g_settings_set_boolean (settings, key, FALSE);
1640 
1641 			g_object_unref (settings);
1642 		}
1643 
1644 		gtk_widget_destroy (dialog);
1645 
1646 		switch (response) {
1647 			case GTK_RESPONSE_NO:
1648 				type = E_MAIL_REPLY_TO_SENDER;
1649 				break;
1650 			case GTK_RESPONSE_CANCEL:
1651 			case GTK_RESPONSE_DELETE_EVENT:
1652 				goto exit;
1653 			default:
1654 				break;
1655 		}
1656 	}
1657 
1658 	e_mail_reader_reply_to_message (closure->reader, message, type);
1659 
1660 exit:
1661 	g_object_unref (message);
1662 
1663 	mail_reader_closure_free (closure);
1664 }
1665 
1666 static void
action_mail_reply_all_cb(GtkAction * action,EMailReader * reader)1667 action_mail_reply_all_cb (GtkAction *action,
1668                           EMailReader *reader)
1669 {
1670 	GSettings *settings;
1671 	const gchar *key;
1672 	guint32 state;
1673 	gboolean ask;
1674 
1675 	state = e_mail_reader_check_state (reader);
1676 
1677 	settings = e_util_ref_settings ("org.gnome.evolution.mail");
1678 
1679 	key = "prompt-on-reply-many-recips";
1680 	ask = g_settings_get_boolean (settings, key);
1681 
1682 	g_object_unref (settings);
1683 
1684 	if (ask && !(state & E_MAIL_READER_SELECTION_IS_MAILING_LIST)) {
1685 		EActivity *activity;
1686 		GCancellable *cancellable;
1687 		EMailReaderClosure *closure;
1688 		CamelFolder *folder;
1689 		GtkWidget *message_list;
1690 		const gchar *message_uid;
1691 
1692 		message_list = e_mail_reader_get_message_list (reader);
1693 		message_uid = MESSAGE_LIST (message_list)->cursor_uid;
1694 		g_return_if_fail (message_uid != NULL);
1695 
1696 		activity = e_mail_reader_new_activity (reader);
1697 		cancellable = e_activity_get_cancellable (activity);
1698 
1699 		closure = g_slice_new0 (EMailReaderClosure);
1700 		closure->activity = activity;
1701 		closure->reader = g_object_ref (reader);
1702 
1703 		folder = e_mail_reader_ref_folder (reader);
1704 
1705 		camel_folder_get_message (
1706 			folder, message_uid, G_PRIORITY_DEFAULT,
1707 			cancellable, (GAsyncReadyCallback)
1708 			action_mail_reply_all_check, closure);
1709 
1710 		g_clear_object (&folder);
1711 
1712 		return;
1713 	}
1714 
1715 	e_mail_reader_reply_to_message (reader, NULL, E_MAIL_REPLY_TO_ALL);
1716 }
1717 
1718 static void
action_mail_reply_alternative_got_message(GObject * source_object,GAsyncResult * result,gpointer user_data)1719 action_mail_reply_alternative_got_message (GObject *source_object,
1720 					   GAsyncResult *result,
1721 					   gpointer user_data)
1722 {
1723 	EMailReaderClosure *closure = user_data;
1724 	EAlertSink *alert_sink;
1725 	CamelMimeMessage *message;
1726 	gboolean is_selection;
1727 	CamelFolder *folder = NULL;
1728 	const gchar *message_uid = NULL;
1729 	EMailPartList *part_list = NULL;
1730 	EMailPartValidityFlags validity_pgp_sum = 0;
1731 	EMailPartValidityFlags validity_smime_sum = 0;
1732 	GError *error = NULL;
1733 
1734 	alert_sink = e_activity_get_alert_sink (closure->activity);
1735 
1736 	message = e_mail_reader_utils_get_selection_or_message_finish (E_MAIL_READER (source_object), result,
1737 			&is_selection, &folder, &message_uid, &part_list, &validity_pgp_sum, &validity_smime_sum, &error);
1738 
1739 	if (e_activity_handle_cancellation (closure->activity, error)) {
1740 		g_warn_if_fail (message == NULL);
1741 		mail_reader_closure_free (closure);
1742 		g_error_free (error);
1743 		return;
1744 
1745 	} else if (error != NULL) {
1746 		g_warn_if_fail (message == NULL);
1747 		e_alert_submit (
1748 			alert_sink, "mail:no-retrieve-message",
1749 			error->message, NULL);
1750 		mail_reader_closure_free (closure);
1751 		g_error_free (error);
1752 		return;
1753 	}
1754 
1755 	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
1756 
1757 	g_clear_object (&closure->activity);
1758 
1759 	em_utils_reply_alternative (e_mail_reader_get_window (closure->reader),
1760 		e_shell_backend_get_shell (E_SHELL_BACKEND (e_mail_reader_get_backend (closure->reader))),
1761 		alert_sink, message, folder, message_uid,
1762 		e_mail_reader_get_reply_style (closure->reader),
1763 		is_selection ? NULL : part_list, validity_pgp_sum, validity_smime_sum);
1764 
1765 	mail_reader_closure_free (closure);
1766 	camel_pstring_free (message_uid);
1767 	g_clear_object (&message);
1768 	g_clear_object (&folder);
1769 	g_clear_object (&part_list);
1770 	g_clear_error (&error);
1771 }
1772 
1773 static void
action_mail_reply_alternative_cb(GtkAction * action,EMailReader * reader)1774 action_mail_reply_alternative_cb (GtkAction *action,
1775 				  EMailReader *reader)
1776 {
1777 	EActivity *activity;
1778 	GCancellable *cancellable;
1779 	EMailReaderClosure *closure;
1780 	GtkWidget *message_list;
1781 	const gchar *message_uid;
1782 
1783 	message_list = e_mail_reader_get_message_list (reader);
1784 	message_uid = MESSAGE_LIST (message_list)->cursor_uid;
1785 	g_return_if_fail (message_uid != NULL);
1786 
1787 	activity = e_mail_reader_new_activity (reader);
1788 	cancellable = e_activity_get_cancellable (activity);
1789 
1790 	closure = g_slice_new0 (EMailReaderClosure);
1791 	closure->activity = activity;
1792 	closure->reader = g_object_ref (reader);
1793 
1794 	e_mail_reader_utils_get_selection_or_message (reader, NULL, cancellable,
1795 		action_mail_reply_alternative_got_message, closure);
1796 }
1797 
1798 static void
action_mail_reply_group_cb(GtkAction * action,EMailReader * reader)1799 action_mail_reply_group_cb (GtkAction *action,
1800                             EMailReader *reader)
1801 {
1802 	GSettings *settings;
1803 	gboolean reply_list;
1804 	guint32 state;
1805 	const gchar *key;
1806 
1807 	state = e_mail_reader_check_state (reader);
1808 
1809 	settings = e_util_ref_settings ("org.gnome.evolution.mail");
1810 
1811 	key = "composer-group-reply-to-list";
1812 	reply_list = g_settings_get_boolean (settings, key);
1813 
1814 	g_object_unref (settings);
1815 
1816 	if (reply_list && (state & E_MAIL_READER_SELECTION_IS_MAILING_LIST)) {
1817 		e_mail_reader_reply_to_message (
1818 			reader, NULL, E_MAIL_REPLY_TO_LIST);
1819 	} else
1820 		action_mail_reply_all_cb (action, reader);
1821 }
1822 
1823 static void
action_mail_reply_list_cb(GtkAction * action,EMailReader * reader)1824 action_mail_reply_list_cb (GtkAction *action,
1825                            EMailReader *reader)
1826 {
1827 	e_mail_reader_reply_to_message (reader, NULL, E_MAIL_REPLY_TO_LIST);
1828 }
1829 
1830 static gboolean
message_is_list_administrative(CamelMimeMessage * message)1831 message_is_list_administrative (CamelMimeMessage *message)
1832 {
1833 	const gchar *header;
1834 
1835 	header = camel_medium_get_header (
1836 		CAMEL_MEDIUM (message), "X-List-Administrivia");
1837 	if (header == NULL)
1838 		return FALSE;
1839 
1840 	while (*header == ' ' || *header == '\t')
1841 		header++;
1842 
1843 	return g_ascii_strncasecmp (header, "yes", 3) == 0;
1844 }
1845 
1846 static void
action_mail_reply_sender_check(CamelFolder * folder,GAsyncResult * result,EMailReaderClosure * closure)1847 action_mail_reply_sender_check (CamelFolder *folder,
1848                                 GAsyncResult *result,
1849                                 EMailReaderClosure *closure)
1850 {
1851 	EAlertSink *alert_sink;
1852 	CamelMimeMessage *message;
1853 	EMailReplyType type = E_MAIL_REPLY_TO_SENDER;
1854 	GSettings *settings;
1855 	gboolean ask_ignore_list_reply_to;
1856 	gboolean ask_list_reply_to;
1857 	gboolean munged_list_message;
1858 	gboolean active;
1859 	const gchar *key;
1860 	GError *local_error = NULL;
1861 
1862 	alert_sink = e_activity_get_alert_sink (closure->activity);
1863 
1864 	message = camel_folder_get_message_finish (
1865 		folder, result, &local_error);
1866 
1867 	/* Sanity check. */
1868 	g_return_if_fail (
1869 		((message != NULL) && (local_error == NULL)) ||
1870 		((message == NULL) && (local_error != NULL)));
1871 
1872 	if (e_activity_handle_cancellation (closure->activity, local_error)) {
1873 		mail_reader_closure_free (closure);
1874 		g_error_free (local_error);
1875 		return;
1876 
1877 	} else if (local_error != NULL) {
1878 		e_alert_submit (
1879 			alert_sink, "mail:no-retrieve-message",
1880 			local_error->message, NULL);
1881 		mail_reader_closure_free (closure);
1882 		g_error_free (local_error);
1883 		return;
1884 	}
1885 
1886 	settings = e_util_ref_settings ("org.gnome.evolution.mail");
1887 
1888 	key = "composer-ignore-list-reply-to";
1889 	ask_ignore_list_reply_to = g_settings_get_boolean (settings, key);
1890 
1891 	key = "prompt-on-list-reply-to";
1892 	ask_list_reply_to = g_settings_get_boolean (settings, key);
1893 
1894 	munged_list_message = em_utils_is_munged_list_message (message);
1895 
1896 	if (message_is_list_administrative (message)) {
1897 		/* Do not ask for messages which are list administrative,
1898 		 * like list confirmation messages. */
1899 	} else if (ask_ignore_list_reply_to || !munged_list_message) {
1900 		/* Don't do the "Are you sure you want to reply in private?"
1901 		 * pop-up if it's a Reply-To: munged list message... unless
1902 		 * we're ignoring munging. */
1903 		GtkWidget *dialog;
1904 		GtkWidget *check;
1905 		GtkWidget *container;
1906 		gint response;
1907 
1908 		dialog = e_alert_dialog_new_for_args (
1909 			e_mail_reader_get_window (closure->reader),
1910 			"mail:ask-list-private-reply", NULL);
1911 
1912 		container = e_alert_dialog_get_content_area (
1913 			E_ALERT_DIALOG (dialog));
1914 
1915 		/* Check buttons */
1916 		check = gtk_check_button_new_with_mnemonic (
1917 			_("_Do not ask me again."));
1918 		gtk_box_pack_start (
1919 			GTK_BOX (container), check, FALSE, FALSE, 0);
1920 		gtk_widget_show (check);
1921 
1922 		response = gtk_dialog_run (GTK_DIALOG (dialog));
1923 
1924 		active = gtk_toggle_button_get_active (
1925 			GTK_TOGGLE_BUTTON (check));
1926 		if (active) {
1927 			key = "prompt-on-private-list-reply";
1928 			g_settings_set_boolean (settings, key, FALSE);
1929 		}
1930 
1931 		gtk_widget_destroy (dialog);
1932 
1933 		if (response == GTK_RESPONSE_YES)
1934 			type = E_MAIL_REPLY_TO_ALL;
1935 		else if (response == GTK_RESPONSE_OK)
1936 			type = E_MAIL_REPLY_TO_LIST;
1937 		else if (response == GTK_RESPONSE_CANCEL ||
1938 			response == GTK_RESPONSE_DELETE_EVENT) {
1939 			goto exit;
1940 		}
1941 
1942 	} else if (ask_list_reply_to) {
1943 		GtkWidget *dialog;
1944 		GtkWidget *container;
1945 		GtkWidget *check_again;
1946 		GtkWidget *check_always_ignore;
1947 		gint response;
1948 
1949 		dialog = e_alert_dialog_new_for_args (
1950 			e_mail_reader_get_window (closure->reader),
1951 			"mail:ask-list-honour-reply-to", NULL);
1952 
1953 		container = e_alert_dialog_get_content_area (
1954 			E_ALERT_DIALOG (dialog));
1955 
1956 		check_again = gtk_check_button_new_with_mnemonic (
1957 			_("_Do not ask me again."));
1958 		gtk_box_pack_start (
1959 			GTK_BOX (container), check_again, FALSE, FALSE, 0);
1960 		gtk_widget_show (check_again);
1961 
1962 		check_always_ignore = gtk_check_button_new_with_mnemonic (
1963 			_("_Always ignore Reply-To: for mailing lists."));
1964 		gtk_box_pack_start (
1965 			GTK_BOX (container), check_always_ignore,
1966 			FALSE, FALSE, 0);
1967 		gtk_widget_show (check_always_ignore);
1968 
1969 		response = gtk_dialog_run (GTK_DIALOG (dialog));
1970 
1971 		active = gtk_toggle_button_get_active (
1972 			GTK_TOGGLE_BUTTON (check_again));
1973 		if (active) {
1974 			key = "prompt-on-list-reply-to";
1975 			g_settings_set_boolean (settings, key, FALSE);
1976 		}
1977 
1978 		key = "composer-ignore-list-reply-to";
1979 		active = gtk_toggle_button_get_active (
1980 			GTK_TOGGLE_BUTTON (check_always_ignore));
1981 		g_settings_set_boolean (settings, key, active);
1982 
1983 		gtk_widget_destroy (dialog);
1984 
1985 		switch (response) {
1986 			case GTK_RESPONSE_NO:
1987 				type = E_MAIL_REPLY_TO_FROM;
1988 				break;
1989 			case GTK_RESPONSE_OK:
1990 				type = E_MAIL_REPLY_TO_LIST;
1991 				break;
1992 			case GTK_RESPONSE_CANCEL:
1993 			case GTK_RESPONSE_DELETE_EVENT:
1994 				goto exit;
1995 			default:
1996 				break;
1997 		}
1998 	}
1999 
2000 	e_mail_reader_reply_to_message (closure->reader, message, type);
2001 
2002 exit:
2003 	g_object_unref (settings);
2004 	g_object_unref (message);
2005 
2006 	mail_reader_closure_free (closure);
2007 }
2008 
2009 static void
action_mail_reply_sender_cb(GtkAction * action,EMailReader * reader)2010 action_mail_reply_sender_cb (GtkAction *action,
2011                              EMailReader *reader)
2012 {
2013 	GSettings *settings;
2014 	gboolean ask_list_reply_to;
2015 	gboolean ask_private_list_reply;
2016 	gboolean ask;
2017 	guint32 state;
2018 	const gchar *key;
2019 
2020 	state = e_mail_reader_check_state (reader);
2021 
2022 	settings = e_util_ref_settings ("org.gnome.evolution.mail");
2023 
2024 	key = "prompt-on-list-reply-to";
2025 	ask_list_reply_to = g_settings_get_boolean (settings, key);
2026 
2027 	key = "prompt-on-private-list-reply";
2028 	ask_private_list_reply = g_settings_get_boolean (settings, key);
2029 
2030 	g_object_unref (settings);
2031 
2032 	ask = (ask_private_list_reply || ask_list_reply_to);
2033 
2034 	if (ask && (state & E_MAIL_READER_SELECTION_IS_MAILING_LIST)) {
2035 		EActivity *activity;
2036 		GCancellable *cancellable;
2037 		EMailReaderClosure *closure;
2038 		CamelFolder *folder;
2039 		GtkWidget *message_list;
2040 		const gchar *message_uid;
2041 
2042 		message_list = e_mail_reader_get_message_list (reader);
2043 		message_uid = MESSAGE_LIST (message_list)->cursor_uid;
2044 		g_return_if_fail (message_uid != NULL);
2045 
2046 		activity = e_mail_reader_new_activity (reader);
2047 		cancellable = e_activity_get_cancellable (activity);
2048 
2049 		closure = g_slice_new0 (EMailReaderClosure);
2050 		closure->activity = activity;
2051 		closure->reader = g_object_ref (reader);
2052 
2053 		folder = e_mail_reader_ref_folder (reader);
2054 
2055 		camel_folder_get_message (
2056 			folder, message_uid, G_PRIORITY_DEFAULT,
2057 			cancellable, (GAsyncReadyCallback)
2058 			action_mail_reply_sender_check, closure);
2059 
2060 		g_clear_object (&folder);
2061 
2062 		return;
2063 	}
2064 
2065 	e_mail_reader_reply_to_message (reader, NULL, E_MAIL_REPLY_TO_SENDER);
2066 }
2067 
2068 static void
action_mail_reply_recipient_cb(GtkAction * action,EMailReader * reader)2069 action_mail_reply_recipient_cb (GtkAction *action,
2070                                 EMailReader *reader)
2071 {
2072 	e_mail_reader_reply_to_message (reader, NULL, E_MAIL_REPLY_TO_RECIPIENT);
2073 }
2074 
2075 static void
action_mail_save_as_cb(GtkAction * action,EMailReader * reader)2076 action_mail_save_as_cb (GtkAction *action,
2077                         EMailReader *reader)
2078 {
2079 	e_mail_reader_save_messages (reader);
2080 }
2081 
2082 static void
action_mail_search_folder_from_mailing_list_cb(GtkAction * action,EMailReader * reader)2083 action_mail_search_folder_from_mailing_list_cb (GtkAction *action,
2084                                                 EMailReader *reader)
2085 {
2086 	e_mail_reader_create_vfolder_from_selected (reader, AUTO_MLIST);
2087 }
2088 
2089 static void
action_mail_search_folder_from_recipients_cb(GtkAction * action,EMailReader * reader)2090 action_mail_search_folder_from_recipients_cb (GtkAction *action,
2091                                               EMailReader *reader)
2092 {
2093 	e_mail_reader_create_vfolder_from_selected (reader, AUTO_TO);
2094 }
2095 
2096 static void
action_mail_search_folder_from_sender_cb(GtkAction * action,EMailReader * reader)2097 action_mail_search_folder_from_sender_cb (GtkAction *action,
2098                                           EMailReader *reader)
2099 {
2100 	e_mail_reader_create_vfolder_from_selected (reader, AUTO_FROM);
2101 }
2102 
2103 static void
action_mail_search_folder_from_subject_cb(GtkAction * action,EMailReader * reader)2104 action_mail_search_folder_from_subject_cb (GtkAction *action,
2105                                            EMailReader *reader)
2106 {
2107 	e_mail_reader_create_vfolder_from_selected (reader, AUTO_SUBJECT);
2108 }
2109 
2110 static void
action_mail_show_all_headers_cb(GtkToggleAction * action,EMailReader * reader)2111 action_mail_show_all_headers_cb (GtkToggleAction *action,
2112                                  EMailReader *reader)
2113 {
2114 	EMailDisplay *display;
2115 	EMailFormatterMode mode;
2116 
2117 	display = e_mail_reader_get_mail_display (reader);
2118 
2119 	/* Ignore action when viewing message source. */
2120 	mode = e_mail_display_get_mode (display);
2121 	if (mode == E_MAIL_FORMATTER_MODE_SOURCE)
2122 		return;
2123 	if (mode == E_MAIL_FORMATTER_MODE_RAW)
2124 		return;
2125 
2126 	if (gtk_toggle_action_get_active (action))
2127 		mode = E_MAIL_FORMATTER_MODE_ALL_HEADERS;
2128 	else
2129 		mode = E_MAIL_FORMATTER_MODE_NORMAL;
2130 
2131 	e_mail_display_set_mode (display, mode);
2132 }
2133 
2134 static void
mail_source_retrieved(GObject * source_object,GAsyncResult * result,gpointer user_data)2135 mail_source_retrieved (GObject *source_object,
2136                        GAsyncResult *result,
2137                        gpointer user_data)
2138 {
2139 	EMailReaderClosure *closure;
2140 	CamelMimeMessage *message;
2141 	EMailDisplay *display;
2142 	GError *error = NULL;
2143 
2144 	closure = (EMailReaderClosure *) user_data;
2145 	display = e_mail_reader_get_mail_display (closure->reader);
2146 
2147 	message = camel_folder_get_message_finish (
2148 		CAMEL_FOLDER (source_object), result, &error);
2149 
2150 	/* Sanity check. */
2151 	g_return_if_fail (
2152 		((message != NULL) && (error == NULL)) ||
2153 		((message == NULL) && (error != NULL)));
2154 
2155 	if (message != NULL) {
2156 		mail_reader_set_display_formatter_for_message (
2157 			closure->reader, display,
2158 			closure->message_uid, message,
2159 			CAMEL_FOLDER (source_object));
2160 		g_object_unref (message);
2161 	} else if (error) {
2162 		if (display) {
2163 			gchar *status;
2164 
2165 			status = g_strdup_printf (
2166 				"%s<br>%s",
2167 				_("Failed to retrieve message:"),
2168 				error->message);
2169 			e_mail_display_set_status (display, status);
2170 			g_free (status);
2171 		}
2172 
2173 		g_error_free (error);
2174 	}
2175 
2176 	e_activity_set_state (closure->activity, E_ACTIVITY_COMPLETED);
2177 
2178 	mail_reader_closure_free (closure);
2179 }
2180 
2181 static void
action_mail_show_source_cb(GtkAction * action,EMailReader * reader)2182 action_mail_show_source_cb (GtkAction *action,
2183                             EMailReader *reader)
2184 {
2185 	EMailDisplay *display;
2186 	EMailBackend *backend;
2187 	GtkWidget *browser;
2188 	CamelFolder *folder;
2189 	GPtrArray *uids;
2190 	const gchar *message_uid;
2191 	gchar *string;
2192 	EActivity *activity;
2193 	GCancellable *cancellable;
2194 	EMailReaderClosure *closure;
2195 	MessageList *ml;
2196 
2197 	backend = e_mail_reader_get_backend (reader);
2198 	folder = e_mail_reader_ref_folder (reader);
2199 	uids = e_mail_reader_get_selected_uids (reader);
2200 	g_return_if_fail (uids != NULL && uids->len == 1);
2201 	message_uid = g_ptr_array_index (uids, 0);
2202 
2203 	if (!E_IS_MAIL_BROWSER (e_mail_reader_get_window (reader))) {
2204 		EMailBrowser *mail_browser;
2205 
2206 		mail_browser = em_utils_find_message_window (E_MAIL_FORMATTER_MODE_SOURCE, folder, message_uid);
2207 
2208 		if (mail_browser) {
2209 			gtk_window_present (GTK_WINDOW (mail_browser));
2210 			g_ptr_array_unref (uids);
2211 			g_clear_object (&folder);
2212 			return;
2213 		}
2214 	}
2215 
2216 	browser = e_mail_browser_new (backend, E_MAIL_FORMATTER_MODE_SOURCE);
2217 	ml = MESSAGE_LIST (e_mail_reader_get_message_list (E_MAIL_READER (browser)));
2218 
2219 	message_list_freeze (ml);
2220 	e_mail_reader_set_folder (E_MAIL_READER (browser), folder);
2221 	e_mail_reader_set_message (E_MAIL_READER (browser), message_uid);
2222 	message_list_thaw (ml);
2223 
2224 	display = e_mail_reader_get_mail_display (E_MAIL_READER (browser));
2225 
2226 	string = g_strdup_printf (_("Retrieving message “%s”"), message_uid);
2227 	e_mail_display_set_part_list (display, NULL);
2228 	e_mail_display_set_status (display, string);
2229 	gtk_widget_show (browser);
2230 
2231 	activity = e_mail_reader_new_activity (E_MAIL_READER (browser));
2232 	e_activity_set_text (activity, string);
2233 	cancellable = e_activity_get_cancellable (activity);
2234 	g_free (string);
2235 
2236 	closure = g_slice_new0 (EMailReaderClosure);
2237 	closure->reader = E_MAIL_READER (g_object_ref (browser));
2238 	closure->activity = g_object_ref (activity);
2239 	closure->message_uid = g_strdup (message_uid);
2240 
2241 	camel_folder_get_message (
2242 		folder, message_uid, G_PRIORITY_DEFAULT,
2243 		cancellable, mail_source_retrieved, closure);
2244 
2245 	g_object_unref (activity);
2246 
2247 	g_ptr_array_unref (uids);
2248 
2249 	g_clear_object (&folder);
2250 }
2251 
2252 static void
action_mail_toggle_important_cb(GtkAction * action,EMailReader * reader)2253 action_mail_toggle_important_cb (GtkAction *action,
2254                                  EMailReader *reader)
2255 {
2256 	CamelFolder *folder;
2257 	GPtrArray *uids;
2258 	guint ii;
2259 
2260 	uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
2261 	if (!uids)
2262 		return;
2263 
2264 	folder = e_mail_reader_ref_folder (reader);
2265 
2266 	camel_folder_freeze (folder);
2267 
2268 	for (ii = 0; ii < uids->len; ii++) {
2269 		guint32 flags;
2270 
2271 		flags = camel_folder_get_message_flags (
2272 			folder, uids->pdata[ii]);
2273 		flags ^= CAMEL_MESSAGE_FLAGGED;
2274 		if (flags & CAMEL_MESSAGE_FLAGGED)
2275 			flags &= ~CAMEL_MESSAGE_DELETED;
2276 
2277 		camel_folder_set_message_flags (
2278 			folder, uids->pdata[ii], CAMEL_MESSAGE_FLAGGED |
2279 			CAMEL_MESSAGE_DELETED, flags);
2280 	}
2281 
2282 	camel_folder_thaw (folder);
2283 
2284 	g_clear_object (&folder);
2285 	g_ptr_array_unref (uids);
2286 }
2287 
2288 static void
action_mail_undelete_cb(GtkAction * action,EMailReader * reader)2289 action_mail_undelete_cb (GtkAction *action,
2290                          EMailReader *reader)
2291 {
2292 	guint32 mask = CAMEL_MESSAGE_DELETED;
2293 	guint32 set = 0;
2294 
2295 	e_mail_reader_mark_selected (reader, mask, set);
2296 }
2297 
2298 static void
action_mail_zoom_100_cb(GtkAction * action,EMailReader * reader)2299 action_mail_zoom_100_cb (GtkAction *action,
2300                          EMailReader *reader)
2301 {
2302 	EMailDisplay *display;
2303 
2304 	display = e_mail_reader_get_mail_display (reader);
2305 
2306 	e_web_view_zoom_100 (E_WEB_VIEW (display));
2307 }
2308 
2309 static void
action_mail_zoom_in_cb(GtkAction * action,EMailReader * reader)2310 action_mail_zoom_in_cb (GtkAction *action,
2311                         EMailReader *reader)
2312 {
2313 	EMailDisplay *display;
2314 
2315 	display = e_mail_reader_get_mail_display (reader);
2316 
2317 	e_web_view_zoom_in (E_WEB_VIEW (display));
2318 }
2319 
2320 static void
action_mail_zoom_out_cb(GtkAction * action,EMailReader * reader)2321 action_mail_zoom_out_cb (GtkAction *action,
2322                          EMailReader *reader)
2323 {
2324 	EMailDisplay *display;
2325 
2326 	display = e_mail_reader_get_mail_display (reader);
2327 
2328 	e_web_view_zoom_out (E_WEB_VIEW (display));
2329 }
2330 
2331 static void
action_mail_search_web_cb(GtkAction * action,EMailReader * reader)2332 action_mail_search_web_cb (GtkAction *action,
2333 			   EMailReader *reader)
2334 {
2335 	EMailDisplay *display;
2336 	GtkAction *wv_action;
2337 
2338 	display = e_mail_reader_get_mail_display (reader);
2339 	wv_action = e_web_view_get_action (E_WEB_VIEW (display), "search-web");
2340 
2341 	gtk_action_activate (wv_action);
2342 }
2343 
2344 static void
action_search_folder_recipient_cb(GtkAction * action,EMailReader * reader)2345 action_search_folder_recipient_cb (GtkAction *action,
2346                                    EMailReader *reader)
2347 {
2348 	EMailBackend *backend;
2349 	EMailSession *session;
2350 	EWebView *web_view;
2351 	CamelURL *curl;
2352 	const gchar *uri;
2353 
2354 	/* This action is defined in EMailDisplay. */
2355 
2356 	web_view = E_WEB_VIEW (e_mail_reader_get_mail_display (reader));
2357 
2358 	uri = e_web_view_get_selected_uri (web_view);
2359 	g_return_if_fail (uri != NULL);
2360 
2361 	curl = camel_url_new (uri, NULL);
2362 	g_return_if_fail (curl != NULL);
2363 
2364 	backend = e_mail_reader_get_backend (reader);
2365 	session = e_mail_backend_get_session (backend);
2366 
2367 	if (curl->path != NULL && *curl->path != '\0') {
2368 		CamelFolder *folder;
2369 		CamelInternetAddress *inet_addr;
2370 
2371 		folder = e_mail_reader_ref_folder (reader);
2372 
2373 		inet_addr = camel_internet_address_new ();
2374 		camel_address_decode (CAMEL_ADDRESS (inet_addr), curl->path);
2375 		vfolder_gui_add_from_address (
2376 			session, inet_addr, AUTO_TO, folder);
2377 		g_object_unref (inet_addr);
2378 
2379 		g_clear_object (&folder);
2380 	}
2381 
2382 	camel_url_free (curl);
2383 }
2384 
2385 static void
action_search_folder_sender_cb(GtkAction * action,EMailReader * reader)2386 action_search_folder_sender_cb (GtkAction *action,
2387                                 EMailReader *reader)
2388 {
2389 	EMailBackend *backend;
2390 	EMailSession *session;
2391 	EWebView *web_view;
2392 	CamelURL *curl;
2393 	const gchar *uri;
2394 
2395 	/* This action is defined in EMailDisplay. */
2396 
2397 	web_view = E_WEB_VIEW (e_mail_reader_get_mail_display (reader));
2398 
2399 	uri = e_web_view_get_selected_uri (web_view);
2400 	g_return_if_fail (uri != NULL);
2401 
2402 	curl = camel_url_new (uri, NULL);
2403 	g_return_if_fail (curl != NULL);
2404 
2405 	backend = e_mail_reader_get_backend (reader);
2406 	session = e_mail_backend_get_session (backend);
2407 
2408 	if (curl->path != NULL && *curl->path != '\0') {
2409 		CamelFolder *folder;
2410 		CamelInternetAddress *inet_addr;
2411 
2412 		folder = e_mail_reader_ref_folder (reader);
2413 
2414 		inet_addr = camel_internet_address_new ();
2415 		camel_address_decode (CAMEL_ADDRESS (inet_addr), curl->path);
2416 		vfolder_gui_add_from_address (
2417 			session, inet_addr, AUTO_FROM, folder);
2418 		g_object_unref (inet_addr);
2419 
2420 		g_clear_object (&folder);
2421 	}
2422 
2423 	camel_url_free (curl);
2424 }
2425 
2426 static GtkActionEntry mail_reader_entries[] = {
2427 
2428 	{ "mail-add-sender",
2429 	  NULL,
2430 	  N_("A_dd Sender to Address Book"),
2431 	  NULL,
2432 	  N_("Add sender to address book"),
2433 	  G_CALLBACK (action_mail_add_sender_cb) },
2434 
2435 	{ "mail-archive",
2436 	  "mail-archive",
2437 	  N_("_Archive…"),
2438 	  "<Alt><Control>a",
2439 	  N_("Move selected messages to the Archive folder for the account"),
2440 	  G_CALLBACK (action_mail_archive_cb) },
2441 
2442 	{ "mail-check-for-junk",
2443 	  "mail-mark-junk",
2444 	  N_("Check for _Junk"),
2445 	  "<Control><Alt>j",
2446 	  N_("Filter the selected messages for junk status"),
2447 	  G_CALLBACK (action_mail_check_for_junk_cb) },
2448 
2449 	{ "mail-color-assign",
2450 	  NULL,
2451 	  N_("Assign C_olor…"),
2452 	  NULL,
2453 	  N_("Assign color for the selected messages"),
2454 	  G_CALLBACK (action_mail_color_assign_cb) },
2455 
2456 	{ "mail-color-unset",
2457 	  NULL,
2458 	  N_("Unse_t Color"),
2459 	  NULL,
2460 	  N_("Unset color for the selected messages"),
2461 	  G_CALLBACK (action_mail_color_unset_cb) },
2462 
2463 	{ "mail-copy",
2464 	  "mail-copy",
2465 	  N_("_Copy to Folder…"),
2466 	  "<Shift><Control>y",
2467 	  N_("Copy selected messages to another folder"),
2468 	  G_CALLBACK (action_mail_copy_cb) },
2469 
2470 	{ "mail-delete",
2471 	  "user-trash",
2472 	  N_("_Delete Message"),
2473 	  "<Control>d",
2474 	  N_("Mark the selected messages for deletion"),
2475 	  G_CALLBACK (action_mail_delete_cb) },
2476 
2477 	{ "mail-add-note",
2478 	  "evolution-memos",
2479 	  N_("_Add note…"),
2480 	  NULL,
2481 	  N_("Add a note for the selected message"),
2482 	  G_CALLBACK (action_mail_edit_note_cb) },
2483 
2484 	{ "mail-delete-note",
2485 	  NULL,
2486 	  N_("Delete no_te"),
2487 	  NULL,
2488 	  N_("Delete the note for the selected message"),
2489 	  G_CALLBACK (action_mail_delete_note_cb) },
2490 
2491 	{ "mail-edit-note",
2492 	  "evolution-memos",
2493 	  N_("_Edit note…"),
2494 	  NULL,
2495 	  N_("Edit a note for the selected message"),
2496 	  G_CALLBACK (action_mail_edit_note_cb) },
2497 
2498 	{ "mail-filter-rule-for-mailing-list",
2499 	  NULL,
2500 	  N_("Create a Filter Rule for Mailing _List…"),
2501 	  NULL,
2502 	  N_("Create a rule to filter messages to this mailing list"),
2503 	  G_CALLBACK (action_mail_filter_on_mailing_list_cb) },
2504 
2505 	{ "mail-filter-rule-for-recipients",
2506 	  NULL,
2507 	  N_("Create a Filter Rule for _Recipients…"),
2508 	  NULL,
2509 	  N_("Create a rule to filter messages to these recipients"),
2510 	  G_CALLBACK (action_mail_filter_on_recipients_cb) },
2511 
2512 	{ "mail-filter-rule-for-sender",
2513 	  NULL,
2514 	  N_("Create a Filter Rule for Se_nder…"),
2515 	  NULL,
2516 	  N_("Create a rule to filter messages from this sender"),
2517 	  G_CALLBACK (action_mail_filter_on_sender_cb) },
2518 
2519 	{ "mail-filter-rule-for-subject",
2520 	  NULL,
2521 	  N_("Create a Filter Rule for _Subject…"),
2522 	  NULL,
2523 	  N_("Create a rule to filter messages with this subject"),
2524 	  G_CALLBACK (action_mail_filter_on_subject_cb) },
2525 
2526 	{ "mail-filters-apply",
2527 	  "stock_mail-filters-apply",
2528 	  N_("A_pply Filters"),
2529 	  "<Control>y",
2530 	  N_("Apply filter rules to the selected messages"),
2531 	  G_CALLBACK (action_mail_filters_apply_cb) },
2532 
2533 	{ "mail-find",
2534 	  "edit-find",
2535 	  N_("_Find in Message…"),
2536 	  "<Shift><Control>f",
2537 	  N_("Search for text in the body of the displayed message"),
2538 	  G_CALLBACK (action_mail_find_cb) },
2539 
2540 	{ "mail-flag-clear",
2541 	  NULL,
2542 	  N_("_Clear Flag"),
2543 	  NULL,
2544 	  N_("Remove the follow-up flag from the selected messages"),
2545 	  G_CALLBACK (action_mail_flag_clear_cb) },
2546 
2547 	{ "mail-flag-completed",
2548 	  NULL,
2549 	  N_("_Flag Completed"),
2550 	  NULL,
2551 	  N_("Set the follow-up flag to completed on the selected messages"),
2552 	  G_CALLBACK (action_mail_flag_completed_cb) },
2553 
2554 	{ "mail-flag-for-followup",
2555 	  "stock_mail-flag-for-followup",
2556 	  N_("Follow _Up…"),
2557 	  "<Shift><Control>g",
2558 	  N_("Flag the selected messages for follow-up"),
2559 	  G_CALLBACK (action_mail_flag_for_followup_cb) },
2560 
2561 	{ "mail-forward-attached",
2562 	  NULL,
2563 	  N_("_Attached"),
2564 	  NULL,
2565 	  N_("Forward the selected message to someone as an attachment"),
2566 	  G_CALLBACK (action_mail_forward_attached_cb) },
2567 
2568 	{ "mail-forward-attached-full",
2569 	  NULL,
2570 	  N_("Forward As _Attached"),
2571 	  NULL,
2572 	  N_("Forward the selected message to someone as an attachment"),
2573 	  G_CALLBACK (action_mail_forward_attached_cb) },
2574 
2575 	{ "mail-forward-inline",
2576 	  NULL,
2577 	  N_("_Inline"),
2578 	  NULL,
2579 	  N_("Forward the selected message in the body of a new message"),
2580 	  G_CALLBACK (action_mail_forward_inline_cb) },
2581 
2582 	{ "mail-forward-inline-full",
2583 	  NULL,
2584 	  N_("Forward As _Inline"),
2585 	  NULL,
2586 	  N_("Forward the selected message in the body of a new message"),
2587 	  G_CALLBACK (action_mail_forward_inline_cb) },
2588 
2589 	{ "mail-forward-quoted",
2590 	  NULL,
2591 	  N_("_Quoted"),
2592 	  NULL,
2593 	  N_("Forward the selected message quoted like a reply"),
2594 	  G_CALLBACK (action_mail_forward_quoted_cb) },
2595 
2596 	{ "mail-forward-quoted-full",
2597 	  NULL,
2598 	  N_("Forward As _Quoted"),
2599 	  NULL,
2600 	  N_("Forward the selected message quoted like a reply"),
2601 	  G_CALLBACK (action_mail_forward_quoted_cb) },
2602 
2603 	{ "mail-label-new",
2604 	  NULL,
2605 	  N_("_New Label"),
2606 	  NULL,
2607 	  NULL,  /* XXX Add a tooltip! */
2608 	  G_CALLBACK (action_mail_label_new_cb) },
2609 
2610 	{ "mail-label-none",
2611 	  NULL,
2612 	  /* Translators: "None" is used in the message label context menu.
2613 	   *              It removes all labels from the selected messages. */
2614 	  N_("N_one"),
2615 	  "0",
2616 	  NULL,  /* XXX Add a tooltip! */
2617 	  G_CALLBACK (action_mail_label_none_cb) },
2618 
2619 	{ "mail-load-images",
2620 	  "image-x-generic",
2621 	  N_("_Load Images"),
2622 	  "<Control>i",
2623 	  N_("Force images in HTML mail to be loaded"),
2624 	  G_CALLBACK (action_mail_load_images_cb) },
2625 
2626 	{ "mail-mark-ignore-thread-sub",
2627 	  NULL,
2628 	  N_("_Ignore Subthread"),
2629 	  NULL,
2630 	  N_("Mark new mails in a subthread as read automatically"),
2631 	  G_CALLBACK (action_mail_mark_ignore_thread_sub_cb) },
2632 
2633 	{ "mail-mark-ignore-thread-whole",
2634 	  NULL,
2635 	  N_("_Ignore Thread"),
2636 	  NULL,
2637 	  N_("Mark new mails in this thread as read automatically"),
2638 	  G_CALLBACK (action_mail_mark_ignore_thread_whole_cb) },
2639 
2640 	{ "mail-mark-important",
2641 	  "mail-mark-important",
2642 	  N_("_Important"),
2643 	  NULL,
2644 	  N_("Mark the selected messages as important"),
2645 	  G_CALLBACK (action_mail_mark_important_cb) },
2646 
2647 	{ "mail-mark-junk",
2648 	  "mail-mark-junk",
2649 	  N_("_Junk"),
2650 	  "<Control>j",
2651 	  N_("Mark the selected messages as junk"),
2652 	  G_CALLBACK (action_mail_mark_junk_cb) },
2653 
2654 	{ "mail-mark-notjunk",
2655 	  "mail-mark-notjunk",
2656 	  N_("_Not Junk"),
2657 	  "<Shift><Control>j",
2658 	  N_("Mark the selected messages as not being junk"),
2659 	  G_CALLBACK (action_mail_mark_notjunk_cb) },
2660 
2661 	{ "mail-mark-read",
2662 	  "mail-mark-read",
2663 	  N_("_Read"),
2664 	  "<Control>k",
2665 	  N_("Mark the selected messages as having been read"),
2666 	  G_CALLBACK (action_mail_mark_read_cb) },
2667 
2668 	{ "mail-mark-unignore-thread-sub",
2669 	  NULL,
2670 	  N_("Do not _Ignore Subthread"),
2671 	  NULL,
2672 	  N_("Do not mark new mails in a subthread as read automatically"),
2673 	  G_CALLBACK (action_mail_mark_unignore_thread_sub_cb) },
2674 
2675 	{ "mail-mark-unignore-thread-whole",
2676 	  NULL,
2677 	  N_("Do not _Ignore Thread"),
2678 	  NULL,
2679 	  N_("Do not mark new mails in this thread as read automatically"),
2680 	  G_CALLBACK (action_mail_mark_unignore_thread_whole_cb) },
2681 
2682 	{ "mail-mark-unimportant",
2683 	  NULL,
2684 	  N_("Uni_mportant"),
2685 	  NULL,
2686 	  N_("Mark the selected messages as unimportant"),
2687 	  G_CALLBACK (action_mail_mark_unimportant_cb) },
2688 
2689 	{ "mail-mark-unread",
2690 	  "mail-mark-unread",
2691 	  N_("_Unread"),
2692 	  "<Shift><Control>k",
2693 	  N_("Mark the selected messages as not having been read"),
2694 	  G_CALLBACK (action_mail_mark_unread_cb) },
2695 
2696 	{ "mail-message-edit",
2697 	  NULL,
2698 	  N_("_Edit as New Message…"),
2699 	  NULL,
2700 	  N_("Open the selected messages in the composer for editing"),
2701 	  G_CALLBACK (action_mail_message_edit_cb) },
2702 
2703 	{ "mail-message-new",
2704 	  "mail-message-new",
2705 	  N_("Compose _New Message"),
2706 	  "<Shift><Control>m",
2707 	  N_("Open a window for composing a mail message"),
2708 	  G_CALLBACK (action_mail_message_new_cb) },
2709 
2710 	{ "mail-message-open",
2711 	  NULL,
2712 	  N_("_Open in New Window"),
2713 	  "<Control>o",
2714 	  N_("Open the selected messages in a new window"),
2715 	  G_CALLBACK (action_mail_message_open_cb) },
2716 
2717 	{ "mail-move",
2718 	  "mail-move",
2719 	  N_("_Move to Folder…"),
2720 	  "<Shift><Control>v",
2721 	  N_("Move selected messages to another folder"),
2722 	  G_CALLBACK (action_mail_move_cb) },
2723 
2724 	{ "mail-next",
2725 	  "go-next",
2726 	  N_("_Next Message"),
2727 	  "<Control>Page_Down",
2728 	  N_("Display the next message"),
2729 	  G_CALLBACK (action_mail_next_cb) },
2730 
2731 	{ "mail-next-important",
2732 	  NULL,
2733 	  N_("Next _Important Message"),
2734 	  NULL,
2735 	  N_("Display the next important message"),
2736 	  G_CALLBACK (action_mail_next_important_cb) },
2737 
2738 	{ "mail-next-thread",
2739 	  NULL,
2740 	  N_("Next _Thread"),
2741 	  NULL,
2742 	  N_("Display the next thread"),
2743 	  G_CALLBACK (action_mail_next_thread_cb) },
2744 
2745 	{ "mail-next-unread",
2746 	  "go-jump",
2747 	  N_("Next _Unread Message"),
2748 	  "<Control>bracketright",
2749 	  N_("Display the next unread message"),
2750 	  G_CALLBACK (action_mail_next_unread_cb) },
2751 
2752 	{ "mail-previous",
2753 	  "go-previous",
2754 	  N_("_Previous Message"),
2755 	  "<Control>Page_Up",
2756 	  N_("Display the previous message"),
2757 	  G_CALLBACK (action_mail_previous_cb) },
2758 
2759 	{ "mail-previous-important",
2760 	  NULL,
2761 	  N_("Pr_evious Important Message"),
2762 	  NULL,
2763 	  N_("Display the previous important message"),
2764 	  G_CALLBACK (action_mail_previous_important_cb) },
2765 
2766 	{ "mail-previous-thread",
2767 	  NULL,
2768 	  N_("Previous T_hread"),
2769 	  NULL,
2770 	  N_("Display the previous thread"),
2771 	  G_CALLBACK (action_mail_previous_thread_cb) },
2772 
2773 	{ "mail-previous-unread",
2774 	  NULL,
2775 	  N_("P_revious Unread Message"),
2776 	  "<Control>bracketleft",
2777 	  N_("Display the previous unread message"),
2778 	  G_CALLBACK (action_mail_previous_unread_cb) },
2779 
2780 	{ "mail-print",
2781 	  "document-print",
2782 	  N_("_Print…"),
2783 	  "<Control>p",
2784 	  N_("Print this message"),
2785 	  G_CALLBACK (action_mail_print_cb) },
2786 
2787 	{ "mail-print-preview",
2788 	  "document-print-preview",
2789 	  N_("Pre_view…"),
2790 	  NULL,
2791 	  N_("Preview the message to be printed"),
2792 	  G_CALLBACK (action_mail_print_preview_cb) },
2793 
2794 	{ "mail-redirect",
2795 	  NULL,
2796 	  N_("Re_direct"),
2797 	  NULL,
2798 	  N_("Redirect (bounce) the selected message to someone"),
2799 	  G_CALLBACK (action_mail_redirect_cb) },
2800 
2801 	{ "mail-remove-attachments",
2802 	  "edit-delete",
2803 	  N_("Remo_ve Attachments"),
2804 	  NULL,
2805 	  N_("Remove attachments"),
2806 	  G_CALLBACK (action_mail_remove_attachments_cb) },
2807 
2808 	{ "mail-remove-duplicates",
2809 	   NULL,
2810 	   N_("Remove Du_plicate Messages"),
2811 	   NULL,
2812 	   N_("Checks selected messages for duplicates"),
2813 	   G_CALLBACK (action_mail_remove_duplicates_cb) },
2814 
2815 	{ "mail-reply-all",
2816 	  NULL,
2817 	  N_("Reply to _All"),
2818 	  "<Shift><Control>r",
2819 	  N_("Compose a reply to all the recipients of the selected message"),
2820 	  G_CALLBACK (action_mail_reply_all_cb) },
2821 
2822 	{ "mail-reply-alternative",
2823 	  NULL,
2824 	  N_("Al_ternative Reply…"),
2825 	  "<Alt><Control>r",
2826 	  N_("Choose reply options for the selected message"),
2827 	  G_CALLBACK (action_mail_reply_alternative_cb) },
2828 
2829 	{ "mail-reply-list",
2830 	  NULL,
2831 	  N_("Reply to _List"),
2832 	  "<Control>l",
2833 	  N_("Compose a reply to the mailing list of the selected message"),
2834 	  G_CALLBACK (action_mail_reply_list_cb) },
2835 
2836 	{ "mail-reply-sender",
2837 	  "mail-reply-sender",
2838 	  N_("_Reply to Sender"),
2839 	  "<Control>r",
2840 	  N_("Compose a reply to the sender of the selected message"),
2841 	  G_CALLBACK (action_mail_reply_sender_cb) },
2842 
2843 	{ "mail-reply-template",
2844 	  NULL,
2845 	  N_("Repl_y with Template"),
2846 	  NULL,
2847 	  NULL,
2848 	  NULL },
2849 
2850 	{ "mail-save-as",
2851 	  "document-save-as",
2852 	  N_("_Save as mbox…"),
2853 	  "<Control>s",
2854 	  N_("Save selected messages as an mbox file"),
2855 	  G_CALLBACK (action_mail_save_as_cb) },
2856 
2857 	{ "mail-search-web",
2858 	  NULL,
2859 	  N_("Search _Web…"),
2860 	  NULL,
2861 	  N_("Search the Web with the selected text"),
2862 	  G_CALLBACK (action_mail_search_web_cb) },
2863 
2864 	{ "mail-show-source",
2865 	  NULL,
2866 	  N_("_Message Source"),
2867 	  "<Control>u",
2868 	  N_("Show the raw email source of the message"),
2869 	  G_CALLBACK (action_mail_show_source_cb) },
2870 
2871 	{ "mail-toggle-important",
2872 	  NULL,
2873 	  NULL,  /* No menu item; key press only */
2874 	  NULL,
2875 	  NULL,
2876 	  G_CALLBACK (action_mail_toggle_important_cb) },
2877 
2878 	{ "mail-undelete",
2879 	  NULL,
2880 	  N_("_Undelete Message"),
2881 	  "<Shift><Control>d",
2882 	  N_("Undelete the selected messages"),
2883 	  G_CALLBACK (action_mail_undelete_cb) },
2884 
2885 	{ "mail-zoom-100",
2886 	  "zoom-original",
2887 	  N_("_Normal Size"),
2888 	  "<Control>0",
2889 	  N_("Reset the text to its original size"),
2890 	  G_CALLBACK (action_mail_zoom_100_cb) },
2891 
2892 	{ "mail-zoom-in",
2893 	  "zoom-in",
2894 	  N_("_Zoom In"),
2895 	  "<Control>plus",
2896 	  N_("Increase the text size"),
2897 	  G_CALLBACK (action_mail_zoom_in_cb) },
2898 
2899 	{ "mail-zoom-out",
2900 	  "zoom-out",
2901 	  N_("Zoom _Out"),
2902 	  "<Control>minus",
2903 	  N_("Decrease the text size"),
2904 	  G_CALLBACK (action_mail_zoom_out_cb) },
2905 
2906 	/*** Menus ***/
2907 
2908 	{ "mail-create-menu",
2909 	  NULL,
2910 	  N_("Cre_ate"),
2911 	  NULL,
2912 	  NULL,
2913 	  NULL },
2914 
2915 	{ "mail-encoding-menu",
2916 	  NULL,
2917 	  N_("Ch_aracter Encoding"),
2918 	  NULL,
2919 	  NULL,
2920 	  NULL },
2921 
2922 	{ "mail-forward-as-menu",
2923 	  NULL,
2924 	  N_("F_orward As"),
2925 	  NULL,
2926 	  NULL,
2927 	  NULL },
2928 
2929 	{ "mail-label-menu",
2930 	  NULL,
2931 	  N_("_Label"),
2932 	  NULL,
2933 	  NULL,
2934 	  NULL },
2935 
2936 	{ "mail-reply-group-menu",
2937 	  NULL,
2938 	  N_("_Group Reply"),
2939 	  NULL,
2940 	  NULL,
2941 	  NULL },
2942 
2943 	{ "mail-goto-menu",
2944 	  NULL,
2945 	  N_("_Go To"),
2946 	  NULL,
2947 	  NULL,
2948 	  NULL },
2949 
2950 	{ "mail-mark-as-menu",
2951 	  NULL,
2952 	  N_("Mar_k As"),
2953 	  NULL,
2954 	  NULL,
2955 	  NULL },
2956 
2957 	{ "mail-message-menu",
2958 	  NULL,
2959 	  N_("_Message"),
2960 	  NULL,
2961 	  NULL,
2962 	  NULL },
2963 
2964 	{ "mail-zoom-menu",
2965 	  NULL,
2966 	  N_("_Zoom"),
2967 	  NULL,
2968 	  NULL,
2969 	  NULL }
2970 };
2971 
2972 static GtkActionEntry mail_reader_search_folder_entries[] = {
2973 
2974 	{ "mail-search-folder-from-mailing-list",
2975 	  NULL,
2976 	  N_("Create a Search Folder from Mailing _List…"),
2977 	  NULL,
2978 	  N_("Create a search folder for this mailing list"),
2979 	  G_CALLBACK (action_mail_search_folder_from_mailing_list_cb) },
2980 
2981 	{ "mail-search-folder-from-recipients",
2982 	  NULL,
2983 	  N_("Create a Search Folder from Recipien_ts…"),
2984 	  NULL,
2985 	  N_("Create a search folder for these recipients"),
2986 	  G_CALLBACK (action_mail_search_folder_from_recipients_cb) },
2987 
2988 	{ "mail-search-folder-from-sender",
2989 	  NULL,
2990 	  N_("Create a Search Folder from Sen_der…"),
2991 	  NULL,
2992 	  N_("Create a search folder for this sender"),
2993 	  G_CALLBACK (action_mail_search_folder_from_sender_cb) },
2994 
2995 	{ "mail-search-folder-from-subject",
2996 	  NULL,
2997 	  N_("Create a Search Folder from S_ubject…"),
2998 	  NULL,
2999 	  N_("Create a search folder for this subject"),
3000 	  G_CALLBACK (action_mail_search_folder_from_subject_cb) },
3001 };
3002 
3003 static EPopupActionEntry mail_reader_popup_entries[] = {
3004 
3005 	{ "mail-popup-archive",
3006 	  NULL,
3007 	  "mail-archive" },
3008 
3009 	{ "mail-popup-color-assign",
3010 	  NULL,
3011 	  "mail-color-assign" },
3012 
3013 	{ "mail-popup-color-unset",
3014 	  NULL,
3015 	  "mail-color-unset" },
3016 
3017 	{ "mail-popup-copy",
3018 	  NULL,
3019 	  "mail-copy" },
3020 
3021 	{ "mail-popup-delete",
3022 	  NULL,
3023 	  "mail-delete" },
3024 
3025 	{ "mail-popup-add-note",
3026 	  NULL,
3027 	  "mail-add-note" },
3028 
3029 	{ "mail-popup-delete-note",
3030 	  NULL,
3031 	  "mail-delete-note" },
3032 
3033 	{ "mail-popup-edit-note",
3034 	  NULL,
3035 	  "mail-edit-note" },
3036 
3037 	{ "mail-popup-flag-clear",
3038 	  NULL,
3039 	  "mail-flag-clear" },
3040 
3041 	{ "mail-popup-flag-completed",
3042 	  NULL,
3043 	  "mail-flag-completed" },
3044 
3045 	{ "mail-popup-flag-for-followup",
3046 	  N_("Mark for Follo_w Up…"),
3047 	  "mail-flag-for-followup" },
3048 
3049 	{ "mail-popup-forward",
3050 	  NULL,
3051 	  "mail-forward" },
3052 
3053 	{ "mail-popup-mark-ignore-thread-sub",
3054 	  N_("_Ignore Subthread"),
3055 	  "mail-mark-ignore-thread-sub" },
3056 
3057 	{ "mail-popup-mark-ignore-thread-whole",
3058 	  N_("_Ignore Thread"),
3059 	  "mail-mark-ignore-thread-whole" },
3060 
3061 	{ "mail-popup-mark-important",
3062 	  N_("Mark as _Important"),
3063 	  "mail-mark-important" },
3064 
3065 	{ "mail-popup-mark-junk",
3066 	  N_("Mark as _Junk"),
3067 	  "mail-mark-junk" },
3068 
3069 	{ "mail-popup-mark-notjunk",
3070 	  N_("Mark as _Not Junk"),
3071 	  "mail-mark-notjunk" },
3072 
3073 	{ "mail-popup-mark-read",
3074 	  N_("Mar_k as Read"),
3075 	  "mail-mark-read" },
3076 
3077 	{ "mail-popup-mark-unignore-thread-sub",
3078 	  N_("Do not _Ignore Subthread"),
3079 	  "mail-mark-unignore-thread-sub" },
3080 
3081 	{ "mail-popup-mark-unignore-thread-whole",
3082 	  N_("Do not _Ignore Thread"),
3083 	  "mail-mark-unignore-thread-whole" },
3084 
3085 	{ "mail-popup-mark-unimportant",
3086 	  N_("Mark as Uni_mportant"),
3087 	  "mail-mark-unimportant" },
3088 
3089 	{ "mail-popup-mark-unread",
3090 	  N_("Mark as _Unread"),
3091 	  "mail-mark-unread" },
3092 
3093 	{ "mail-popup-message-edit",
3094 	  NULL,
3095 	  "mail-message-edit" },
3096 
3097 	{ "mail-popup-move",
3098 	  NULL,
3099 	  "mail-move" },
3100 
3101 	{ "mail-popup-print",
3102 	  NULL,
3103 	  "mail-print" },
3104 
3105 	{ "mail-popup-remove-attachments",
3106 	  NULL,
3107 	  "mail-remove-attachments" },
3108 
3109 	{ "mail-popup-remove-duplicates",
3110 	  NULL,
3111 	  "mail-remove-duplicates" },
3112 
3113 	{ "mail-popup-reply-all",
3114 	  NULL,
3115 	  "mail-reply-all" },
3116 
3117 	{ "mail-popup-reply-sender",
3118 	  NULL,
3119 	  "mail-reply-sender" },
3120 
3121 	{ "mail-popup-reply-template",
3122 	  NULL,
3123 	  "mail-reply-template" },
3124 
3125 	{ "mail-popup-save-as",
3126 	  NULL,
3127 	  "mail-save-as" },
3128 
3129 	{ "mail-popup-search-web",
3130 	  NULL,
3131 	  "mail-search-web" },
3132 
3133 	{ "mail-popup-undelete",
3134 	  NULL,
3135 	  "mail-undelete" }
3136 };
3137 
3138 static GtkToggleActionEntry mail_reader_toggle_entries[] = {
3139 
3140 	{ "mail-caret-mode",
3141 	  NULL,
3142 	  N_("_Caret Mode"),
3143 	  "F7",
3144 	  N_("Show a blinking cursor in the body of displayed messages"),
3145 	  NULL,  /* No callback required */
3146 	  FALSE },
3147 
3148 	{ "mail-show-all-headers",
3149 	  NULL,
3150 	  N_("All Message _Headers"),
3151 	  NULL,
3152 	  N_("Show messages with all email headers"),
3153 	  G_CALLBACK (action_mail_show_all_headers_cb),
3154 	  FALSE }
3155 };
3156 
3157 static void
mail_reader_double_click_cb(EMailReader * reader,gint row,ETreePath path,gint col,GdkEvent * event)3158 mail_reader_double_click_cb (EMailReader *reader,
3159                              gint row,
3160                              ETreePath path,
3161                              gint col,
3162                              GdkEvent *event)
3163 {
3164 	GtkAction *action;
3165 
3166 	/* Ignore double clicks on columns that handle their own state. */
3167 	if (MESSAGE_LIST_COLUMN_IS_ACTIVE (col))
3168 		return;
3169 
3170 	action = e_mail_reader_get_action (reader, "mail-message-open");
3171 	gtk_action_activate (action);
3172 }
3173 
3174 static gboolean
mail_reader_key_press_event_cb(EMailReader * reader,GdkEventKey * event)3175 mail_reader_key_press_event_cb (EMailReader *reader,
3176                                 GdkEventKey *event)
3177 {
3178 	GtkAction *action;
3179 	const gchar *action_name;
3180 
3181 	if (!gtk_widget_has_focus (GTK_WIDGET (reader))) {
3182 		EMailDisplay *display;
3183 
3184 		display = e_mail_reader_get_mail_display (reader);
3185 		if (e_web_view_get_need_input (E_WEB_VIEW (display)) &&
3186 		    gtk_widget_has_focus (GTK_WIDGET (display)))
3187 			return FALSE;
3188 	}
3189 
3190 	if ((event->state & GDK_CONTROL_MASK) != 0)
3191 		goto ctrl;
3192 
3193 	/* <keyval> alone */
3194 	switch (event->keyval) {
3195 		case GDK_KEY_Delete:
3196 		case GDK_KEY_KP_Delete:
3197 			action_name = "mail-delete";
3198 			break;
3199 
3200 		case GDK_KEY_Return:
3201 		case GDK_KEY_KP_Enter:
3202 		case GDK_KEY_ISO_Enter:
3203 			if (E_IS_MAIL_BROWSER (reader))
3204 				return FALSE;
3205 
3206 			action_name = "mail-message-open";
3207 			break;
3208 
3209 		case GDK_KEY_period:
3210 		case GDK_KEY_bracketright:
3211 			action_name = "mail-next-unread";
3212 			break;
3213 
3214 		case GDK_KEY_comma:
3215 		case GDK_KEY_bracketleft:
3216 			action_name = "mail-previous-unread";
3217 			break;
3218 
3219 #ifdef HAVE_XFREE
3220 		case XF86XK_Reply:
3221 			action_name = "mail-reply-all";
3222 			break;
3223 
3224 		case XF86XK_MailForward:
3225 			action_name = "mail-forward";
3226 			break;
3227 #endif
3228 
3229 		case GDK_KEY_exclam:
3230 			action_name = "mail-toggle-important";
3231 			break;
3232 
3233 		case GDK_KEY_ZoomIn:
3234 			action_name = "mail-zoom-in";
3235 			break;
3236 
3237 		case GDK_KEY_ZoomOut:
3238 			action_name = "mail-zoom-out";
3239 			break;
3240 
3241 		default:
3242 			return FALSE;
3243 	}
3244 
3245 	goto exit;
3246 
3247 ctrl:
3248 
3249 	/* Ctrl + <keyval> */
3250 	switch (event->keyval) {
3251 		case GDK_KEY_period:
3252 			action_name = "mail-next-unread";
3253 			break;
3254 
3255 		case GDK_KEY_comma:
3256 			action_name = "mail-previous-unread";
3257 			break;
3258 
3259 		case GDK_KEY_equal:
3260 		case GDK_KEY_KP_Add:
3261 			action_name = "mail-zoom-in";
3262 			break;
3263 
3264 		case GDK_KEY_KP_Subtract:
3265 			action_name = "mail-zoom-out";
3266 			break;
3267 
3268 		default:
3269 			return FALSE;
3270 	}
3271 
3272 exit:
3273 	action = e_mail_reader_get_action (reader, action_name);
3274 	gtk_action_activate (action);
3275 
3276 	return TRUE;
3277 }
3278 
3279 static gint
mail_reader_key_press_cb(EMailReader * reader,gint row,ETreePath path,gint col,GdkEvent * event)3280 mail_reader_key_press_cb (EMailReader *reader,
3281                           gint row,
3282                           ETreePath path,
3283                           gint col,
3284                           GdkEvent *event)
3285 {
3286 	return mail_reader_key_press_event_cb (reader, &event->key);
3287 }
3288 
3289 static gboolean
mail_reader_message_seen_cb(gpointer user_data)3290 mail_reader_message_seen_cb (gpointer user_data)
3291 {
3292 	EMailReaderClosure *closure = user_data;
3293 	EMailReader *reader;
3294 	GtkWidget *message_list;
3295 	EMailPartList *parts;
3296 	EMailDisplay *display;
3297 	CamelMimeMessage *message;
3298 	const gchar *current_uid;
3299 	const gchar *message_uid;
3300 	gboolean uid_is_current = TRUE;
3301 
3302 	reader = closure->reader;
3303 	message_uid = closure->message_uid;
3304 
3305 	display = e_mail_reader_get_mail_display (reader);
3306 	parts = e_mail_display_get_part_list (display);
3307 	message_list = e_mail_reader_get_message_list (reader);
3308 
3309 	g_return_val_if_fail (IS_MESSAGE_LIST (message_list), FALSE);
3310 
3311 	/* zero the timeout id now, if it was not rescheduled */
3312 	if (g_source_get_id (g_main_current_source ()) == MESSAGE_LIST (message_list)->seen_id)
3313 		MESSAGE_LIST (message_list)->seen_id = 0;
3314 
3315 	if (e_tree_is_dragging (E_TREE (message_list)))
3316 		return FALSE;
3317 
3318 	current_uid = MESSAGE_LIST (message_list)->cursor_uid;
3319 	uid_is_current &= (g_strcmp0 (current_uid, message_uid) == 0);
3320 
3321 	if (parts != NULL)
3322 		message = e_mail_part_list_get_message (parts);
3323 	else
3324 		message = NULL;
3325 
3326 	if (uid_is_current && message != NULL)
3327 		g_signal_emit (
3328 			reader, signals[MESSAGE_SEEN], 0,
3329 			message_uid, message);
3330 
3331 	return FALSE;
3332 }
3333 
3334 static void
schedule_timeout_mark_seen(EMailReader * reader)3335 schedule_timeout_mark_seen (EMailReader *reader)
3336 {
3337 	EMailReaderPrivate *priv;
3338 	MessageList *message_list;
3339 
3340 	g_return_if_fail (E_IS_MAIL_READER (reader));
3341 
3342 	priv = E_MAIL_READER_GET_PRIVATE (reader);
3343 
3344 	message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
3345 	g_return_if_fail (message_list != NULL);
3346 
3347 	if (message_list->cursor_uid) {
3348 		EMailReaderClosure *timeout_closure;
3349 
3350 		if (message_list->seen_id > 0) {
3351 			g_source_remove (message_list->seen_id);
3352 			message_list->seen_id = 0;
3353 		}
3354 
3355 		timeout_closure = g_slice_new0 (EMailReaderClosure);
3356 		timeout_closure->reader = g_object_ref (reader);
3357 		timeout_closure->message_uid = g_strdup (message_list->cursor_uid);
3358 
3359 		MESSAGE_LIST (message_list)->seen_id =
3360 			e_named_timeout_add_full (
3361 				G_PRIORITY_DEFAULT, priv->schedule_mark_seen_interval,
3362 				mail_reader_message_seen_cb,
3363 				timeout_closure, (GDestroyNotify)
3364 				mail_reader_closure_free);
3365 	}
3366 }
3367 
3368 static void
mail_reader_load_changed_cb(EMailReader * reader,WebKitLoadEvent event,EMailDisplay * display)3369 mail_reader_load_changed_cb (EMailReader *reader,
3370                              WebKitLoadEvent event,
3371                              EMailDisplay *display)
3372 {
3373 	EMailReaderPrivate *priv;
3374 
3375 	if (event != WEBKIT_LOAD_FINISHED)
3376 		return;
3377 
3378 	priv = E_MAIL_READER_GET_PRIVATE (reader);
3379 	if (priv->schedule_mark_seen &&
3380 	    E_IS_MAIL_VIEW (reader) &&
3381 	    e_mail_display_get_part_list (display) &&
3382 	    e_mail_view_get_preview_visible (E_MAIL_VIEW (reader))) {
3383 		if (priv->folder_was_just_selected)
3384 			priv->folder_was_just_selected = FALSE;
3385 		else
3386 			schedule_timeout_mark_seen (reader);
3387 	}
3388 }
3389 
3390 static void
mail_reader_remote_content_clicked_cb(EMailReader * reader,const GdkRectangle * position,gpointer user_data)3391 mail_reader_remote_content_clicked_cb (EMailReader *reader,
3392 				       const GdkRectangle *position,
3393 				       gpointer user_data)
3394 {
3395 	GtkWidget *mail_display = user_data;
3396 
3397 	g_return_if_fail (E_IS_MAIL_READER (reader));
3398 	g_return_if_fail (E_IS_MAIL_DISPLAY (mail_display));
3399 
3400 	e_mail_remote_content_popover_run (reader, mail_display, position);
3401 }
3402 
3403 static void
maybe_schedule_timeout_mark_seen(EMailReader * reader)3404 maybe_schedule_timeout_mark_seen (EMailReader *reader)
3405 {
3406 	EMailReaderPrivate *priv;
3407 	MessageList *message_list;
3408 	gboolean schedule_timeout;
3409 	gint timeout_interval = -1;
3410 	const gchar *message_uid;
3411 
3412 	message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
3413 
3414 	message_uid = message_list->cursor_uid;
3415 	if (message_uid == NULL ||
3416 	    e_tree_is_dragging (E_TREE (message_list)))
3417 		return;
3418 
3419 	schedule_timeout =
3420 		(message_uid != NULL) &&
3421 		e_mail_reader_utils_get_mark_seen_setting (reader, &timeout_interval);
3422 
3423 	if (message_list->seen_id > 0) {
3424 		g_source_remove (message_list->seen_id);
3425 		message_list->seen_id = 0;
3426 	}
3427 
3428 	priv = E_MAIL_READER_GET_PRIVATE (reader);
3429 	priv->schedule_mark_seen = schedule_timeout;
3430 	priv->schedule_mark_seen_interval = timeout_interval;
3431 }
3432 
3433 static gboolean
discard_timeout_mark_seen_cb(EMailReader * reader)3434 discard_timeout_mark_seen_cb (EMailReader *reader)
3435 {
3436 	EMailReaderPrivate *priv;
3437 	MessageList *message_list;
3438 
3439 	g_return_val_if_fail (reader != NULL, FALSE);
3440 
3441 	priv = E_MAIL_READER_GET_PRIVATE (reader);
3442 	priv->schedule_mark_seen = FALSE;
3443 
3444 	message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
3445 	g_return_val_if_fail (message_list != NULL, FALSE);
3446 
3447 	if (message_list->seen_id > 0) {
3448 		g_source_remove (message_list->seen_id);
3449 		message_list->seen_id = 0;
3450 	}
3451 
3452 	return FALSE;
3453 }
3454 
3455 
3456 static void
mail_reader_preview_pane_visible_changed_cb(EMailReader * reader,GParamSpec * param,GtkWidget * widget)3457 mail_reader_preview_pane_visible_changed_cb (EMailReader *reader,
3458 					     GParamSpec *param,
3459 					     GtkWidget *widget)
3460 {
3461 	g_return_if_fail (E_IS_MAIL_READER (reader));
3462 	g_return_if_fail (GTK_IS_WIDGET (widget));
3463 
3464 	if (!gtk_widget_get_visible (widget))
3465 		discard_timeout_mark_seen_cb (reader);
3466 }
3467 
3468 static void
mail_reader_remove_followup_alert(EMailReader * reader)3469 mail_reader_remove_followup_alert (EMailReader *reader)
3470 {
3471 	EMailReaderPrivate *priv;
3472 
3473 	g_return_if_fail (E_IS_MAIL_READER (reader));
3474 
3475 	priv = E_MAIL_READER_GET_PRIVATE (reader);
3476 	if (!priv)
3477 		return;
3478 
3479 	if (priv->followup_alert)
3480 		e_alert_response (priv->followup_alert, GTK_RESPONSE_OK);
3481 }
3482 
3483 static void
mail_reader_manage_followup_flag(EMailReader * reader,CamelFolder * folder,const gchar * message_uid)3484 mail_reader_manage_followup_flag (EMailReader *reader,
3485 				  CamelFolder *folder,
3486 				  const gchar *message_uid)
3487 {
3488 	EMailReaderPrivate *priv;
3489 	CamelMessageInfo *info;
3490 	const gchar *followup, *completed_on, *due_by;
3491 	time_t date;
3492 	gchar *date_str = NULL;
3493 	gboolean alert_added = FALSE;
3494 
3495 	g_return_if_fail (E_IS_MAIL_READER (reader));
3496 	g_return_if_fail (CAMEL_IS_FOLDER (folder));
3497 	g_return_if_fail (message_uid != NULL);
3498 
3499 	priv = E_MAIL_READER_GET_PRIVATE (reader);
3500 	if (!priv)
3501 		return;
3502 
3503 	info = camel_folder_get_message_info (folder, message_uid);
3504 	if (!info)
3505 		return;
3506 
3507 	followup = camel_message_info_get_user_tag (info, "follow-up");
3508 	if (followup && *followup) {
3509 		EPreviewPane *preview_pane;
3510 		const gchar *alert_tag;
3511 		EAlert *alert;
3512 
3513 		completed_on = camel_message_info_get_user_tag (info, "completed-on");
3514 		due_by = camel_message_info_get_user_tag (info, "due-by");
3515 
3516 		if (completed_on && *completed_on) {
3517 			alert_tag = "mail:follow-up-completed-info";
3518 			date = camel_header_decode_date (completed_on, NULL);
3519 			date_str = e_datetime_format_format ("mail", "header", DTFormatKindDateTime, date);
3520 		} else if (due_by && *due_by) {
3521 			time_t now;
3522 
3523 			alert_tag = "mail:follow-up-dueby-info";
3524 			date = camel_header_decode_date (due_by, NULL);
3525 			date_str = e_datetime_format_format ("mail", "header", DTFormatKindDateTime, date);
3526 
3527 			now = time (NULL);
3528 			if (now > date)
3529 				alert_tag = "mail:follow-up-overdue-error";
3530 		} else {
3531 			alert_tag = "mail:follow-up-flag-info";
3532 		}
3533 
3534 		alert = e_alert_new (alert_tag, followup, date_str ? date_str : "???", NULL);
3535 
3536 		g_free (date_str);
3537 
3538 		preview_pane = e_mail_reader_get_preview_pane (reader);
3539 		e_alert_sink_submit_alert (E_ALERT_SINK (preview_pane), alert);
3540 
3541 		alert_added = TRUE;
3542 
3543 		mail_reader_remove_followup_alert (reader);
3544 		priv->followup_alert = alert;
3545 		g_object_add_weak_pointer (G_OBJECT (priv->followup_alert), &priv->followup_alert);
3546 
3547 		g_object_unref (alert);
3548 	}
3549 
3550 	g_clear_object (&info);
3551 
3552 	if (!alert_added)
3553 		mail_reader_remove_followup_alert (reader);
3554 }
3555 
3556 static void
mail_reader_reload(EMailReader * reader)3557 mail_reader_reload (EMailReader *reader)
3558 {
3559 	CamelFolder *folder;
3560 	GPtrArray *uids;
3561 	EMailDisplay *mail_display;
3562 
3563 	g_return_if_fail (E_IS_MAIL_READER (reader));
3564 
3565 	folder = e_mail_reader_ref_folder (reader);
3566 	uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
3567 
3568 	if (uids && uids->len == 1)
3569 		mail_reader_manage_followup_flag (reader, folder, uids->pdata[0]);
3570 
3571 	g_clear_object (&folder);
3572 	if (uids)
3573 		g_ptr_array_unref (uids);
3574 
3575 	mail_display = e_mail_reader_get_mail_display (reader);
3576 	e_mail_display_reload (mail_display);
3577 }
3578 
3579 static void
mail_reader_remove_ui(EMailReader * reader)3580 mail_reader_remove_ui (EMailReader *reader)
3581 {
3582 	EMailReaderPrivate *priv;
3583 	GtkWindow *window;
3584 	GtkUIManager *ui_manager = NULL;
3585 
3586 	g_return_if_fail (E_IS_MAIL_READER (reader));
3587 
3588 	priv = E_MAIL_READER_GET_PRIVATE (reader);
3589 
3590 	if (!priv->main_menu_label_merge_id)
3591 		return;
3592 
3593 	window = e_mail_reader_get_window (reader);
3594 	g_return_if_fail (window != NULL);
3595 
3596 	if (E_IS_SHELL_WINDOW (window))
3597 		ui_manager = e_shell_window_get_ui_manager (E_SHELL_WINDOW (window));
3598 	else if (E_IS_MAIL_BROWSER (window))
3599 		ui_manager = e_mail_browser_get_ui_manager (E_MAIL_BROWSER (window));
3600 
3601 	g_return_if_fail (ui_manager != NULL);
3602 	g_return_if_fail (GTK_IS_UI_MANAGER (ui_manager));
3603 
3604 	gtk_ui_manager_remove_ui (ui_manager, priv->main_menu_label_merge_id);
3605 }
3606 
3607 static void
mail_reader_message_loaded_cb(CamelFolder * folder,GAsyncResult * result,EMailReaderClosure * closure)3608 mail_reader_message_loaded_cb (CamelFolder *folder,
3609                                GAsyncResult *result,
3610                                EMailReaderClosure *closure)
3611 {
3612 	EMailReader *reader;
3613 	EMailReaderPrivate *priv;
3614 	CamelMimeMessage *message = NULL;
3615 	GtkWidget *message_list;
3616 	const gchar *message_uid;
3617 	GError *error = NULL;
3618 
3619 	reader = closure->reader;
3620 	message_uid = closure->message_uid;
3621 
3622 	priv = E_MAIL_READER_GET_PRIVATE (reader);
3623 
3624 	/* If the private struct is NULL, the EMailReader was destroyed
3625 	 * while we were loading the message and we're likely holding the
3626 	 * last reference.  Nothing to do but drop the reference.
3627 	 * FIXME Use a GWeakRef instead of this hack. */
3628 	if (priv == NULL) {
3629 		mail_reader_closure_free (closure);
3630 		return;
3631 	}
3632 
3633 	message = camel_folder_get_message_finish (folder, result, &error);
3634 
3635 	/* If the user picked a different message in the time it took
3636 	 * to fetch this message, then don't bother rendering it. */
3637 	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
3638 		g_clear_error (&error);
3639 		goto exit;
3640 	}
3641 
3642 	message_list = e_mail_reader_get_message_list (reader);
3643 
3644 	if (message_list == NULL) {
3645 		/* For cases where message fetching took so long that
3646 		 * user closed the message window before this was called. */
3647 		goto exit;
3648 	}
3649 
3650 	if (message != NULL) {
3651 		CamelMessageInfo *mi;
3652 
3653 		mail_reader_manage_followup_flag (reader, folder, message_uid);
3654 
3655 		mi = camel_folder_get_message_info (folder, message_uid);
3656 		if (mi) {
3657 			if (camel_util_fill_message_info_user_headers (mi, camel_medium_get_headers (CAMEL_MEDIUM (message))))
3658 				gtk_widget_queue_draw (message_list);
3659 
3660 			g_object_unref (mi);
3661 		}
3662 
3663 		g_signal_emit (
3664 			reader, signals[MESSAGE_LOADED], 0,
3665 			message_uid, message);
3666 	}
3667 
3668 exit:
3669 	if (error != NULL) {
3670 		EPreviewPane *preview_pane;
3671 		EWebView *web_view;
3672 
3673 		preview_pane = e_mail_reader_get_preview_pane (reader);
3674 		web_view = e_preview_pane_get_web_view (preview_pane);
3675 
3676 		if (g_error_matches (error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_UNAVAILABLE) &&
3677 		    CAMEL_IS_OFFLINE_FOLDER (folder) &&
3678 		    camel_service_get_connection_status (CAMEL_SERVICE (camel_folder_get_parent_store (folder))) != CAMEL_SERVICE_CONNECTED)
3679 			e_alert_submit (
3680 				E_ALERT_SINK (web_view),
3681 				"mail:no-retrieve-message-offline",
3682 				NULL);
3683 		else
3684 			e_alert_submit (
3685 				E_ALERT_SINK (web_view),
3686 				"mail:no-retrieve-message",
3687 				error->message, NULL);
3688 	}
3689 
3690 	g_clear_error (&error);
3691 
3692 	mail_reader_closure_free (closure);
3693 
3694 	g_clear_object (&message);
3695 }
3696 
3697 static gboolean
mail_reader_message_selected_timeout_cb(gpointer user_data)3698 mail_reader_message_selected_timeout_cb (gpointer user_data)
3699 {
3700 	EMailReader *reader;
3701 	EMailReaderPrivate *priv;
3702 	EMailDisplay *display;
3703 	GtkWidget *message_list;
3704 	const gchar *cursor_uid;
3705 	const gchar *format_uid;
3706 	EMailPartList *parts;
3707 
3708 	reader = E_MAIL_READER (user_data);
3709 	priv = E_MAIL_READER_GET_PRIVATE (reader);
3710 
3711 	message_list = e_mail_reader_get_message_list (reader);
3712 	display = e_mail_reader_get_mail_display (reader);
3713 	parts = e_mail_display_get_part_list (display);
3714 
3715 	cursor_uid = MESSAGE_LIST (message_list)->cursor_uid;
3716 	if (parts != NULL)
3717 		format_uid = e_mail_part_list_get_message_uid (parts);
3718 	else
3719 		format_uid = NULL;
3720 
3721 	if (MESSAGE_LIST (message_list)->last_sel_single) {
3722 		GtkWidget *widget;
3723 		gboolean display_visible;
3724 		gboolean selected_uid_changed;
3725 
3726 		/* Decide whether to download the full message now. */
3727 		widget = GTK_WIDGET (display);
3728 		display_visible = gtk_widget_get_mapped (widget);
3729 
3730 		selected_uid_changed = (g_strcmp0 (cursor_uid, format_uid) != 0);
3731 
3732 		if (display_visible && selected_uid_changed) {
3733 			EMailReaderClosure *closure;
3734 			GCancellable *cancellable;
3735 			CamelFolder *folder;
3736 			EActivity *activity;
3737 			gchar *string;
3738 
3739 			string = g_strdup_printf (
3740 				_("Retrieving message “%s”"), cursor_uid);
3741 			e_mail_display_set_part_list (display, NULL);
3742 			e_mail_display_set_status (display, string);
3743 			g_free (string);
3744 
3745 			activity = e_mail_reader_new_activity (reader);
3746 			e_activity_set_text (activity, _("Retrieving message"));
3747 			cancellable = e_activity_get_cancellable (activity);
3748 
3749 			closure = g_slice_new0 (EMailReaderClosure);
3750 			closure->activity = activity;
3751 			closure->reader = g_object_ref (reader);
3752 			closure->message_uid = g_strdup (cursor_uid);
3753 
3754 			folder = e_mail_reader_ref_folder (reader);
3755 
3756 			camel_folder_get_message (
3757 				folder, cursor_uid, G_PRIORITY_DEFAULT,
3758 				cancellable, (GAsyncReadyCallback)
3759 				mail_reader_message_loaded_cb, closure);
3760 
3761 			g_clear_object (&folder);
3762 
3763 			if (priv->retrieving_message != NULL)
3764 				g_object_unref (priv->retrieving_message);
3765 			priv->retrieving_message = g_object_ref (cancellable);
3766 		}
3767 	} else {
3768 		e_mail_display_set_part_list (display, NULL);
3769 	}
3770 
3771 	priv->message_selected_timeout_id = 0;
3772 
3773 	return FALSE;
3774 }
3775 
3776 static void
mail_reader_message_selected_cb(EMailReader * reader,const gchar * message_uid)3777 mail_reader_message_selected_cb (EMailReader *reader,
3778                                  const gchar *message_uid)
3779 {
3780 	EMailReaderPrivate *priv;
3781 	MessageList *message_list;
3782 
3783 	priv = E_MAIL_READER_GET_PRIVATE (reader);
3784 
3785 	/* Cancel the previous message retrieval activity. */
3786 	g_cancellable_cancel (priv->retrieving_message);
3787 
3788 	/* Cancel the message selected timer. */
3789 	if (priv->message_selected_timeout_id > 0) {
3790 		g_source_remove (priv->message_selected_timeout_id);
3791 		priv->message_selected_timeout_id = 0;
3792 	}
3793 
3794 	if (priv->folder_was_just_selected && message_uid) {
3795 		if (priv->did_try_to_open_message)
3796 			priv->folder_was_just_selected = FALSE;
3797 		else
3798 			priv->did_try_to_open_message = TRUE;
3799 	}
3800 
3801 	message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
3802 	if (message_list) {
3803 		EMailPartList *parts;
3804 		const gchar *cursor_uid, *format_uid;
3805 
3806 		parts = e_mail_display_get_part_list (e_mail_reader_get_mail_display (reader));
3807 
3808 		cursor_uid = MESSAGE_LIST (message_list)->cursor_uid;
3809 		if (parts != NULL)
3810 			format_uid = e_mail_part_list_get_message_uid (parts);
3811 		else
3812 			format_uid = NULL;
3813 
3814 		/* It can happen when the message was loaded that quickly that
3815 		   it was delivered before this callback. */
3816 		if (g_strcmp0 (cursor_uid, format_uid) == 0) {
3817 			e_mail_reader_changed (reader);
3818 			return;
3819 		}
3820 	}
3821 
3822 	/* Cancel the seen timer. */
3823 	if (message_list != NULL && message_list->seen_id) {
3824 		g_source_remove (message_list->seen_id);
3825 		message_list->seen_id = 0;
3826 	}
3827 
3828 	if (message_list_selected_count (message_list) != 1) {
3829 		EMailDisplay *display;
3830 
3831 		display = e_mail_reader_get_mail_display (reader);
3832 		e_mail_display_set_part_list (display, NULL);
3833 		e_web_view_clear (E_WEB_VIEW (display));
3834 
3835 	} else if (priv->folder_was_just_selected) {
3836 		/* Skip the timeout if we're restoring the previous message
3837 		 * selection.  The timeout is there for when we're scrolling
3838 		 * rapidly through the message list. */
3839 		mail_reader_message_selected_timeout_cb (reader);
3840 
3841 	} else {
3842 		priv->message_selected_timeout_id = e_named_timeout_add (
3843 			100, mail_reader_message_selected_timeout_cb, reader);
3844 	}
3845 
3846 	e_mail_reader_changed (reader);
3847 }
3848 
3849 static void
mail_reader_message_cursor_change_cb(EMailReader * reader)3850 mail_reader_message_cursor_change_cb (EMailReader *reader)
3851 {
3852 	MessageList *message_list;
3853 	EMailReaderPrivate *priv;
3854 
3855 	g_return_if_fail (reader != NULL);
3856 
3857 	priv = E_MAIL_READER_GET_PRIVATE (reader);
3858 	g_return_if_fail (priv != NULL);
3859 
3860 	message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
3861 	g_return_if_fail (message_list != NULL);
3862 
3863 	if (message_list->seen_id == 0 &&
3864 	    E_IS_MAIL_VIEW (reader) &&
3865 	    e_mail_view_get_preview_visible (E_MAIL_VIEW (reader)) &&
3866 	    !priv->avoid_next_mark_as_seen)
3867 		maybe_schedule_timeout_mark_seen (reader);
3868 }
3869 
3870 static void
mail_reader_emit_folder_loaded(EMailReader * reader)3871 mail_reader_emit_folder_loaded (EMailReader *reader)
3872 {
3873 	EMailReaderPrivate *priv;
3874 	MessageList *message_list;
3875 
3876 	priv = E_MAIL_READER_GET_PRIVATE (reader);
3877 	message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
3878 
3879 	if (priv && (message_list_count (message_list) <= 0 ||
3880 	    message_list_selected_count (message_list) <= 0))
3881 		priv->avoid_next_mark_as_seen = FALSE;
3882 
3883 	g_signal_emit (reader, signals[FOLDER_LOADED], 0);
3884 }
3885 
3886 static void
mail_reader_message_list_built_cb(MessageList * message_list,EMailReader * reader)3887 mail_reader_message_list_built_cb (MessageList *message_list,
3888 				   EMailReader *reader)
3889 {
3890 	EMailReaderPrivate *priv;
3891 
3892 	priv = E_MAIL_READER_GET_PRIVATE (reader);
3893 	mail_reader_emit_folder_loaded (reader);
3894 
3895 	/* No cursor_uid means that there will not be emitted any
3896 	   "cursor-changed" and "message-selected" signal, thus
3897 	   unset the "just selected folder" flag */
3898 	if (!message_list->cursor_uid)
3899 		priv->folder_was_just_selected = FALSE;
3900 }
3901 
3902 static EAlertSink *
mail_reader_get_alert_sink(EMailReader * reader)3903 mail_reader_get_alert_sink (EMailReader *reader)
3904 {
3905 	EPreviewPane *preview_pane;
3906 
3907 	preview_pane = e_mail_reader_get_preview_pane (reader);
3908 
3909 	if (!gtk_widget_is_visible (GTK_WIDGET (preview_pane))) {
3910 		GtkWindow *window;
3911 
3912 		window = e_mail_reader_get_window (reader);
3913 
3914 		if (E_IS_SHELL_WINDOW (window))
3915 			return E_ALERT_SINK (window);
3916 	}
3917 
3918 	return E_ALERT_SINK (preview_pane);
3919 }
3920 
3921 static GPtrArray *
mail_reader_get_selected_uids(EMailReader * reader)3922 mail_reader_get_selected_uids (EMailReader *reader)
3923 {
3924 	GtkWidget *message_list;
3925 
3926 	message_list = e_mail_reader_get_message_list (reader);
3927 
3928 	return message_list_get_selected (MESSAGE_LIST (message_list));
3929 }
3930 
3931 static GPtrArray *
mail_reader_get_selected_uids_with_collapsed_threads(EMailReader * reader)3932 mail_reader_get_selected_uids_with_collapsed_threads (EMailReader *reader)
3933 {
3934 	GtkWidget *message_list;
3935 
3936 	message_list = e_mail_reader_get_message_list (reader);
3937 
3938 	return message_list_get_selected_with_collapsed_threads (MESSAGE_LIST (message_list));
3939 }
3940 
3941 static CamelFolder *
mail_reader_ref_folder(EMailReader * reader)3942 mail_reader_ref_folder (EMailReader *reader)
3943 {
3944 	GtkWidget *message_list;
3945 
3946 	message_list = e_mail_reader_get_message_list (reader);
3947 
3948 	return message_list_ref_folder (MESSAGE_LIST (message_list));
3949 }
3950 
3951 static void
mail_reader_set_folder(EMailReader * reader,CamelFolder * folder)3952 mail_reader_set_folder (EMailReader *reader,
3953                         CamelFolder *folder)
3954 {
3955 	EMailReaderPrivate *priv;
3956 	EMailDisplay *display;
3957 	CamelFolder *previous_folder;
3958 	GtkWidget *message_list;
3959 	EMailBackend *backend;
3960 	EShell *shell;
3961 	gboolean sync_folder;
3962 
3963 	priv = E_MAIL_READER_GET_PRIVATE (reader);
3964 
3965 	display = e_mail_reader_get_mail_display (reader);
3966 	message_list = e_mail_reader_get_message_list (reader);
3967 
3968 	previous_folder = e_mail_reader_ref_folder (reader);
3969 
3970 	backend = e_mail_reader_get_backend (reader);
3971 	shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
3972 
3973 	/* Only synchronize the real folder if we're online. */
3974 	sync_folder =
3975 		(previous_folder != NULL) &&
3976 		(CAMEL_IS_VEE_FOLDER (previous_folder) ||
3977 		e_shell_get_online (shell));
3978 	if (sync_folder)
3979 		mail_sync_folder (previous_folder, TRUE, NULL, NULL);
3980 
3981 	/* Skip the rest if we're already viewing the folder. */
3982 	if (folder != previous_folder) {
3983 		e_web_view_clear (E_WEB_VIEW (display));
3984 
3985 		priv->folder_was_just_selected = (folder != NULL) && !priv->mark_seen_always;
3986 		priv->did_try_to_open_message = FALSE;
3987 
3988 		/* This is to make sure any post-poned changes in Search
3989 		 * Folders will be propagated on folder selection. */
3990 		if (CAMEL_IS_VEE_FOLDER (folder))
3991 			mail_sync_folder (folder, FALSE, NULL, NULL);
3992 
3993 		message_list_set_folder (MESSAGE_LIST (message_list), folder);
3994 
3995 		mail_reader_emit_folder_loaded (reader);
3996 	}
3997 
3998 	g_clear_object (&previous_folder);
3999 }
4000 
4001 static void
mail_reader_set_message(EMailReader * reader,const gchar * message_uid)4002 mail_reader_set_message (EMailReader *reader,
4003                          const gchar *message_uid)
4004 {
4005 	GtkWidget *message_list;
4006 	EMailReaderPrivate *priv;
4007 
4008 	priv = E_MAIL_READER_GET_PRIVATE (reader);
4009 
4010 	/* For a case when the preview panel had been disabled */
4011 	priv->folder_was_just_selected = FALSE;
4012 
4013 	message_list = e_mail_reader_get_message_list (reader);
4014 
4015 	message_list_select_uid (
4016 		MESSAGE_LIST (message_list), message_uid, FALSE);
4017 }
4018 
4019 static void
mail_reader_folder_loaded(EMailReader * reader)4020 mail_reader_folder_loaded (EMailReader *reader)
4021 {
4022 	guint32 state;
4023 
4024 	state = e_mail_reader_check_state (reader);
4025 	e_mail_reader_update_actions (reader, state);
4026 }
4027 
4028 static void
mail_reader_message_list_suggest_update_actions_cb(EMailReader * reader)4029 mail_reader_message_list_suggest_update_actions_cb (EMailReader *reader)
4030 {
4031 	guint32 state;
4032 
4033 	state = e_mail_reader_check_state (reader);
4034 	e_mail_reader_update_actions (reader, state);
4035 }
4036 
4037 static void
set_mail_display_part_list(GObject * object,GAsyncResult * result,gpointer user_data)4038 set_mail_display_part_list (GObject *object,
4039                             GAsyncResult *result,
4040                             gpointer user_data)
4041 {
4042 	EMailPartList *part_list;
4043 	EMailReader *reader;
4044 	EMailDisplay *display;
4045 	GError *local_error = NULL;
4046 
4047 	reader = E_MAIL_READER (object);
4048 
4049 	part_list = e_mail_reader_parse_message_finish (reader, result, &local_error);
4050 
4051 	if (local_error) {
4052 		g_warn_if_fail (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED));
4053 
4054 		g_clear_error (&local_error);
4055 		return;
4056 	}
4057 
4058 	display = e_mail_reader_get_mail_display (reader);
4059 
4060 	e_mail_display_set_part_list (display, part_list);
4061 	e_mail_display_load (display, NULL);
4062 
4063 	/* Remove the reference added when parts list was
4064 	 * created, so that only owners are EMailDisplays. */
4065 	g_object_unref (part_list);
4066 }
4067 
4068 static void
mail_reader_set_display_formatter_for_message(EMailReader * reader,EMailDisplay * display,const gchar * message_uid,CamelMimeMessage * message,CamelFolder * folder)4069 mail_reader_set_display_formatter_for_message (EMailReader *reader,
4070                                                EMailDisplay *display,
4071                                                const gchar *message_uid,
4072                                                CamelMimeMessage *message,
4073                                                CamelFolder *folder)
4074 {
4075 	CamelObjectBag *registry;
4076 	EMailPartList *parts;
4077 	EMailReaderPrivate *priv;
4078 	gchar *mail_uri;
4079 
4080 	priv = E_MAIL_READER_GET_PRIVATE (reader);
4081 	mail_uri = e_mail_part_build_uri (folder, message_uid, NULL, NULL);
4082 	registry = e_mail_part_list_get_registry ();
4083 	parts = camel_object_bag_peek (registry, mail_uri);
4084 	g_free (mail_uri);
4085 
4086 	if (parts == NULL) {
4087 		if (!priv->retrieving_message)
4088 			priv->retrieving_message = camel_operation_new ();
4089 
4090 		e_mail_reader_parse_message (
4091 			reader, folder, message_uid, message,
4092 			priv->retrieving_message,
4093 			set_mail_display_part_list, NULL);
4094 	} else {
4095 		e_mail_display_set_part_list (display, parts);
4096 		e_mail_display_load (display, NULL);
4097 		g_object_unref (parts);
4098 	}
4099 }
4100 
4101 static void
mail_reader_message_loaded(EMailReader * reader,const gchar * message_uid,CamelMimeMessage * message)4102 mail_reader_message_loaded (EMailReader *reader,
4103                             const gchar *message_uid,
4104                             CamelMimeMessage *message)
4105 {
4106 	EMailReaderPrivate *priv;
4107 	GtkWidget *message_list;
4108 	EMailBackend *backend;
4109 	CamelFolder *folder;
4110 	EMailDisplay *display;
4111 	EShellBackend *shell_backend;
4112 	EShell *shell;
4113 	EMEvent *event;
4114 	EMEventTargetMessage *target;
4115 
4116 	priv = E_MAIL_READER_GET_PRIVATE (reader);
4117 
4118 	folder = e_mail_reader_ref_folder (reader);
4119 	backend = e_mail_reader_get_backend (reader);
4120 	display = e_mail_reader_get_mail_display (reader);
4121 	message_list = e_mail_reader_get_message_list (reader);
4122 
4123 	shell_backend = E_SHELL_BACKEND (backend);
4124 	shell = e_shell_backend_get_shell (shell_backend);
4125 
4126 	/** @Event: message.reading
4127 	 * @Title: Viewing a message
4128 	 * @Target: EMEventTargetMessage
4129 	 *
4130 	 * message.reading is emitted whenever a user views a message.
4131 	 */
4132 	event = em_event_peek ();
4133 	target = em_event_target_new_message (
4134 		event, folder, message, message_uid, 0, NULL);
4135 	e_event_emit (
4136 		(EEvent *) event, "message.reading",
4137 		(EEventTarget *) target);
4138 
4139 	mail_reader_set_display_formatter_for_message (
4140 		reader, display, message_uid, message, folder);
4141 
4142 	/* Reset the shell view icon. */
4143 	e_shell_event (shell, "mail-icon", (gpointer) "evolution-mail");
4144 
4145 	if (MESSAGE_LIST (message_list)->seen_id > 0) {
4146 		g_source_remove (MESSAGE_LIST (message_list)->seen_id);
4147 		MESSAGE_LIST (message_list)->seen_id = 0;
4148 	}
4149 
4150 	/* Determine whether to mark the message as read. */
4151 	if (message != NULL &&
4152 	    !priv->avoid_next_mark_as_seen)
4153 		maybe_schedule_timeout_mark_seen (reader);
4154 
4155 	priv->avoid_next_mark_as_seen = FALSE;
4156 
4157 	g_clear_object (&folder);
4158 }
4159 
4160 static void
mail_reader_message_seen(EMailReader * reader,const gchar * message_uid,CamelMimeMessage * message)4161 mail_reader_message_seen (EMailReader *reader,
4162                           const gchar *message_uid,
4163                           CamelMimeMessage *message)
4164 {
4165 	CamelFolder *folder;
4166 	guint32 mask, set;
4167 
4168 	mask = CAMEL_MESSAGE_SEEN;
4169 	set = CAMEL_MESSAGE_SEEN;
4170 
4171 	folder = e_mail_reader_ref_folder (reader);
4172 	camel_folder_set_message_flags (folder, message_uid, mask, set);
4173 	g_clear_object (&folder);
4174 }
4175 
4176 static void
mail_reader_show_search_bar(EMailReader * reader)4177 mail_reader_show_search_bar (EMailReader *reader)
4178 {
4179 	EPreviewPane *preview_pane;
4180 
4181 	preview_pane = e_mail_reader_get_preview_pane (reader);
4182 	e_preview_pane_show_search_bar (preview_pane);
4183 }
4184 
4185 static void
action_mail_label_cb(GtkToggleAction * action,EMailReader * reader)4186 action_mail_label_cb (GtkToggleAction *action,
4187                       EMailReader *reader)
4188 {
4189 	CamelFolder *folder;
4190 	GPtrArray *uids;
4191 	const gchar *tag;
4192 	gint ii;
4193 
4194 	tag = g_object_get_data (G_OBJECT (action), "tag");
4195 	g_return_if_fail (tag != NULL);
4196 
4197 	uids = e_mail_reader_get_selected_uids (reader);
4198 	if (!uids)
4199 		return;
4200 
4201 	folder = e_mail_reader_ref_folder (reader);
4202 
4203 	camel_folder_freeze (folder);
4204 	for (ii = 0; ii < uids->len; ii++) {
4205 		if (gtk_toggle_action_get_active (action))
4206 			camel_folder_set_message_user_flag (
4207 				folder, uids->pdata[ii], tag, TRUE);
4208 		else {
4209 			camel_folder_set_message_user_flag (
4210 				folder, uids->pdata[ii], tag, FALSE);
4211 			camel_folder_set_message_user_tag (
4212 				folder, uids->pdata[ii], "label", NULL);
4213 		}
4214 	}
4215 	camel_folder_thaw (folder);
4216 
4217 	g_clear_object (&folder);
4218 	g_ptr_array_unref (uids);
4219 }
4220 
4221 #define LABEL_UNKNOWN	0
4222 #define LABEL_EXISTS	(1 << 0)
4223 #define LABEL_NOTEXIST	(1 << 1)
4224 
4225 static GHashTable *
mail_reader_gather_labels_info(EMailReader * reader,EMailLabelListStore * label_store,GPtrArray * uids)4226 mail_reader_gather_labels_info (EMailReader *reader,
4227 				EMailLabelListStore *label_store,
4228 				GPtrArray *uids)
4229 {
4230 	GHashTable *labels_info;
4231 	CamelFolder *folder;
4232 	GtkTreeIter iter;
4233 	GtkTreeModel *model;
4234 	gboolean valid;
4235 	guint ii;
4236 
4237 	labels_info = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
4238 
4239 	model = GTK_TREE_MODEL (label_store);
4240 	folder = e_mail_reader_ref_folder (reader);
4241 
4242 	if (!folder)
4243 		return labels_info;
4244 
4245 	for (ii = 0; ii < uids->len; ii++) {
4246 		CamelMessageInfo *info;
4247 
4248 		info = camel_folder_get_message_info (folder, uids->pdata[ii]);
4249 		if (!info)
4250 			continue;
4251 
4252 		for (valid = gtk_tree_model_get_iter_first (model, &iter);
4253 		     valid;
4254 		     valid = gtk_tree_model_iter_next (model, &iter)) {
4255 			gchar *tag;
4256 			guint value;
4257 
4258 			tag = e_mail_label_list_store_get_tag (label_store, &iter);
4259 			value = GPOINTER_TO_UINT (g_hash_table_lookup (labels_info, tag));
4260 			if ((!(value & LABEL_EXISTS)) || (!(value & LABEL_NOTEXIST))) {
4261 				gboolean exists = FALSE, notexist = FALSE;
4262 
4263 				/* Check for new-style labels. */
4264 				if (camel_message_info_get_user_flag (info, tag)) {
4265 					exists = TRUE;
4266 				} else {
4267 					/* Check for old-style labels. */
4268 					const gchar *old_label = camel_message_info_get_user_tag (info, "label");
4269 					if (old_label) {
4270 						gchar *new_label;
4271 
4272 						/* Convert old-style labels ("<name>") to "$Label<name>". */
4273 						new_label = g_alloca (strlen (old_label) + 10);
4274 						g_stpcpy (g_stpcpy (new_label, "$Label"), old_label);
4275 
4276 						if (g_strcmp0 (new_label, tag) == 0)
4277 							exists = TRUE;
4278 						else
4279 							notexist = TRUE;
4280 					} else {
4281 						notexist = TRUE;
4282 					}
4283 				}
4284 
4285 				value = value |
4286 					(exists ? LABEL_EXISTS : LABEL_UNKNOWN) |
4287 					(notexist ? LABEL_NOTEXIST : LABEL_UNKNOWN);
4288 
4289 				g_hash_table_insert (labels_info, tag, GUINT_TO_POINTER (value));
4290 
4291 				/* the hash table took the 'tag' */
4292 				tag = NULL;
4293 			}
4294 
4295 			g_free (tag);
4296 		}
4297 
4298 		g_clear_object (&info);
4299 	}
4300 
4301 	g_clear_object (&folder);
4302 
4303 	return labels_info;
4304 }
4305 
4306 static void
mail_reader_update_label_action(GtkToggleAction * action,GHashTable * labels_info,const gchar * label_tag)4307 mail_reader_update_label_action (GtkToggleAction *action,
4308 				 GHashTable *labels_info, /* gchar * ~> guint */
4309 				 const gchar *label_tag)
4310 {
4311 	gboolean exists = FALSE;
4312 	gboolean not_exists = FALSE;
4313 	gboolean sensitive;
4314 	guint value;
4315 
4316 	/* Figure out the proper label action state for the selected
4317 	 * messages.  If all the selected messages have the given label,
4318 	 * make the toggle action active.  If all the selected message
4319 	 * DO NOT have the given label, make the toggle action inactive.
4320 	 * If some do and some don't, make the action insensitive. */
4321 
4322 	value = GPOINTER_TO_UINT (g_hash_table_lookup (labels_info, label_tag));
4323 	exists = (value & LABEL_EXISTS) != 0;
4324 	not_exists = (value & LABEL_NOTEXIST) != 0;
4325 
4326 	sensitive = !(exists && not_exists);
4327 	gtk_toggle_action_set_active (action, exists);
4328 	gtk_action_set_sensitive (GTK_ACTION (action), sensitive);
4329 }
4330 
4331 static void
mail_reader_update_labels_menu(EMailReader * reader)4332 mail_reader_update_labels_menu (EMailReader *reader)
4333 {
4334 	EMailReaderPrivate *priv;
4335 	EMailLabelListStore *label_store;
4336 	EMailBackend *backend;
4337 	EMailSession *session;
4338 	GtkWindow *window;
4339 	GtkUIManager *ui_manager = NULL;
4340 	GtkActionGroup *action_group;
4341 	GtkTreeIter iter;
4342 	GHashTable *labels_info; /* gchar * ~> guint { LABEL_EXISTS | LABEL_NOTEXIST | LABEL_UNKNOWN } */
4343 	GPtrArray *uids;
4344 	const gchar *main_menu_path, *popup_menu_path;
4345 	gboolean valid;
4346 	gint ii = 0;
4347 
4348 	priv = E_MAIL_READER_GET_PRIVATE (reader);
4349 
4350 	window = e_mail_reader_get_window (reader);
4351 	g_return_if_fail (window != NULL);
4352 
4353 	if (E_IS_SHELL_WINDOW (window))
4354 		ui_manager = e_shell_window_get_ui_manager (E_SHELL_WINDOW (window));
4355 	else if (E_IS_MAIL_BROWSER (window))
4356 		ui_manager = e_mail_browser_get_ui_manager (E_MAIL_BROWSER (window));
4357 
4358 	g_return_if_fail (ui_manager != NULL);
4359 	g_return_if_fail (GTK_IS_UI_MANAGER (ui_manager));
4360 
4361 	backend = e_mail_reader_get_backend (reader);
4362 	session = e_mail_backend_get_session (backend);
4363 	label_store = e_mail_ui_session_get_label_store (E_MAIL_UI_SESSION (session));
4364 
4365 	action_group = e_mail_reader_get_action_group (reader, E_MAIL_READER_ACTION_GROUP_LABELS);
4366 	main_menu_path = "/main-menu/custom-menus/mail-message-menu/mail-mark-as-menu/mail-label-menu/mail-label-actions";
4367 	popup_menu_path = "/mail-message-popup/mail-label-menu/mail-label-actions";
4368 
4369 	/* Unmerge the previous menu items. */
4370 	if (priv->main_menu_label_merge_id)
4371 		gtk_ui_manager_remove_ui (ui_manager, priv->main_menu_label_merge_id);
4372 	else
4373 		priv->main_menu_label_merge_id = gtk_ui_manager_new_merge_id (ui_manager);
4374 
4375 	if (priv->popup_menu_label_merge_id)
4376 		gtk_ui_manager_remove_ui (ui_manager, priv->popup_menu_label_merge_id);
4377 	else
4378 		priv->popup_menu_label_merge_id = gtk_ui_manager_new_merge_id (ui_manager);
4379 
4380 	e_action_group_remove_all_actions (action_group);
4381 	gtk_ui_manager_ensure_update (ui_manager);
4382 
4383 	uids = e_mail_reader_get_selected_uids (reader);
4384 	labels_info = mail_reader_gather_labels_info (reader, label_store, uids);
4385 
4386 	valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (label_store), &iter);
4387 
4388 	while (valid) {
4389 		EMailLabelAction *label_action;
4390 		GtkAction *action;
4391 		gchar *action_name;
4392 		gchar *stock_id;
4393 		gchar *label;
4394 		gchar *tag;
4395 
4396 		label = e_mail_label_list_store_get_name (label_store, &iter);
4397 		stock_id = e_mail_label_list_store_get_stock_id (label_store, &iter);
4398 		tag = e_mail_label_list_store_get_tag (label_store, &iter);
4399 		action_name = g_strdup_printf ("mail-label-%d", ii);
4400 
4401 		/* XXX Add a tooltip! */
4402 		label_action = e_mail_label_action_new (action_name, label, NULL, stock_id);
4403 
4404 		g_object_set_data_full (
4405 			G_OBJECT (label_action), "tag",
4406 			tag, (GDestroyNotify) g_free);
4407 
4408 		/* Configure the action before we connect to signals. */
4409 		mail_reader_update_label_action (GTK_TOGGLE_ACTION (label_action), labels_info, tag);
4410 
4411 		g_signal_connect (
4412 			label_action, "toggled",
4413 			G_CALLBACK (action_mail_label_cb), reader);
4414 
4415 		/* The action group takes ownership of the action. */
4416 		action = GTK_ACTION (label_action);
4417 
4418 		if (ii + 1 < 10) {
4419 			gchar accel[5];
4420 
4421 			accel[0] = '1' + ii;
4422 			accel[1] = '\0';
4423 
4424 			gtk_action_group_add_action_with_accel (action_group, action, accel);
4425 		} else {
4426 			gtk_action_group_add_action (action_group, action);
4427 		}
4428 		g_object_unref (label_action);
4429 
4430 		gtk_ui_manager_add_ui (
4431 			ui_manager, priv->main_menu_label_merge_id, main_menu_path,
4432 			action_name, action_name, GTK_UI_MANAGER_AUTO, FALSE);
4433 
4434 		gtk_ui_manager_add_ui (
4435 			ui_manager, priv->popup_menu_label_merge_id, popup_menu_path,
4436 			action_name, action_name, GTK_UI_MANAGER_AUTO, FALSE);
4437 
4438 		g_free (label);
4439 		g_free (stock_id);
4440 		g_free (action_name);
4441 
4442 		valid = gtk_tree_model_iter_next (
4443 			GTK_TREE_MODEL (label_store), &iter);
4444 		ii++;
4445 	}
4446 
4447 	g_hash_table_destroy (labels_info);
4448 	g_ptr_array_unref (uids);
4449 }
4450 
4451 static void
mail_reader_update_actions(EMailReader * reader,guint32 state)4452 mail_reader_update_actions (EMailReader *reader,
4453                             guint32 state)
4454 {
4455 	GtkAction *action;
4456 	const gchar *action_name;
4457 	gboolean sensitive;
4458 	EMailDisplay *mail_display;
4459 
4460 	/* Be descriptive. */
4461 	gboolean any_messages_selected;
4462 	gboolean enable_flag_clear;
4463 	gboolean enable_flag_completed;
4464 	gboolean have_enabled_account;
4465 	gboolean multiple_messages_selected;
4466 	gboolean selection_has_attachment_messages;
4467 	gboolean selection_has_deleted_messages;
4468 	gboolean selection_has_ignore_thread_messages;
4469 	gboolean selection_has_notignore_thread_messages;
4470 	gboolean selection_has_important_messages;
4471 	gboolean selection_has_junk_messages;
4472 	gboolean selection_has_not_junk_messages;
4473 	gboolean selection_has_read_messages;
4474 	gboolean selection_has_undeleted_messages;
4475 	gboolean selection_has_unimportant_messages;
4476 	gboolean selection_has_unread_messages;
4477 	gboolean selection_has_mail_note;
4478 	gboolean selection_has_color;
4479 	gboolean selection_is_mailing_list;
4480 	gboolean single_message_selected;
4481 	gboolean first_message_selected = FALSE;
4482 	gboolean last_message_selected = FALSE;
4483 
4484 	have_enabled_account =
4485 		(state & E_MAIL_READER_HAVE_ENABLED_ACCOUNT);
4486 	single_message_selected =
4487 		(state & E_MAIL_READER_SELECTION_SINGLE);
4488 	multiple_messages_selected =
4489 		(state & E_MAIL_READER_SELECTION_MULTIPLE);
4490 	/* FIXME Missing CAN_ADD_SENDER */
4491 	enable_flag_clear =
4492 		(state & E_MAIL_READER_SELECTION_FLAG_CLEAR);
4493 	enable_flag_completed =
4494 		(state & E_MAIL_READER_SELECTION_FLAG_COMPLETED);
4495 	selection_has_attachment_messages =
4496 		(state & E_MAIL_READER_SELECTION_HAS_ATTACHMENTS);
4497 	selection_has_deleted_messages =
4498 		(state & E_MAIL_READER_SELECTION_HAS_DELETED);
4499 	selection_has_ignore_thread_messages =
4500 		(state & E_MAIL_READER_SELECTION_HAS_IGNORE_THREAD);
4501 	selection_has_notignore_thread_messages =
4502 		(state & E_MAIL_READER_SELECTION_HAS_NOTIGNORE_THREAD);
4503 	selection_has_important_messages =
4504 		(state & E_MAIL_READER_SELECTION_HAS_IMPORTANT);
4505 	selection_has_junk_messages =
4506 		(state & E_MAIL_READER_SELECTION_HAS_JUNK);
4507 	selection_has_not_junk_messages =
4508 		(state & E_MAIL_READER_SELECTION_HAS_NOT_JUNK);
4509 	selection_has_read_messages =
4510 		(state & E_MAIL_READER_SELECTION_HAS_READ);
4511 	selection_has_undeleted_messages =
4512 		(state & E_MAIL_READER_SELECTION_HAS_UNDELETED);
4513 	selection_has_unimportant_messages =
4514 		(state & E_MAIL_READER_SELECTION_HAS_UNIMPORTANT);
4515 	selection_has_unread_messages =
4516 		(state & E_MAIL_READER_SELECTION_HAS_UNREAD);
4517 	selection_has_mail_note =
4518 		(state & E_MAIL_READER_SELECTION_HAS_MAIL_NOTE);
4519 	selection_has_color =
4520 		(state & E_MAIL_READER_SELECTION_HAS_COLOR);
4521 	selection_is_mailing_list =
4522 		(state & E_MAIL_READER_SELECTION_IS_MAILING_LIST);
4523 
4524 	any_messages_selected =
4525 		(single_message_selected || multiple_messages_selected);
4526 
4527 	mail_display = e_mail_reader_get_mail_display (reader);
4528 
4529 	if (any_messages_selected) {
4530 		MessageList *message_list;
4531 		gint row = -1, count = -1;
4532 		ETreeTableAdapter *etta;
4533 		ETreePath node = NULL;
4534 
4535 		message_list = MESSAGE_LIST (
4536 			e_mail_reader_get_message_list (reader));
4537 		etta = e_tree_get_table_adapter (E_TREE (message_list));
4538 
4539 		if (message_list->cursor_uid != NULL)
4540 			node = g_hash_table_lookup (
4541 				message_list->uid_nodemap,
4542 				message_list->cursor_uid);
4543 
4544 		if (node != NULL) {
4545 			row = e_tree_table_adapter_row_of_node (etta, node);
4546 			count = e_table_model_row_count (E_TABLE_MODEL (etta));
4547 		}
4548 
4549 		first_message_selected = row <= 0;
4550 		last_message_selected = row < 0 || row + 1 >= count;
4551 	}
4552 
4553 	action_name = "mail-add-sender";
4554 	sensitive = single_message_selected;
4555 	action = e_mail_reader_get_action (reader, action_name);
4556 	gtk_action_set_sensitive (action, sensitive);
4557 
4558 	action_name = "mail-archive";
4559 	sensitive = any_messages_selected && (state & E_MAIL_READER_FOLDER_ARCHIVE_FOLDER_SET) != 0;
4560 	action = e_mail_reader_get_action (reader, action_name);
4561 	gtk_action_set_sensitive (action, sensitive);
4562 
4563 	action_name = "mail-check-for-junk";
4564 	sensitive = any_messages_selected;
4565 	action = e_mail_reader_get_action (reader, action_name);
4566 	gtk_action_set_sensitive (action, sensitive);
4567 
4568 	action_name = "mail-color-assign";
4569 	sensitive = any_messages_selected;
4570 	action = e_mail_reader_get_action (reader, action_name);
4571 	gtk_action_set_sensitive (action, sensitive);
4572 
4573 	action_name = "mail-color-unset";
4574 	sensitive = any_messages_selected && selection_has_color;
4575 	action = e_mail_reader_get_action (reader, action_name);
4576 	gtk_action_set_sensitive (action, sensitive);
4577 
4578 	action_name = "mail-copy";
4579 	sensitive = any_messages_selected;
4580 	action = e_mail_reader_get_action (reader, action_name);
4581 	gtk_action_set_sensitive (action, sensitive);
4582 
4583 	action_name = "mail-create-menu";
4584 	sensitive = single_message_selected;
4585 	action = e_mail_reader_get_action (reader, action_name);
4586 	gtk_action_set_sensitive (action, sensitive);
4587 
4588 	/* If a single message is selected, let the user hit delete to
4589 	 * advance the cursor even if the message is already deleted. */
4590 	action_name = "mail-delete";
4591 	sensitive =
4592 		(single_message_selected ||
4593 		selection_has_undeleted_messages) &&
4594 		(state & E_MAIL_READER_FOLDER_IS_VTRASH) == 0;
4595 	action = e_mail_reader_get_action (reader, action_name);
4596 	gtk_action_set_sensitive (action, sensitive);
4597 
4598 	action_name = "mail-add-note";
4599 	sensitive = single_message_selected && !selection_has_mail_note;
4600 	action = e_mail_reader_get_action (reader, action_name);
4601 	gtk_action_set_sensitive (action, sensitive);
4602 	gtk_action_set_visible (action, sensitive);
4603 
4604 	action_name = "mail-edit-note";
4605 	sensitive = single_message_selected && selection_has_mail_note;
4606 	action = e_mail_reader_get_action (reader, action_name);
4607 	gtk_action_set_sensitive (action, sensitive);
4608 	gtk_action_set_visible (action, sensitive);
4609 
4610 	action_name = "mail-delete-note";
4611 	sensitive = single_message_selected && selection_has_mail_note;
4612 	action = e_mail_reader_get_action (reader, action_name);
4613 	gtk_action_set_sensitive (action, sensitive);
4614 	gtk_action_set_visible (action, sensitive);
4615 
4616 	action_name = "mail-filters-apply";
4617 	sensitive = any_messages_selected;
4618 	action = e_mail_reader_get_action (reader, action_name);
4619 	gtk_action_set_sensitive (action, sensitive);
4620 
4621 	action_name = "mail-filter-rule-for-mailing-list";
4622 	sensitive = single_message_selected && selection_is_mailing_list;
4623 	action = e_mail_reader_get_action (reader, action_name);
4624 	gtk_action_set_sensitive (action, sensitive);
4625 
4626 	action_name = "mail-find";
4627 	sensitive = single_message_selected;
4628 	action = e_mail_reader_get_action (reader, action_name);
4629 	gtk_action_set_sensitive (action, sensitive);
4630 
4631 	action_name = "mail-flag-clear";
4632 	sensitive = enable_flag_clear;
4633 	action = e_mail_reader_get_action (reader, action_name);
4634 	gtk_action_set_sensitive (action, sensitive);
4635 
4636 	action_name = "mail-flag-completed";
4637 	sensitive = enable_flag_completed;
4638 	action = e_mail_reader_get_action (reader, action_name);
4639 	gtk_action_set_sensitive (action, sensitive);
4640 
4641 	action_name = "mail-flag-for-followup";
4642 	sensitive = any_messages_selected;
4643 	action = e_mail_reader_get_action (reader, action_name);
4644 	gtk_action_set_sensitive (action, sensitive);
4645 
4646 	action_name = "mail-forward";
4647 	sensitive = have_enabled_account && any_messages_selected;
4648 	action = e_mail_reader_get_action (reader, action_name);
4649 	gtk_action_set_sensitive (action, sensitive);
4650 
4651 	action_name = "mail-forward-attached";
4652 	sensitive = have_enabled_account && any_messages_selected;
4653 	action = e_mail_reader_get_action (reader, action_name);
4654 	gtk_action_set_sensitive (action, sensitive);
4655 
4656 	action_name = "mail-forward-attached-full";
4657 	sensitive = have_enabled_account && any_messages_selected;
4658 	action = e_mail_reader_get_action (reader, action_name);
4659 	gtk_action_set_sensitive (action, sensitive);
4660 
4661 	action_name = "mail-forward-as-menu";
4662 	sensitive = have_enabled_account && any_messages_selected;
4663 	action = e_mail_reader_get_action (reader, action_name);
4664 	gtk_action_set_sensitive (action, sensitive);
4665 
4666 	action_name = "mail-forward-inline";
4667 	sensitive = have_enabled_account && single_message_selected;
4668 	action = e_mail_reader_get_action (reader, action_name);
4669 	gtk_action_set_sensitive (action, sensitive);
4670 
4671 	action_name = "mail-forward-inline-full";
4672 	sensitive = have_enabled_account && single_message_selected;
4673 	action = e_mail_reader_get_action (reader, action_name);
4674 	gtk_action_set_sensitive (action, sensitive);
4675 
4676 	action_name = "mail-forward-quoted";
4677 	sensitive = have_enabled_account && single_message_selected;
4678 	action = e_mail_reader_get_action (reader, action_name);
4679 	gtk_action_set_sensitive (action, sensitive);
4680 
4681 	action_name = "mail-forward-quoted-full";
4682 	sensitive = have_enabled_account && single_message_selected;
4683 	action = e_mail_reader_get_action (reader, action_name);
4684 	gtk_action_set_sensitive (action, sensitive);
4685 
4686 	action_name = "mail-goto-menu";
4687 	sensitive = any_messages_selected;
4688 	action = e_mail_reader_get_action (reader, action_name);
4689 	gtk_action_set_sensitive (action, sensitive);
4690 
4691 	action_name = "mail-load-images";
4692 	sensitive = single_message_selected;
4693 	action = e_mail_reader_get_action (reader, action_name);
4694 	gtk_action_set_sensitive (action, sensitive);
4695 
4696 	action_name = "mail-mark-as-menu";
4697 	sensitive = any_messages_selected;
4698 	action = e_mail_reader_get_action (reader, action_name);
4699 	gtk_action_set_sensitive (action, sensitive);
4700 
4701 	action_name = "mail-mark-ignore-thread-sub";
4702 	sensitive = selection_has_notignore_thread_messages;
4703 	action = e_mail_reader_get_action (reader, action_name);
4704 	gtk_action_set_sensitive (action, sensitive);
4705 	gtk_action_set_visible (action, sensitive);
4706 
4707 	action_name = "mail-mark-ignore-thread-whole";
4708 	sensitive = selection_has_notignore_thread_messages;
4709 	action = e_mail_reader_get_action (reader, action_name);
4710 	gtk_action_set_sensitive (action, sensitive);
4711 	gtk_action_set_visible (action, sensitive);
4712 
4713 	action_name = "mail-mark-important";
4714 	sensitive = selection_has_unimportant_messages;
4715 	action = e_mail_reader_get_action (reader, action_name);
4716 	gtk_action_set_sensitive (action, sensitive);
4717 
4718 	action_name = "mail-mark-junk";
4719 	sensitive = selection_has_not_junk_messages;
4720 	action = e_mail_reader_get_action (reader, action_name);
4721 	gtk_action_set_sensitive (action, sensitive);
4722 
4723 	action_name = "mail-mark-notjunk";
4724 	sensitive = selection_has_junk_messages;
4725 	action = e_mail_reader_get_action (reader, action_name);
4726 	gtk_action_set_sensitive (action, sensitive);
4727 
4728 	action_name = "mail-mark-read";
4729 	sensitive = selection_has_unread_messages;
4730 	action = e_mail_reader_get_action (reader, action_name);
4731 	gtk_action_set_sensitive (action, sensitive);
4732 
4733 	action_name = "mail-mark-unignore-thread-sub";
4734 	sensitive = selection_has_ignore_thread_messages;
4735 	action = e_mail_reader_get_action (reader, action_name);
4736 	gtk_action_set_sensitive (action, sensitive);
4737 	gtk_action_set_visible (action, sensitive);
4738 
4739 	action_name = "mail-mark-unignore-thread-whole";
4740 	sensitive = selection_has_ignore_thread_messages;
4741 	action = e_mail_reader_get_action (reader, action_name);
4742 	gtk_action_set_sensitive (action, sensitive);
4743 	gtk_action_set_visible (action, sensitive);
4744 
4745 	action_name = "mail-mark-unimportant";
4746 	sensitive = selection_has_important_messages;
4747 	action = e_mail_reader_get_action (reader, action_name);
4748 	gtk_action_set_sensitive (action, sensitive);
4749 
4750 	action_name = "mail-mark-unread";
4751 	sensitive = selection_has_read_messages;
4752 	action = e_mail_reader_get_action (reader, action_name);
4753 	gtk_action_set_sensitive (action, sensitive);
4754 
4755 	action_name = "mail-message-edit";
4756 	sensitive = have_enabled_account && single_message_selected;
4757 	action = e_mail_reader_get_action (reader, action_name);
4758 	gtk_action_set_sensitive (action, sensitive);
4759 
4760 	action_name = "mail-message-new";
4761 	sensitive = have_enabled_account;
4762 	action = e_mail_reader_get_action (reader, action_name);
4763 	gtk_action_set_sensitive (action, sensitive);
4764 
4765 	action_name = "mail-message-open";
4766 	sensitive = any_messages_selected;
4767 	action = e_mail_reader_get_action (reader, action_name);
4768 	gtk_action_set_sensitive (action, sensitive);
4769 
4770 	action_name = "mail-move";
4771 	sensitive = any_messages_selected;
4772 	action = e_mail_reader_get_action (reader, action_name);
4773 	gtk_action_set_sensitive (action, sensitive);
4774 
4775 	action_name = "mail-next";
4776 	sensitive = any_messages_selected && !last_message_selected;
4777 	action = e_mail_reader_get_action (reader, action_name);
4778 	gtk_action_set_sensitive (action, sensitive);
4779 
4780 	action_name = "mail-next-important";
4781 	sensitive = single_message_selected;
4782 	action = e_mail_reader_get_action (reader, action_name);
4783 	gtk_action_set_sensitive (action, sensitive);
4784 
4785 	action_name = "mail-next-thread";
4786 	sensitive = single_message_selected && !last_message_selected;
4787 	action = e_mail_reader_get_action (reader, action_name);
4788 	gtk_action_set_sensitive (action, sensitive);
4789 
4790 	action_name = "mail-next-unread";
4791 	sensitive = any_messages_selected;
4792 	action = e_mail_reader_get_action (reader, action_name);
4793 	gtk_action_set_sensitive (action, sensitive);
4794 
4795 	action_name = "mail-previous";
4796 	sensitive = any_messages_selected && !first_message_selected;
4797 	action = e_mail_reader_get_action (reader, action_name);
4798 	gtk_action_set_sensitive (action, sensitive);
4799 
4800 	action_name = "mail-previous-important";
4801 	sensitive = single_message_selected;
4802 	action = e_mail_reader_get_action (reader, action_name);
4803 	gtk_action_set_sensitive (action, sensitive);
4804 
4805 	action_name = "mail-previous-unread";
4806 	sensitive = any_messages_selected;
4807 	action = e_mail_reader_get_action (reader, action_name);
4808 	gtk_action_set_sensitive (action, sensitive);
4809 
4810 	action_name = "mail-previous-thread";
4811 	sensitive = any_messages_selected && !first_message_selected;
4812 	action = e_mail_reader_get_action (reader, action_name);
4813 	gtk_action_set_sensitive (action, sensitive);
4814 
4815 	action_name = "mail-print";
4816 	sensitive = single_message_selected;
4817 	action = e_mail_reader_get_action (reader, action_name);
4818 	gtk_action_set_sensitive (action, sensitive);
4819 
4820 	action_name = "mail-print-preview";
4821 	sensitive = single_message_selected;
4822 	action = e_mail_reader_get_action (reader, action_name);
4823 	gtk_action_set_sensitive (action, sensitive);
4824 
4825 	action_name = "mail-redirect";
4826 	sensitive = have_enabled_account && single_message_selected;
4827 	action = e_mail_reader_get_action (reader, action_name);
4828 	gtk_action_set_sensitive (action, sensitive);
4829 
4830 	action_name = "mail-remove-attachments";
4831 	sensitive = any_messages_selected && selection_has_attachment_messages;
4832 	action = e_mail_reader_get_action (reader, action_name);
4833 	gtk_action_set_sensitive (action, sensitive);
4834 
4835 	action_name = "mail-remove-duplicates";
4836 	sensitive = multiple_messages_selected;
4837 	action = e_mail_reader_get_action (reader, action_name);
4838 	gtk_action_set_sensitive (action, sensitive);
4839 
4840 	action_name = "mail-reply-all";
4841 	sensitive = have_enabled_account && single_message_selected;
4842 	action = e_mail_reader_get_action (reader, action_name);
4843 	gtk_action_set_sensitive (action, sensitive);
4844 
4845 	action_name = "mail-reply-alternative";
4846 	sensitive = have_enabled_account && single_message_selected;
4847 	action = e_mail_reader_get_action (reader, action_name);
4848 	gtk_action_set_sensitive (action, sensitive);
4849 
4850 	action_name = "mail-reply-group";
4851 	sensitive = have_enabled_account && single_message_selected;
4852 	action = e_mail_reader_get_action (reader, action_name);
4853 	gtk_action_set_sensitive (action, sensitive);
4854 
4855 	action_name = "mail-reply-group-menu";
4856 	sensitive = have_enabled_account && any_messages_selected;
4857 	action = e_mail_reader_get_action (reader, action_name);
4858 	gtk_action_set_sensitive (action, sensitive);
4859 
4860 	action_name = "mail-reply-list";
4861 	sensitive = have_enabled_account && single_message_selected &&
4862 		selection_is_mailing_list;
4863 	action = e_mail_reader_get_action (reader, action_name);
4864 	gtk_action_set_sensitive (action, sensitive);
4865 
4866 	action_name = "mail-reply-sender";
4867 	sensitive = have_enabled_account && single_message_selected;
4868 	action = e_mail_reader_get_action (reader, action_name);
4869 	gtk_action_set_sensitive (action, sensitive);
4870 
4871 	action_name = "mail-save-as";
4872 	sensitive = any_messages_selected;
4873 	action = e_mail_reader_get_action (reader, action_name);
4874 	gtk_action_set_sensitive (action, sensitive);
4875 
4876 	action_name = "mail-show-source";
4877 	sensitive = single_message_selected;
4878 	action = e_mail_reader_get_action (reader, action_name);
4879 	gtk_action_set_sensitive (action, sensitive);
4880 
4881 	action_name = "mail-undelete";
4882 	sensitive = selection_has_deleted_messages;
4883 	action = e_mail_reader_get_action (reader, action_name);
4884 	gtk_action_set_sensitive (action, sensitive);
4885 
4886 	action_name = "mail-zoom-100";
4887 	sensitive = single_message_selected;
4888 	action = e_mail_reader_get_action (reader, action_name);
4889 	gtk_action_set_sensitive (action, sensitive);
4890 
4891 	action_name = "mail-zoom-in";
4892 	sensitive = single_message_selected;
4893 	action = e_mail_reader_get_action (reader, action_name);
4894 	gtk_action_set_sensitive (action, sensitive);
4895 
4896 	action_name = "mail-zoom-out";
4897 	sensitive = single_message_selected;
4898 	action = e_mail_reader_get_action (reader, action_name);
4899 	gtk_action_set_sensitive (action, sensitive);
4900 
4901 	action = e_mail_reader_get_action (reader, "mail-search-web");
4902 	gtk_action_set_sensitive (action, single_message_selected &&
4903 		mail_display && e_web_view_has_selection (E_WEB_VIEW (mail_display)));
4904 
4905 	mail_reader_update_labels_menu (reader);
4906 }
4907 
4908 static gboolean
mail_reader_close_on_delete_or_junk(EMailReader * reader)4909 mail_reader_close_on_delete_or_junk (EMailReader *reader)
4910 {
4911 	return FALSE;
4912 }
4913 
4914 static void
mail_reader_init_charset_actions(EMailReader * reader,GtkActionGroup * action_group)4915 mail_reader_init_charset_actions (EMailReader *reader,
4916                                   GtkActionGroup *action_group)
4917 {
4918 	GtkRadioAction *default_action;
4919 	GSList *radio_group;
4920 
4921 	radio_group = e_charset_add_radio_actions (
4922 		action_group, "mail-charset-", NULL,
4923 		G_CALLBACK (action_mail_charset_cb), reader);
4924 
4925 	/* XXX Add a tooltip! */
4926 	default_action = gtk_radio_action_new (
4927 		"mail-charset-default", _("Default"), NULL, NULL, -1);
4928 
4929 	gtk_radio_action_set_group (default_action, radio_group);
4930 
4931 	g_signal_connect (
4932 		default_action, "changed",
4933 		G_CALLBACK (action_mail_charset_cb), reader);
4934 
4935 	gtk_action_group_add_action (
4936 		action_group, GTK_ACTION (default_action));
4937 
4938 	gtk_radio_action_set_current_value (default_action, -1);
4939 }
4940 
4941 static void
e_mail_reader_default_init(EMailReaderInterface * iface)4942 e_mail_reader_default_init (EMailReaderInterface *iface)
4943 {
4944 	quark_private = g_quark_from_static_string ("e-mail-reader-private");
4945 
4946 	iface->get_alert_sink = mail_reader_get_alert_sink;
4947 	iface->get_selected_uids = mail_reader_get_selected_uids;
4948 	iface->get_selected_uids_with_collapsed_threads = mail_reader_get_selected_uids_with_collapsed_threads;
4949 	iface->ref_folder = mail_reader_ref_folder;
4950 	iface->set_folder = mail_reader_set_folder;
4951 	iface->set_message = mail_reader_set_message;
4952 	iface->open_selected_mail = e_mail_reader_open_selected;
4953 	iface->folder_loaded = mail_reader_folder_loaded;
4954 	iface->message_loaded = mail_reader_message_loaded;
4955 	iface->message_seen = mail_reader_message_seen;
4956 	iface->show_search_bar = mail_reader_show_search_bar;
4957 	iface->update_actions = mail_reader_update_actions;
4958 	iface->close_on_delete_or_junk = mail_reader_close_on_delete_or_junk;
4959 	iface->reload = mail_reader_reload;
4960 	iface->remove_ui = mail_reader_remove_ui;
4961 
4962 	g_object_interface_install_property (
4963 		iface,
4964 		g_param_spec_enum (
4965 			"forward-style",
4966 			"Forward Style",
4967 			"How to forward messages",
4968 			E_TYPE_MAIL_FORWARD_STYLE,
4969 			E_MAIL_FORWARD_STYLE_ATTACHED,
4970 			G_PARAM_READWRITE));
4971 
4972 	g_object_interface_install_property (
4973 		iface,
4974 		g_param_spec_boolean (
4975 			"group-by-threads",
4976 			"Group by Threads",
4977 			"Whether to group messages by threads",
4978 			FALSE,
4979 			G_PARAM_READWRITE));
4980 
4981 	g_object_interface_install_property (
4982 		iface,
4983 		g_param_spec_enum (
4984 			"reply-style",
4985 			"Reply Style",
4986 			"How to reply to messages",
4987 			E_TYPE_MAIL_REPLY_STYLE,
4988 			E_MAIL_REPLY_STYLE_QUOTED,
4989 			G_PARAM_READWRITE));
4990 
4991 	g_object_interface_install_property (
4992 		iface,
4993 		g_param_spec_boolean (
4994 			"mark-seen-always",
4995 			"Mark Seen Always",
4996 			"Whether to mark unread message seen even after folder change",
4997 			FALSE,
4998 			G_PARAM_READWRITE));
4999 
5000 	g_object_interface_install_property (
5001 		iface,
5002 		g_param_spec_boolean (
5003 			"delete-selects-previous",
5004 			"Delete Selects Previous",
5005 			"Whether go to the previous message after message deletion",
5006 			FALSE,
5007 			G_PARAM_READWRITE));
5008 
5009 	signals[CHANGED] = g_signal_new (
5010 		"changed",
5011 		G_OBJECT_CLASS_TYPE (iface),
5012 		G_SIGNAL_RUN_FIRST,
5013 		0, NULL, NULL,
5014 		g_cclosure_marshal_VOID__VOID,
5015 		G_TYPE_NONE, 0);
5016 
5017 	signals[COMPOSER_CREATED] = g_signal_new (
5018 		"composer-created",
5019 		G_OBJECT_CLASS_TYPE (iface),
5020 		G_SIGNAL_RUN_FIRST,
5021 		G_STRUCT_OFFSET (EMailReaderInterface, composer_created),
5022 		NULL, NULL, NULL,
5023 		G_TYPE_NONE, 2,
5024 		E_TYPE_MSG_COMPOSER,
5025 		CAMEL_TYPE_MIME_MESSAGE);
5026 
5027 	signals[FOLDER_LOADED] = g_signal_new (
5028 		"folder-loaded",
5029 		G_OBJECT_CLASS_TYPE (iface),
5030 		G_SIGNAL_RUN_FIRST,
5031 		G_STRUCT_OFFSET (EMailReaderInterface, folder_loaded),
5032 		NULL, NULL,
5033 		g_cclosure_marshal_VOID__VOID,
5034 		G_TYPE_NONE, 0);
5035 
5036 	signals[MESSAGE_LOADED] = g_signal_new (
5037 		"message-loaded",
5038 		G_OBJECT_CLASS_TYPE (iface),
5039 		G_SIGNAL_RUN_LAST,
5040 		G_STRUCT_OFFSET (EMailReaderInterface, message_loaded),
5041 		NULL, NULL,
5042 		e_marshal_VOID__STRING_OBJECT,
5043 		G_TYPE_NONE, 2,
5044 		G_TYPE_STRING,
5045 		CAMEL_TYPE_MIME_MESSAGE);
5046 
5047 	signals[MESSAGE_SEEN] = g_signal_new (
5048 		"message-seen",
5049 		G_OBJECT_CLASS_TYPE (iface),
5050 		G_SIGNAL_RUN_LAST,
5051 		G_STRUCT_OFFSET (EMailReaderInterface, message_seen),
5052 		NULL, NULL,
5053 		e_marshal_VOID__STRING_OBJECT,
5054 		G_TYPE_NONE, 2,
5055 		G_TYPE_STRING,
5056 		CAMEL_TYPE_MIME_MESSAGE);
5057 
5058 	signals[SHOW_SEARCH_BAR] = g_signal_new (
5059 		"show-search-bar",
5060 		G_OBJECT_CLASS_TYPE (iface),
5061 		G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
5062 		G_STRUCT_OFFSET (EMailReaderInterface, show_search_bar),
5063 		NULL, NULL,
5064 		g_cclosure_marshal_VOID__VOID,
5065 		G_TYPE_NONE, 0);
5066 
5067 	signals[UPDATE_ACTIONS] = g_signal_new (
5068 		"update-actions",
5069 		G_OBJECT_CLASS_TYPE (iface),
5070 		G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
5071 		G_STRUCT_OFFSET (EMailReaderInterface, update_actions),
5072 		NULL, NULL,
5073 		g_cclosure_marshal_VOID__UINT,
5074 		G_TYPE_NONE, 1,
5075 		G_TYPE_UINT);
5076 }
5077 
5078 void
e_mail_reader_init(EMailReader * reader,gboolean init_actions,gboolean connect_signals)5079 e_mail_reader_init (EMailReader *reader,
5080                     gboolean init_actions,
5081                     gboolean connect_signals)
5082 {
5083 	EMenuToolAction *menu_tool_action;
5084 	GtkActionGroup *action_group;
5085 	GtkWidget *message_list;
5086 	GtkAction *action;
5087 	const gchar *action_name;
5088 	EMailDisplay *display;
5089 	GSettings *settings;
5090 
5091 	g_return_if_fail (E_IS_MAIL_READER (reader));
5092 
5093 	message_list = e_mail_reader_get_message_list (reader);
5094 	display = e_mail_reader_get_mail_display (reader);
5095 
5096 	/* Initialize a private struct. */
5097 	g_object_set_qdata_full (
5098 		G_OBJECT (reader), quark_private,
5099 		g_slice_new0 (EMailReaderPrivate),
5100 		(GDestroyNotify) mail_reader_private_free);
5101 
5102 	e_binding_bind_property (
5103 		reader, "group-by-threads",
5104 		message_list, "group-by-threads",
5105 		G_BINDING_SYNC_CREATE);
5106 
5107 	if (!init_actions)
5108 		goto connect_signals;
5109 
5110 	/* Add the "standard" EMailReader actions. */
5111 
5112 	action_group = e_mail_reader_get_action_group (
5113 		reader, E_MAIL_READER_ACTION_GROUP_STANDARD);
5114 
5115 	/* The "mail-forward" action is special: it uses a GtkMenuToolButton
5116 	 * for its toolbar item type.  So we have to create it separately. */
5117 
5118 	menu_tool_action = e_menu_tool_action_new (
5119 		"mail-forward", _("_Forward"),
5120 		_("Forward the selected message to someone"));
5121 
5122 	gtk_action_set_icon_name (
5123 		GTK_ACTION (menu_tool_action), "mail-forward");
5124 
5125 	g_signal_connect (
5126 		menu_tool_action, "activate",
5127 		G_CALLBACK (action_mail_forward_cb), reader);
5128 
5129 	gtk_action_group_add_action_with_accel (
5130 		action_group, GTK_ACTION (menu_tool_action), "<Control>f");
5131 
5132 	/* Likewise the "mail-reply-group" action. */
5133 
5134 	menu_tool_action = e_menu_tool_action_new (
5135 		/* For Translators: "Group Reply" will reply either to a mailing list
5136 		 * (if possible and if that configuration option is enabled), or else
5137 		 * it will reply to all. The word "Group" was chosen because it covers
5138 		 * either of those, without too strongly implying one or the other. */
5139 		"mail-reply-group", _("Group Reply"),
5140 		_("Reply to the mailing list, or to all recipients"));
5141 
5142 	gtk_action_set_icon_name (
5143 		GTK_ACTION (menu_tool_action), "mail-reply-all");
5144 
5145 	g_signal_connect (
5146 		menu_tool_action, "activate",
5147 		G_CALLBACK (action_mail_reply_group_cb), reader);
5148 
5149 	gtk_action_group_add_action_with_accel (
5150 		action_group, GTK_ACTION (menu_tool_action), "<Control>g");
5151 
5152 	/* Add the other actions the normal way. */
5153 	gtk_action_group_add_actions (
5154 		action_group, mail_reader_entries,
5155 		G_N_ELEMENTS (mail_reader_entries), reader);
5156 	e_action_group_add_popup_actions (
5157 		action_group, mail_reader_popup_entries,
5158 		G_N_ELEMENTS (mail_reader_popup_entries));
5159 	gtk_action_group_add_toggle_actions (
5160 		action_group, mail_reader_toggle_entries,
5161 		G_N_ELEMENTS (mail_reader_toggle_entries), reader);
5162 
5163 	mail_reader_init_charset_actions (reader, action_group);
5164 
5165 	/* Add EMailReader actions for Search Folders.  The action group
5166 	 * should be made invisible if Search Folders are disabled. */
5167 
5168 	action_group = e_mail_reader_get_action_group (
5169 		reader, E_MAIL_READER_ACTION_GROUP_SEARCH_FOLDERS);
5170 
5171 	gtk_action_group_add_actions (
5172 		action_group, mail_reader_search_folder_entries,
5173 		G_N_ELEMENTS (mail_reader_search_folder_entries), reader);
5174 
5175 	display = e_mail_reader_get_mail_display (reader);
5176 
5177 	/* Bind GObject properties to GSettings keys. */
5178 
5179 	settings = e_util_ref_settings ("org.gnome.evolution.mail");
5180 
5181 	action_name = "mail-caret-mode";
5182 	action = e_mail_reader_get_action (reader, action_name);
5183 	g_settings_bind (
5184 		settings, "caret-mode",
5185 		action, "active", G_SETTINGS_BIND_DEFAULT);
5186 
5187 	action_name = "mail-show-all-headers";
5188 	action = e_mail_reader_get_action (reader, action_name);
5189 	g_settings_bind (
5190 		settings, "show-all-headers",
5191 		action, "active", G_SETTINGS_BIND_DEFAULT);
5192 
5193 	/* Mode change when viewing message source is ignored. */
5194 	if (e_mail_display_get_mode (display) == E_MAIL_FORMATTER_MODE_SOURCE ||
5195 	    e_mail_display_get_mode (display) == E_MAIL_FORMATTER_MODE_RAW) {
5196 		gtk_action_set_sensitive (action, FALSE);
5197 		gtk_action_set_visible (action, FALSE);
5198 	}
5199 
5200 	g_object_unref (settings);
5201 
5202 	/* Fine tuning. */
5203 
5204 	action_name = "mail-delete";
5205 	action = e_mail_reader_get_action (reader, action_name);
5206 	gtk_action_set_short_label (action, _("Delete"));
5207 
5208 	action_name = "mail-forward";
5209 	action = e_mail_reader_get_action (reader, action_name);
5210 	gtk_action_set_is_important (action, TRUE);
5211 
5212 	action_name = "mail-reply-group";
5213 	action = e_mail_reader_get_action (reader, action_name);
5214 	gtk_action_set_is_important (action, TRUE);
5215 
5216 	action_name = "mail-next";
5217 	action = e_mail_reader_get_action (reader, action_name);
5218 	gtk_action_set_short_label (action, _("Next"));
5219 
5220 	action_name = "mail-previous";
5221 	action = e_mail_reader_get_action (reader, action_name);
5222 	gtk_action_set_short_label (action, _("Previous"));
5223 
5224 	action_name = "mail-reply-all";
5225 	action = e_mail_reader_get_action (reader, action_name);
5226 	gtk_action_set_is_important (action, TRUE);
5227 
5228 	action_name = "mail-reply-sender";
5229 	action = e_mail_reader_get_action (reader, action_name);
5230 	gtk_action_set_is_important (action, TRUE);
5231 	gtk_action_set_short_label (action, _("Reply"));
5232 
5233 	action_name = "add-to-address-book";
5234 	action = e_mail_display_get_action (display, action_name);
5235 	g_signal_connect (
5236 		action, "activate",
5237 		G_CALLBACK (action_add_to_address_book_cb), reader);
5238 
5239 	action_name = "send-reply";
5240 	action = e_mail_display_get_action (display, action_name);
5241 	g_signal_connect (
5242 		action, "activate",
5243 		G_CALLBACK (action_mail_reply_recipient_cb), reader);
5244 
5245 	action_name = "search-folder-recipient";
5246 	action = e_mail_display_get_action (display, action_name);
5247 	g_signal_connect (
5248 		action, "activate",
5249 		G_CALLBACK (action_search_folder_recipient_cb), reader);
5250 
5251 	action_name = "search-folder-sender";
5252 	action = e_mail_display_get_action (display, action_name);
5253 	g_signal_connect (
5254 		action, "activate",
5255 		G_CALLBACK (action_search_folder_sender_cb), reader);
5256 
5257 #ifndef G_OS_WIN32
5258 	/* Lockdown integration. */
5259 
5260 	settings = e_util_ref_settings ("org.gnome.desktop.lockdown");
5261 
5262 	action_name = "mail-print";
5263 	action = e_mail_reader_get_action (reader, action_name);
5264 	g_settings_bind (
5265 		settings, "disable-printing",
5266 		action, "visible",
5267 		G_SETTINGS_BIND_GET |
5268 		G_SETTINGS_BIND_NO_SENSITIVITY |
5269 		G_SETTINGS_BIND_INVERT_BOOLEAN);
5270 
5271 	action_name = "mail-print-preview";
5272 	action = e_mail_reader_get_action (reader, action_name);
5273 	g_settings_bind (
5274 		settings, "disable-printing",
5275 		action, "visible",
5276 		G_SETTINGS_BIND_GET |
5277 		G_SETTINGS_BIND_NO_SENSITIVITY |
5278 		G_SETTINGS_BIND_INVERT_BOOLEAN);
5279 
5280 	action_name = "mail-save-as";
5281 	action = e_mail_reader_get_action (reader, action_name);
5282 	g_settings_bind (
5283 		settings, "disable-save-to-disk",
5284 		action, "visible",
5285 		G_SETTINGS_BIND_GET |
5286 		G_SETTINGS_BIND_NO_SENSITIVITY |
5287 		G_SETTINGS_BIND_INVERT_BOOLEAN);
5288 
5289 	g_object_unref (settings);
5290 #endif
5291 
5292 	/* Bind properties. */
5293 
5294 	action_name = "mail-caret-mode";
5295 	action = e_mail_reader_get_action (reader, action_name);
5296 
5297 	e_binding_bind_property (
5298 		action, "active",
5299 		display, "caret-mode",
5300 		G_BINDING_BIDIRECTIONAL |
5301 		G_BINDING_SYNC_CREATE);
5302 
5303 connect_signals:
5304 
5305 	if (!connect_signals)
5306 		return;
5307 
5308 	/* Connect signals. */
5309 	g_signal_connect_swapped (
5310 		display, "key-press-event",
5311 		G_CALLBACK (mail_reader_key_press_event_cb), reader);
5312 
5313 	g_signal_connect_swapped (
5314 		display, "load-changed",
5315 		G_CALLBACK (mail_reader_load_changed_cb), reader);
5316 
5317 	g_signal_connect_swapped (
5318 		display, "remote-content-clicked",
5319 		G_CALLBACK (mail_reader_remote_content_clicked_cb), reader);
5320 
5321 	g_signal_connect_swapped (
5322 		message_list, "message-selected",
5323 		G_CALLBACK (mail_reader_message_selected_cb), reader);
5324 
5325 	g_signal_connect_swapped (
5326 		message_list, "update-actions",
5327 		G_CALLBACK (mail_reader_message_list_suggest_update_actions_cb), reader);
5328 
5329 	/* re-schedule mark-as-seen,... */
5330 	g_signal_connect_swapped (
5331 		message_list, "cursor-change",
5332 		G_CALLBACK (mail_reader_message_cursor_change_cb), reader);
5333 
5334 	/* but do not mark-as-seen if... */
5335 	g_signal_connect_swapped (
5336 		message_list, "tree-drag-begin",
5337 		G_CALLBACK (discard_timeout_mark_seen_cb), reader);
5338 
5339 	g_signal_connect_swapped (
5340 		message_list, "tree-drag-end",
5341 		G_CALLBACK (discard_timeout_mark_seen_cb), reader);
5342 
5343 	g_signal_connect_swapped (
5344 		message_list, "right-click",
5345 		G_CALLBACK (discard_timeout_mark_seen_cb), reader);
5346 
5347 	g_signal_connect_swapped (
5348 		e_mail_reader_get_preview_pane (reader), "notify::visible",
5349 		G_CALLBACK (mail_reader_preview_pane_visible_changed_cb), reader);
5350 
5351 	g_signal_connect_after (
5352 		message_list, "message-list-built",
5353 		G_CALLBACK (mail_reader_message_list_built_cb), reader);
5354 
5355 	g_signal_connect_swapped (
5356 		message_list, "double-click",
5357 		G_CALLBACK (mail_reader_double_click_cb), reader);
5358 
5359 	g_signal_connect_swapped (
5360 		message_list, "key-press",
5361 		G_CALLBACK (mail_reader_key_press_cb), reader);
5362 
5363 	g_signal_connect_swapped (
5364 		message_list, "selection-change",
5365 		G_CALLBACK (e_mail_reader_changed), reader);
5366 }
5367 
5368 static void
mail_reader_ongoing_operation_destroyed(gpointer user_data,GObject * cancellable)5369 mail_reader_ongoing_operation_destroyed (gpointer user_data,
5370 					 GObject *cancellable)
5371 {
5372 	EMailReader *reader = user_data;
5373 	EMailReaderPrivate *priv;
5374 
5375 	g_return_if_fail (E_IS_MAIL_READER (reader));
5376 
5377 	priv = E_MAIL_READER_GET_PRIVATE (reader);
5378 
5379 	priv->ongoing_operations = g_slist_remove (priv->ongoing_operations, cancellable);
5380 }
5381 
5382 void
e_mail_reader_dispose(EMailReader * reader)5383 e_mail_reader_dispose (EMailReader *reader)
5384 {
5385 	EMailReaderPrivate *priv;
5386 	EMailDisplay *mail_display;
5387 	GtkWidget *message_list;
5388 	GSList *ongoing_operations, *link;
5389 
5390 	g_return_if_fail (E_IS_MAIL_READER (reader));
5391 
5392 	priv = E_MAIL_READER_GET_PRIVATE (reader);
5393 
5394 	if (priv->message_selected_timeout_id > 0) {
5395 		g_source_remove (priv->message_selected_timeout_id);
5396 		priv->message_selected_timeout_id = 0;
5397 	}
5398 
5399 	if (priv->retrieving_message)
5400 		g_cancellable_cancel (priv->retrieving_message);
5401 
5402 	ongoing_operations = g_slist_copy_deep (priv->ongoing_operations, (GCopyFunc) g_object_ref, NULL);
5403 	g_slist_free (priv->ongoing_operations);
5404 	priv->ongoing_operations = NULL;
5405 
5406 	for (link = ongoing_operations; link; link = g_slist_next (link)) {
5407 		GCancellable *cancellable = link->data;
5408 
5409 		g_object_weak_unref (G_OBJECT (cancellable), mail_reader_ongoing_operation_destroyed, reader);
5410 
5411 		g_cancellable_cancel (cancellable);
5412 	}
5413 
5414 	g_slist_free_full (ongoing_operations, g_object_unref);
5415 
5416 	mail_display = e_mail_reader_get_mail_display (reader);
5417 	if (mail_display)
5418 		g_signal_handlers_disconnect_by_data (mail_display, reader);
5419 
5420 	message_list = e_mail_reader_get_message_list (reader);
5421 	if (message_list)
5422 		g_signal_handlers_disconnect_by_data (message_list, reader);
5423 }
5424 
5425 void
e_mail_reader_changed(EMailReader * reader)5426 e_mail_reader_changed (EMailReader *reader)
5427 {
5428 	MessageList *message_list;
5429 
5430 	g_return_if_fail (E_IS_MAIL_READER (reader));
5431 
5432 	g_signal_emit (reader, signals[CHANGED], 0);
5433 
5434 	message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
5435 
5436 	if (!message_list || message_list_selected_count (message_list) != 1)
5437 		mail_reader_remove_followup_alert (reader);
5438 }
5439 
5440 guint32
e_mail_reader_check_state(EMailReader * reader)5441 e_mail_reader_check_state (EMailReader *reader)
5442 {
5443 	EShell *shell;
5444 	GPtrArray *uids;
5445 	CamelFolder *folder;
5446 	CamelStore *store = NULL;
5447 	EMailBackend *backend;
5448 	ESourceRegistry *registry;
5449 	EMailSession *mail_session;
5450 	EMailAccountStore *account_store;
5451 	const gchar *tag;
5452 	gboolean can_clear_flags = FALSE;
5453 	gboolean can_flag_completed = FALSE;
5454 	gboolean can_flag_for_followup = FALSE;
5455 	gboolean has_attachments = FALSE;
5456 	gboolean has_deleted = FALSE;
5457 	gboolean has_ignore_thread = FALSE;
5458 	gboolean has_notignore_thread = FALSE;
5459 	gboolean has_important = FALSE;
5460 	gboolean has_junk = FALSE;
5461 	gboolean has_not_junk = FALSE;
5462 	gboolean has_read = FALSE;
5463 	gboolean has_undeleted = FALSE;
5464 	gboolean has_unimportant = FALSE;
5465 	gboolean has_unread = FALSE;
5466 	gboolean has_mail_note = FALSE;
5467 	gboolean has_color = FALSE;
5468 	gboolean have_enabled_account = FALSE;
5469 	gboolean drafts_or_outbox = FALSE;
5470 	gboolean is_mailing_list;
5471 	gboolean is_junk_folder = FALSE;
5472 	gboolean is_vtrash_folder = FALSE;
5473 	gboolean archive_folder_set = FALSE;
5474 	guint32 state = 0;
5475 	guint ii;
5476 
5477 	g_return_val_if_fail (E_IS_MAIL_READER (reader), 0);
5478 
5479 	backend = e_mail_reader_get_backend (reader);
5480 	shell = e_shell_backend_get_shell (E_SHELL_BACKEND (backend));
5481 	registry = e_shell_get_registry (shell);
5482 	mail_session = e_mail_backend_get_session (backend);
5483 	account_store = e_mail_ui_session_get_account_store (
5484 		E_MAIL_UI_SESSION (mail_session));
5485 
5486 	folder = e_mail_reader_ref_folder (reader);
5487 	uids = e_mail_reader_get_selected_uids_with_collapsed_threads (reader);
5488 
5489 	if (folder != NULL) {
5490 		gchar *archive_folder;
5491 		guint32 folder_flags;
5492 
5493 		store = camel_folder_get_parent_store (folder);
5494 		folder_flags = camel_folder_get_flags (folder);
5495 		is_junk_folder = (folder_flags & CAMEL_FOLDER_IS_JUNK) != 0;
5496 		is_vtrash_folder = (camel_store_get_flags (store) & CAMEL_STORE_VTRASH) != 0 && (folder_flags & CAMEL_FOLDER_IS_TRASH) != 0;
5497 		drafts_or_outbox =
5498 			em_utils_folder_is_drafts (registry, folder) ||
5499 			em_utils_folder_is_outbox (registry, folder);
5500 
5501 		archive_folder = em_utils_get_archive_folder_uri_from_folder (folder, backend, uids, TRUE);
5502 		if (archive_folder && *archive_folder)
5503 			archive_folder_set = TRUE;
5504 
5505 		g_free (archive_folder);
5506 	}
5507 
5508 	/* Initialize this flag based on whether there are any
5509 	 * messages selected.  We will update it in the loop. */
5510 	is_mailing_list = (uids->len > 0);
5511 
5512 	for (ii = 0; ii < uids->len; ii++) {
5513 		CamelMessageInfo *info;
5514 		const gchar *string;
5515 		guint32 flags;
5516 
5517 		info = camel_folder_get_message_info (
5518 			folder, uids->pdata[ii]);
5519 		if (info == NULL)
5520 			continue;
5521 
5522 		flags = camel_message_info_get_flags (info);
5523 
5524 		if (flags & CAMEL_MESSAGE_SEEN)
5525 			has_read = TRUE;
5526 		else
5527 			has_unread = TRUE;
5528 
5529 		if (flags & CAMEL_MESSAGE_ATTACHMENTS)
5530 			has_attachments = TRUE;
5531 
5532 		if (drafts_or_outbox) {
5533 			has_junk = FALSE;
5534 			has_not_junk = FALSE;
5535 		} else {
5536 			guint32 bitmask;
5537 
5538 			/* XXX Strictly speaking, this logic is correct.
5539 			 *     Problem is there's nothing in the message
5540 			 *     list that indicates whether a message is
5541 			 *     already marked "Not Junk".  So the user may
5542 			 *     think the "Not Junk" button is enabling and
5543 			 *     disabling itself randomly as he reads mail. */
5544 
5545 			if (flags & CAMEL_MESSAGE_JUNK)
5546 				has_junk = TRUE;
5547 			if (flags & CAMEL_MESSAGE_NOTJUNK)
5548 				has_not_junk = TRUE;
5549 
5550 			bitmask = CAMEL_MESSAGE_JUNK | CAMEL_MESSAGE_NOTJUNK;
5551 
5552 			/* If neither junk flag is set, the
5553 			 * message can be marked either way. */
5554 			if ((flags & bitmask) == 0) {
5555 				has_junk = TRUE;
5556 				has_not_junk = TRUE;
5557 			}
5558 		}
5559 
5560 		if (flags & CAMEL_MESSAGE_DELETED)
5561 			has_deleted = TRUE;
5562 		else
5563 			has_undeleted = TRUE;
5564 
5565 		if (flags & CAMEL_MESSAGE_FLAGGED)
5566 			has_important = TRUE;
5567 		else
5568 			has_unimportant = TRUE;
5569 
5570 		tag = camel_message_info_get_user_tag (info, "follow-up");
5571 		if (tag != NULL && *tag != '\0') {
5572 			can_clear_flags = TRUE;
5573 			tag = camel_message_info_get_user_tag (
5574 				info, "completed-on");
5575 			if (tag == NULL || *tag == '\0')
5576 				can_flag_completed = TRUE;
5577 		} else
5578 			can_flag_for_followup = TRUE;
5579 
5580 		string = camel_message_info_get_mlist (info);
5581 		is_mailing_list &= (string != NULL && *string != '\0');
5582 
5583 		has_ignore_thread = has_ignore_thread || camel_message_info_get_user_flag (info, "ignore-thread");
5584 		has_notignore_thread = has_notignore_thread || !camel_message_info_get_user_flag (info, "ignore-thread");
5585 		has_mail_note = has_mail_note || camel_message_info_get_user_flag (info, E_MAIL_NOTES_USER_FLAG);
5586 		has_color = has_color || camel_message_info_get_user_tag (info, "color") != NULL;
5587 
5588 		g_clear_object (&info);
5589 	}
5590 
5591 	have_enabled_account =
5592 		e_mail_account_store_have_enabled_service (
5593 		account_store, CAMEL_TYPE_STORE);
5594 
5595 	if (have_enabled_account)
5596 		state |= E_MAIL_READER_HAVE_ENABLED_ACCOUNT;
5597 	if (uids->len == 1)
5598 		state |= E_MAIL_READER_SELECTION_SINGLE;
5599 	if (uids->len > 1)
5600 		state |= E_MAIL_READER_SELECTION_MULTIPLE;
5601 	if (!drafts_or_outbox && uids->len == 1)
5602 		state |= E_MAIL_READER_SELECTION_CAN_ADD_SENDER;
5603 	if (can_clear_flags)
5604 		state |= E_MAIL_READER_SELECTION_FLAG_CLEAR;
5605 	if (can_flag_completed)
5606 		state |= E_MAIL_READER_SELECTION_FLAG_COMPLETED;
5607 	if (can_flag_for_followup)
5608 		state |= E_MAIL_READER_SELECTION_FLAG_FOLLOWUP;
5609 	if (has_attachments)
5610 		state |= E_MAIL_READER_SELECTION_HAS_ATTACHMENTS;
5611 	if (has_deleted)
5612 		state |= E_MAIL_READER_SELECTION_HAS_DELETED;
5613 	if (has_ignore_thread)
5614 		state |= E_MAIL_READER_SELECTION_HAS_IGNORE_THREAD;
5615 	if (has_notignore_thread)
5616 		state |= E_MAIL_READER_SELECTION_HAS_NOTIGNORE_THREAD;
5617 	if (has_important)
5618 		state |= E_MAIL_READER_SELECTION_HAS_IMPORTANT;
5619 	if (has_junk)
5620 		state |= E_MAIL_READER_SELECTION_HAS_JUNK;
5621 	if (has_not_junk)
5622 		state |= E_MAIL_READER_SELECTION_HAS_NOT_JUNK;
5623 	if (has_read)
5624 		state |= E_MAIL_READER_SELECTION_HAS_READ;
5625 	if (has_undeleted)
5626 		state |= E_MAIL_READER_SELECTION_HAS_UNDELETED;
5627 	if (has_unimportant)
5628 		state |= E_MAIL_READER_SELECTION_HAS_UNIMPORTANT;
5629 	if (has_unread)
5630 		state |= E_MAIL_READER_SELECTION_HAS_UNREAD;
5631 	if (is_mailing_list)
5632 		state |= E_MAIL_READER_SELECTION_IS_MAILING_LIST;
5633 	if (is_junk_folder)
5634 		state |= E_MAIL_READER_FOLDER_IS_JUNK;
5635 	if (is_vtrash_folder)
5636 		state |= E_MAIL_READER_FOLDER_IS_VTRASH;
5637 	if (archive_folder_set)
5638 		state |= E_MAIL_READER_FOLDER_ARCHIVE_FOLDER_SET;
5639 	if (has_mail_note)
5640 		state |= E_MAIL_READER_SELECTION_HAS_MAIL_NOTE;
5641 	if (has_color)
5642 		state |= E_MAIL_READER_SELECTION_HAS_COLOR;
5643 
5644 	if (!(state & E_MAIL_READER_SELECTION_SINGLE)) {
5645 		GPtrArray *real_selected_uids;
5646 
5647 		real_selected_uids = e_mail_reader_get_selected_uids (reader);
5648 
5649 		if (real_selected_uids && real_selected_uids->len == 1) {
5650 			state |= E_MAIL_READER_SELECTION_SINGLE;
5651 		}
5652 
5653 		if (real_selected_uids)
5654 			g_ptr_array_unref (real_selected_uids);
5655 	}
5656 
5657 	g_clear_object (&folder);
5658 	g_ptr_array_unref (uids);
5659 
5660 	return state;
5661 }
5662 
5663 EActivity *
e_mail_reader_new_activity(EMailReader * reader)5664 e_mail_reader_new_activity (EMailReader *reader)
5665 {
5666 	EMailReaderPrivate *priv;
5667 	EActivity *activity;
5668 	EMailBackend *backend;
5669 	EAlertSink *alert_sink;
5670 	GCancellable *cancellable;
5671 
5672 	g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
5673 
5674 	priv = E_MAIL_READER_GET_PRIVATE (reader);
5675 
5676 	activity = e_activity_new ();
5677 
5678 	alert_sink = e_mail_reader_get_alert_sink (reader);
5679 	e_activity_set_alert_sink (activity, alert_sink);
5680 
5681 	cancellable = camel_operation_new ();
5682 
5683 	priv->ongoing_operations = g_slist_prepend (priv->ongoing_operations, cancellable);
5684 	g_object_weak_ref (G_OBJECT (cancellable), mail_reader_ongoing_operation_destroyed, reader);
5685 
5686 	e_activity_set_cancellable (activity, cancellable);
5687 	g_object_unref (cancellable);
5688 
5689 	backend = e_mail_reader_get_backend (reader);
5690 	e_shell_backend_add_activity (E_SHELL_BACKEND (backend), activity);
5691 
5692 	return activity;
5693 }
5694 
5695 void
e_mail_reader_update_actions(EMailReader * reader,guint32 state)5696 e_mail_reader_update_actions (EMailReader *reader,
5697                               guint32 state)
5698 {
5699 	g_return_if_fail (E_IS_MAIL_READER (reader));
5700 
5701 	g_signal_emit (reader, signals[UPDATE_ACTIONS], 0, state);
5702 }
5703 
5704 GtkAction *
e_mail_reader_get_action(EMailReader * reader,const gchar * action_name)5705 e_mail_reader_get_action (EMailReader *reader,
5706                           const gchar *action_name)
5707 {
5708 	GtkAction *action = NULL;
5709 	gint ii;
5710 
5711 	g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
5712 	g_return_val_if_fail (action_name != NULL, NULL);
5713 
5714 	for (ii = 0; ii < E_MAIL_READER_NUM_ACTION_GROUPS; ii++) {
5715 		GtkActionGroup *group;
5716 
5717 		group = e_mail_reader_get_action_group (reader, ii);
5718 		action = gtk_action_group_get_action (group, action_name);
5719 
5720 		if (action != NULL)
5721 			break;
5722 	}
5723 
5724 	if (action == NULL)
5725 		g_critical (
5726 			"%s: action '%s' not found", G_STRFUNC, action_name);
5727 
5728 	return action;
5729 }
5730 
5731 GtkActionGroup *
e_mail_reader_get_action_group(EMailReader * reader,EMailReaderActionGroup group)5732 e_mail_reader_get_action_group (EMailReader *reader,
5733                                 EMailReaderActionGroup group)
5734 {
5735 	EMailReaderInterface *iface;
5736 
5737 	g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
5738 
5739 	iface = E_MAIL_READER_GET_INTERFACE (reader);
5740 	g_return_val_if_fail (iface->get_action_group != NULL, NULL);
5741 
5742 	return iface->get_action_group (reader, group);
5743 }
5744 
5745 EAlertSink *
e_mail_reader_get_alert_sink(EMailReader * reader)5746 e_mail_reader_get_alert_sink (EMailReader *reader)
5747 {
5748 	EMailReaderInterface *iface;
5749 
5750 	g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
5751 
5752 	iface = E_MAIL_READER_GET_INTERFACE (reader);
5753 	g_return_val_if_fail (iface->get_alert_sink != NULL, NULL);
5754 
5755 	return iface->get_alert_sink (reader);
5756 }
5757 
5758 EMailBackend *
e_mail_reader_get_backend(EMailReader * reader)5759 e_mail_reader_get_backend (EMailReader *reader)
5760 {
5761 	EMailReaderInterface *iface;
5762 
5763 	g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
5764 
5765 	iface = E_MAIL_READER_GET_INTERFACE (reader);
5766 	g_return_val_if_fail (iface->get_backend != NULL, NULL);
5767 
5768 	return iface->get_backend (reader);
5769 }
5770 
5771 EMailDisplay *
e_mail_reader_get_mail_display(EMailReader * reader)5772 e_mail_reader_get_mail_display (EMailReader *reader)
5773 {
5774 	EMailReaderInterface *iface;
5775 
5776 	g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
5777 
5778 	iface = E_MAIL_READER_GET_INTERFACE (reader);
5779 	g_return_val_if_fail (iface->get_mail_display != NULL, NULL);
5780 
5781 	return iface->get_mail_display (reader);
5782 }
5783 
5784 gboolean
e_mail_reader_get_hide_deleted(EMailReader * reader)5785 e_mail_reader_get_hide_deleted (EMailReader *reader)
5786 {
5787 	EMailReaderInterface *iface;
5788 
5789 	g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE);
5790 
5791 	iface = E_MAIL_READER_GET_INTERFACE (reader);
5792 	g_return_val_if_fail (iface->get_hide_deleted != NULL, FALSE);
5793 
5794 	return iface->get_hide_deleted (reader);
5795 }
5796 
5797 GtkWidget *
e_mail_reader_get_message_list(EMailReader * reader)5798 e_mail_reader_get_message_list (EMailReader *reader)
5799 {
5800 	EMailReaderInterface *iface;
5801 
5802 	g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
5803 
5804 	iface = E_MAIL_READER_GET_INTERFACE (reader);
5805 	g_return_val_if_fail (iface->get_message_list != NULL, NULL);
5806 
5807 	return iface->get_message_list (reader);
5808 }
5809 
5810 static void
e_mail_reader_popup_menu_deactivate_cb(GtkMenu * popup_menu,EMailReader * reader)5811 e_mail_reader_popup_menu_deactivate_cb (GtkMenu *popup_menu,
5812 					EMailReader *reader)
5813 {
5814 	g_return_if_fail (GTK_IS_MENU (popup_menu));
5815 
5816 	g_signal_handlers_disconnect_by_func (popup_menu, e_mail_reader_popup_menu_deactivate_cb, reader);
5817 	gtk_menu_detach (popup_menu);
5818 }
5819 
5820 GtkMenu *
e_mail_reader_get_popup_menu(EMailReader * reader)5821 e_mail_reader_get_popup_menu (EMailReader *reader)
5822 {
5823 	EMailReaderInterface *iface;
5824 	GtkMenu *menu;
5825 
5826 	g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
5827 
5828 	iface = E_MAIL_READER_GET_INTERFACE (reader);
5829 	g_return_val_if_fail (iface->get_popup_menu != NULL, NULL);
5830 
5831 	menu = iface->get_popup_menu (reader);
5832 	if (!gtk_menu_get_attach_widget (GTK_MENU (menu))) {
5833 		gtk_menu_attach_to_widget (GTK_MENU (menu),
5834 					   GTK_WIDGET (reader),
5835 					   NULL);
5836 		g_signal_connect (
5837 			menu, "deactivate",
5838 			G_CALLBACK (e_mail_reader_popup_menu_deactivate_cb), reader);
5839 	}
5840 
5841 	return menu;
5842 }
5843 
5844 EPreviewPane *
e_mail_reader_get_preview_pane(EMailReader * reader)5845 e_mail_reader_get_preview_pane (EMailReader *reader)
5846 {
5847 	EMailReaderInterface *iface;
5848 
5849 	g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
5850 
5851 	iface = E_MAIL_READER_GET_INTERFACE (reader);
5852 	g_return_val_if_fail (iface->get_preview_pane != NULL, NULL);
5853 
5854 	return iface->get_preview_pane (reader);
5855 }
5856 
5857 GPtrArray *
e_mail_reader_get_selected_uids(EMailReader * reader)5858 e_mail_reader_get_selected_uids (EMailReader *reader)
5859 {
5860 	EMailReaderInterface *iface;
5861 
5862 	g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
5863 
5864 	iface = E_MAIL_READER_GET_INTERFACE (reader);
5865 	g_return_val_if_fail (iface->get_selected_uids != NULL, NULL);
5866 
5867 	return iface->get_selected_uids (reader);
5868 }
5869 
5870 GPtrArray *
e_mail_reader_get_selected_uids_with_collapsed_threads(EMailReader * reader)5871 e_mail_reader_get_selected_uids_with_collapsed_threads (EMailReader *reader)
5872 {
5873 	EMailReaderInterface *iface;
5874 
5875 	g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
5876 
5877 	iface = E_MAIL_READER_GET_INTERFACE (reader);
5878 	g_return_val_if_fail (iface->get_selected_uids_with_collapsed_threads != NULL, NULL);
5879 
5880 	return iface->get_selected_uids_with_collapsed_threads (reader);
5881 }
5882 
5883 GtkWindow *
e_mail_reader_get_window(EMailReader * reader)5884 e_mail_reader_get_window (EMailReader *reader)
5885 {
5886 	EMailReaderInterface *iface;
5887 
5888 	g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
5889 
5890 	iface = E_MAIL_READER_GET_INTERFACE (reader);
5891 	g_return_val_if_fail (iface->get_window != NULL, NULL);
5892 
5893 	return iface->get_window (reader);
5894 }
5895 
5896 gboolean
e_mail_reader_close_on_delete_or_junk(EMailReader * reader)5897 e_mail_reader_close_on_delete_or_junk (EMailReader *reader)
5898 {
5899 	EMailReaderInterface *iface;
5900 
5901 	g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE);
5902 
5903 	iface = E_MAIL_READER_GET_INTERFACE (reader);
5904 
5905 	return iface->close_on_delete_or_junk != NULL &&
5906 	       iface->close_on_delete_or_junk (reader);
5907 }
5908 
5909 CamelFolder *
e_mail_reader_ref_folder(EMailReader * reader)5910 e_mail_reader_ref_folder (EMailReader *reader)
5911 {
5912 	EMailReaderInterface *iface;
5913 
5914 	g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL);
5915 
5916 	iface = E_MAIL_READER_GET_INTERFACE (reader);
5917 	g_return_val_if_fail (iface->ref_folder != NULL, NULL);
5918 
5919 	return iface->ref_folder (reader);
5920 }
5921 
5922 void
e_mail_reader_set_folder(EMailReader * reader,CamelFolder * folder)5923 e_mail_reader_set_folder (EMailReader *reader,
5924                           CamelFolder *folder)
5925 {
5926 	EMailReaderInterface *iface;
5927 
5928 	g_return_if_fail (E_IS_MAIL_READER (reader));
5929 
5930 	iface = E_MAIL_READER_GET_INTERFACE (reader);
5931 	g_return_if_fail (iface->set_folder != NULL);
5932 
5933 	iface->set_folder (reader, folder);
5934 }
5935 
5936 void
e_mail_reader_set_message(EMailReader * reader,const gchar * message_uid)5937 e_mail_reader_set_message (EMailReader *reader,
5938                            const gchar *message_uid)
5939 {
5940 	EMailReaderInterface *iface;
5941 
5942 	g_return_if_fail (E_IS_MAIL_READER (reader));
5943 
5944 	iface = E_MAIL_READER_GET_INTERFACE (reader);
5945 	g_return_if_fail (iface->set_message != NULL);
5946 
5947 	iface->set_message (reader, message_uid);
5948 }
5949 
5950 guint
e_mail_reader_open_selected_mail(EMailReader * reader)5951 e_mail_reader_open_selected_mail (EMailReader *reader)
5952 {
5953 	EMailReaderInterface *iface;
5954 
5955 	g_return_val_if_fail (E_IS_MAIL_READER (reader), 0);
5956 
5957 	iface = E_MAIL_READER_GET_INTERFACE (reader);
5958 	g_return_val_if_fail (iface->open_selected_mail != NULL, 0);
5959 
5960 	return iface->open_selected_mail (reader);
5961 }
5962 
5963 EMailForwardStyle
e_mail_reader_get_forward_style(EMailReader * reader)5964 e_mail_reader_get_forward_style (EMailReader *reader)
5965 {
5966 	EMailReaderPrivate *priv;
5967 
5968 	g_return_val_if_fail (E_IS_MAIL_READER (reader), 0);
5969 
5970 	priv = E_MAIL_READER_GET_PRIVATE (reader);
5971 
5972 	return priv->forward_style;
5973 }
5974 
5975 void
e_mail_reader_set_forward_style(EMailReader * reader,EMailForwardStyle style)5976 e_mail_reader_set_forward_style (EMailReader *reader,
5977                                  EMailForwardStyle style)
5978 {
5979 	EMailReaderPrivate *priv;
5980 
5981 	g_return_if_fail (E_IS_MAIL_READER (reader));
5982 
5983 	priv = E_MAIL_READER_GET_PRIVATE (reader);
5984 
5985 	if (priv->forward_style == style)
5986 		return;
5987 
5988 	priv->forward_style = style;
5989 
5990 	g_object_notify (G_OBJECT (reader), "forward-style");
5991 }
5992 
5993 gboolean
e_mail_reader_get_group_by_threads(EMailReader * reader)5994 e_mail_reader_get_group_by_threads (EMailReader *reader)
5995 {
5996 	EMailReaderPrivate *priv;
5997 
5998 	g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE);
5999 
6000 	priv = E_MAIL_READER_GET_PRIVATE (reader);
6001 
6002 	return priv->group_by_threads;
6003 }
6004 
6005 void
e_mail_reader_set_group_by_threads(EMailReader * reader,gboolean group_by_threads)6006 e_mail_reader_set_group_by_threads (EMailReader *reader,
6007                                     gboolean group_by_threads)
6008 {
6009 	EMailReaderPrivate *priv;
6010 
6011 	g_return_if_fail (E_IS_MAIL_READER (reader));
6012 
6013 	priv = E_MAIL_READER_GET_PRIVATE (reader);
6014 
6015 	if (priv->group_by_threads == group_by_threads)
6016 		return;
6017 
6018 	priv->group_by_threads = group_by_threads;
6019 
6020 	g_object_notify (G_OBJECT (reader), "group-by-threads");
6021 }
6022 
6023 EMailReplyStyle
e_mail_reader_get_reply_style(EMailReader * reader)6024 e_mail_reader_get_reply_style (EMailReader *reader)
6025 {
6026 	EMailReaderPrivate *priv;
6027 
6028 	g_return_val_if_fail (E_IS_MAIL_READER (reader), 0);
6029 
6030 	priv = E_MAIL_READER_GET_PRIVATE (reader);
6031 
6032 	return priv->reply_style;
6033 }
6034 
6035 void
e_mail_reader_set_reply_style(EMailReader * reader,EMailReplyStyle style)6036 e_mail_reader_set_reply_style (EMailReader *reader,
6037                                EMailReplyStyle style)
6038 {
6039 	EMailReaderPrivate *priv;
6040 
6041 	g_return_if_fail (E_IS_MAIL_READER (reader));
6042 
6043 	priv = E_MAIL_READER_GET_PRIVATE (reader);
6044 
6045 	if (priv->reply_style == style)
6046 		return;
6047 
6048 	priv->reply_style = style;
6049 
6050 	g_object_notify (G_OBJECT (reader), "reply-style");
6051 }
6052 
6053 gboolean
e_mail_reader_get_mark_seen_always(EMailReader * reader)6054 e_mail_reader_get_mark_seen_always (EMailReader *reader)
6055 {
6056 	EMailReaderPrivate *priv;
6057 
6058 	g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE);
6059 
6060 	priv = E_MAIL_READER_GET_PRIVATE (reader);
6061 
6062 	return priv->mark_seen_always;
6063 }
6064 
6065 void
e_mail_reader_set_mark_seen_always(EMailReader * reader,gboolean mark_seen_always)6066 e_mail_reader_set_mark_seen_always (EMailReader *reader,
6067                                     gboolean mark_seen_always)
6068 {
6069 	EMailReaderPrivate *priv;
6070 
6071 	g_return_if_fail (E_IS_MAIL_READER (reader));
6072 
6073 	priv = E_MAIL_READER_GET_PRIVATE (reader);
6074 
6075 	if (priv->mark_seen_always == mark_seen_always)
6076 		return;
6077 
6078 	priv->mark_seen_always = mark_seen_always;
6079 
6080 	g_object_notify (G_OBJECT (reader), "mark-seen-always");
6081 }
6082 
6083 gboolean
e_mail_reader_get_delete_selects_previous(EMailReader * reader)6084 e_mail_reader_get_delete_selects_previous (EMailReader *reader)
6085 {
6086 	EMailReaderPrivate *priv;
6087 
6088 	g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE);
6089 
6090 	priv = E_MAIL_READER_GET_PRIVATE (reader);
6091 
6092 	return priv->delete_selects_previous;
6093 }
6094 
6095 void
e_mail_reader_set_delete_selects_previous(EMailReader * reader,gboolean delete_selects_previous)6096 e_mail_reader_set_delete_selects_previous (EMailReader *reader,
6097 					   gboolean delete_selects_previous)
6098 {
6099 	EMailReaderPrivate *priv;
6100 
6101 	g_return_if_fail (E_IS_MAIL_READER (reader));
6102 
6103 	priv = E_MAIL_READER_GET_PRIVATE (reader);
6104 
6105 	if (priv->delete_selects_previous == delete_selects_previous)
6106 		return;
6107 
6108 	priv->delete_selects_previous = delete_selects_previous;
6109 
6110 	g_object_notify (G_OBJECT (reader), "delete-selects-previous");
6111 }
6112 
6113 void
e_mail_reader_create_charset_menu(EMailReader * reader,GtkUIManager * ui_manager,guint merge_id)6114 e_mail_reader_create_charset_menu (EMailReader *reader,
6115                                    GtkUIManager *ui_manager,
6116                                    guint merge_id)
6117 {
6118 	GtkAction *action;
6119 	const gchar *action_name;
6120 	const gchar *path;
6121 	GSList *list;
6122 
6123 	g_return_if_fail (E_IS_MAIL_READER (reader));
6124 	g_return_if_fail (GTK_IS_UI_MANAGER (ui_manager));
6125 
6126 	action_name = "mail-charset-default";
6127 	action = e_mail_reader_get_action (reader, action_name);
6128 	g_return_if_fail (action != NULL);
6129 
6130 	list = gtk_radio_action_get_group (GTK_RADIO_ACTION (action));
6131 	list = g_slist_copy (list);
6132 	list = g_slist_remove (list, action);
6133 	list = g_slist_sort (list, (GCompareFunc) e_action_compare_by_label);
6134 
6135 	path = "/main-menu/view-menu/mail-message-view-actions/mail-encoding-menu";
6136 
6137 	while (list != NULL) {
6138 		action = list->data;
6139 
6140 		gtk_ui_manager_add_ui (
6141 			ui_manager, merge_id, path,
6142 			gtk_action_get_name (action),
6143 			gtk_action_get_name (action),
6144 			GTK_UI_MANAGER_AUTO, FALSE);
6145 
6146 		list = g_slist_delete_link (list, list);
6147 	}
6148 
6149 	gtk_ui_manager_ensure_update (ui_manager);
6150 }
6151 
6152 void
e_mail_reader_show_search_bar(EMailReader * reader)6153 e_mail_reader_show_search_bar (EMailReader *reader)
6154 {
6155 	g_return_if_fail (E_IS_MAIL_READER (reader));
6156 
6157 	g_signal_emit (reader, signals[SHOW_SEARCH_BAR], 0);
6158 }
6159 
6160 void
e_mail_reader_avoid_next_mark_as_seen(EMailReader * reader)6161 e_mail_reader_avoid_next_mark_as_seen (EMailReader *reader)
6162 {
6163 	EMailReaderPrivate *priv;
6164 	MessageList *message_list;
6165 
6166 	g_return_if_fail (reader != NULL);
6167 
6168 	priv = E_MAIL_READER_GET_PRIVATE (reader);
6169 	g_return_if_fail (priv != NULL);
6170 
6171 	message_list = MESSAGE_LIST (e_mail_reader_get_message_list (reader));
6172 	g_return_if_fail (message_list != NULL);
6173 
6174 	priv->avoid_next_mark_as_seen = TRUE;
6175 }
6176 
6177 void
e_mail_reader_unset_folder_just_selected(EMailReader * reader)6178 e_mail_reader_unset_folder_just_selected (EMailReader *reader)
6179 {
6180 	EMailReaderPrivate *priv;
6181 
6182 	g_return_if_fail (reader != NULL);
6183 
6184 	priv = E_MAIL_READER_GET_PRIVATE (reader);
6185 	g_return_if_fail (priv != NULL);
6186 
6187 	priv->folder_was_just_selected = FALSE;
6188 }
6189 
6190 /**
6191  * e_mail_reader_composer_created:
6192  * @reader: an #EMailReader
6193  * @composer: an #EMsgComposer
6194  * @message: the source #CamelMimeMessage, or %NULL
6195  *
6196  * Emits an #EMailReader::composer-created signal to indicate the @composer
6197  * window was created in response to a user action on @reader.  Examples of
6198  * such actions include replying, forwarding, and composing a new message.
6199  * If applicable, the source @message (i.e. the message being replied to or
6200  * forwarded) should be included.
6201  **/
6202 void
e_mail_reader_composer_created(EMailReader * reader,EMsgComposer * composer,CamelMimeMessage * message)6203 e_mail_reader_composer_created (EMailReader *reader,
6204                                 EMsgComposer *composer,
6205                                 CamelMimeMessage *message)
6206 {
6207 	g_return_if_fail (E_IS_MAIL_READER (reader));
6208 	g_return_if_fail (E_IS_MSG_COMPOSER (composer));
6209 
6210 	if (message != NULL)
6211 		g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
6212 
6213 	g_signal_emit (
6214 		reader, signals[COMPOSER_CREATED], 0, composer, message);
6215 }
6216 
6217 void
e_mail_reader_reload(EMailReader * reader)6218 e_mail_reader_reload (EMailReader *reader)
6219 {
6220 	EMailReaderInterface *iface;
6221 
6222 	g_return_if_fail (E_IS_MAIL_READER (reader));
6223 
6224 	iface = E_MAIL_READER_GET_INTERFACE (reader);
6225 	g_return_if_fail (iface->reload != NULL);
6226 
6227 	iface->reload (reader);
6228 }
6229 
6230 void
e_mail_reader_remove_ui(EMailReader * reader)6231 e_mail_reader_remove_ui (EMailReader *reader)
6232 {
6233 	EMailReaderInterface *iface;
6234 
6235 	g_return_if_fail (E_IS_MAIL_READER (reader));
6236 
6237 	iface = E_MAIL_READER_GET_INTERFACE (reader);
6238 	g_return_if_fail (iface->remove_ui != NULL);
6239 
6240 	iface->remove_ui (reader);
6241 }
6242