1 /*
2  * This program is free software; you can redistribute it and/or modify it
3  * under the terms of the GNU Lesser General Public License as published by
4  * the Free Software Foundation.
5  *
6  * This program is distributed in the hope that it will be useful, but
7  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
8  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
9  * for more details.
10  *
11  * You should have received a copy of the GNU Lesser General Public License
12  * along with this program; if not, see <http://www.gnu.org/licenses/>.
13  *
14  *
15  * Authors:
16  *		Srinivasa Ragavan <sragavan@gnome.org>
17  *
18  * Copyright (C) 2010 Intel corporation. (www.intel.com)
19  *
20  */
21 
22 #include "evolution-config.h"
23 
24 #include <glib/gi18n.h>
25 
26 #include <shell/e-shell-window-actions.h>
27 
28 #include <libemail-engine/libemail-engine.h>
29 
30 #include "em-utils.h"
31 #include "message-list.h"
32 #include "e-mail-reader-utils.h"
33 
34 #include "e-mail-paned-view.h"
35 
36 #define E_MAIL_PANED_VIEW_GET_PRIVATE(obj) \
37 	(G_TYPE_INSTANCE_GET_PRIVATE \
38 	((obj), E_TYPE_MAIL_PANED_VIEW, EMailPanedViewPrivate))
39 
40 #define E_SHELL_WINDOW_ACTION_GROUP_MAIL(window) \
41 	E_SHELL_WINDOW_ACTION_GROUP ((window), "mail")
42 
43 struct _EMailPanedViewPrivate {
44 	GtkWidget *paned;
45 	GtkWidget *scrolled_window;
46 	GtkWidget *message_list;
47 	GtkWidget *preview_pane;
48 	GtkWidget *search_bar;
49 
50 	EMailDisplay *display;
51 	GalViewInstance *view_instance;
52 
53 	/* ETable scrolling hack */
54 	gdouble default_scrollbar_position;
55 
56 	guint paned_binding_id;
57 
58 	/* Signal handler IDs */
59 	guint message_list_built_id;
60 
61 	/* TRUE when folder had been just set */
62 	gboolean folder_just_set;
63 	gchar *last_selected_uid;
64 };
65 
66 enum {
67 	PROP_0,
68 	PROP_FORWARD_STYLE,
69 	PROP_GROUP_BY_THREADS,
70 	PROP_REPLY_STYLE,
71 	PROP_MARK_SEEN_ALWAYS,
72 	PROP_DELETE_SELECTS_PREVIOUS
73 };
74 
75 #define STATE_KEY_GROUP_BY_THREADS	"GroupByThreads"
76 #define STATE_KEY_SELECTED_MESSAGE	"SelectedMessage"
77 #define STATE_KEY_PREVIEW_VISIBLE	"PreviewVisible"
78 #define STATE_GROUP_GLOBAL_FOLDER	"GlobalFolder"
79 
80 /* Forward Declarations */
81 static void e_mail_paned_view_reader_init (EMailReaderInterface *iface);
82 
G_DEFINE_TYPE_WITH_CODE(EMailPanedView,e_mail_paned_view,E_TYPE_MAIL_VIEW,G_IMPLEMENT_INTERFACE (E_TYPE_MAIL_READER,e_mail_paned_view_reader_init)G_IMPLEMENT_INTERFACE (E_TYPE_EXTENSIBLE,NULL))83 G_DEFINE_TYPE_WITH_CODE (
84 	EMailPanedView, e_mail_paned_view, E_TYPE_MAIL_VIEW,
85 	G_IMPLEMENT_INTERFACE (
86 		E_TYPE_MAIL_READER, e_mail_paned_view_reader_init)
87 	G_IMPLEMENT_INTERFACE (
88 		E_TYPE_EXTENSIBLE, NULL))
89 
90 static void
91 mail_paned_view_save_boolean (EMailView *view,
92                               const gchar *key,
93                               gboolean value)
94 {
95 	EMailReader *reader;
96 	CamelFolder *folder;
97 
98 	reader = E_MAIL_READER (view);
99 	folder = e_mail_reader_ref_folder (reader);
100 
101 	if (folder != NULL) {
102 		EShellView *shell_view;
103 		GKeyFile *key_file;
104 		gchar *folder_uri;
105 		gchar *group_name;
106 
107 		shell_view = e_mail_view_get_shell_view (view);
108 		key_file = e_shell_view_get_state_key_file (shell_view);
109 
110 		folder_uri = e_mail_folder_uri_from_folder (folder);
111 		group_name = g_strdup_printf ("Folder %s", folder_uri);
112 		g_key_file_set_boolean (key_file, group_name, key, value);
113 		g_free (group_name);
114 		g_free (folder_uri);
115 
116 		g_key_file_set_boolean (
117 			key_file, STATE_GROUP_GLOBAL_FOLDER, key, value);
118 
119 		e_shell_view_set_state_dirty (shell_view);
120 
121 		g_object_unref (folder);
122 	}
123 }
124 
125 static gboolean
mail_paned_view_message_list_is_empty(MessageList * message_list)126 mail_paned_view_message_list_is_empty (MessageList *message_list)
127 {
128 	ETreeModel *model;
129 	ETreePath root;
130 
131 	g_return_val_if_fail (IS_MESSAGE_LIST (message_list), TRUE);
132 
133 	model = e_tree_get_model (E_TREE (message_list));
134 	if (!model)
135 		return TRUE;
136 
137 	root = e_tree_model_get_root (model);
138 	if (!root)
139 		return TRUE;
140 
141 	return !e_tree_model_node_get_first_child (model, root);
142 }
143 
144 static void
mail_paned_view_message_list_built_cb(EMailView * view,MessageList * message_list)145 mail_paned_view_message_list_built_cb (EMailView *view,
146                                        MessageList *message_list)
147 {
148 	EMailPanedViewPrivate *priv;
149 	EShellView *shell_view;
150 	EShellWindow *shell_window;
151 	CamelFolder *folder;
152 	GKeyFile *key_file;
153 	gboolean ensure_message_selected;
154 
155 	priv = E_MAIL_PANED_VIEW_GET_PRIVATE (view);
156 
157 	ensure_message_selected = priv->folder_just_set;
158 	priv->folder_just_set = FALSE;
159 
160 	folder = message_list_ref_folder (message_list);
161 
162 	shell_view = e_mail_view_get_shell_view (view);
163 	shell_window = e_shell_view_get_shell_window (shell_view);
164 
165 	key_file = e_shell_view_get_state_key_file (shell_view);
166 
167 	if (message_list->cursor_uid != NULL)
168 		;  /* do nothing */
169 
170 	else if (folder == NULL)
171 		;  /* do nothing */
172 
173 	else if (e_shell_window_get_safe_mode (shell_window))
174 		e_shell_window_set_safe_mode (shell_window, FALSE);
175 
176 	else {
177 		gchar *uid = NULL;
178 
179 		/* This is for regen when setting filter, or when folder changed or such */
180 		if (!ensure_message_selected &&
181 		    !message_list_selected_count (message_list) &&
182 		    !mail_paned_view_message_list_is_empty (message_list)) {
183 			ensure_message_selected = TRUE;
184 
185 			if (priv->last_selected_uid &&
186 			    message_list_contains_uid (message_list, priv->last_selected_uid)) {
187 				g_free (uid);
188 				uid = g_strdup (priv->last_selected_uid);
189 			}
190 		}
191 
192 		/* This is to prefer last selected message from the previous search folder
193 		   over the stored message. The _set_folder() makes sure to unset
194 		   priv->last_selected_uid, when it's not from this folder. */
195 		if (ensure_message_selected && !uid && priv->last_selected_uid &&
196 		    message_list_contains_uid (message_list, priv->last_selected_uid)) {
197 			uid = g_strdup (priv->last_selected_uid);
198 		}
199 
200 		if (ensure_message_selected && !uid) {
201 			const gchar *key;
202 			gchar *folder_uri;
203 			gchar *group_name;
204 
205 			folder_uri = e_mail_folder_uri_from_folder (folder);
206 
207 			key = STATE_KEY_SELECTED_MESSAGE;
208 			group_name = g_strdup_printf ("Folder %s", folder_uri);
209 			uid = g_key_file_get_string (key_file, group_name, key, NULL);
210 			g_free (group_name);
211 
212 			g_free (folder_uri);
213 		}
214 
215 		if (ensure_message_selected && !message_list_contains_uid (message_list, uid) &&
216 		    e_mail_reader_get_mark_seen_always (E_MAIL_READER (view)))
217 			e_mail_reader_unset_folder_just_selected (E_MAIL_READER (view));
218 
219 		if (ensure_message_selected) {
220 			/* Use selection fallbacks if UID is not found. */
221 			message_list_select_uid (message_list, uid, TRUE);
222 		}
223 
224 		g_free (uid);
225 	}
226 
227 	g_clear_object (&folder);
228 }
229 
230 static void
mail_paned_view_message_selected_cb(EMailView * view,const gchar * message_uid,MessageList * message_list)231 mail_paned_view_message_selected_cb (EMailView *view,
232                                      const gchar *message_uid,
233                                      MessageList *message_list)
234 {
235 	EShellView *shell_view;
236 	CamelFolder *folder;
237 	GKeyFile *key_file;
238 	const gchar *key;
239 	gchar *folder_uri;
240 	gchar *group_name;
241 
242 	folder = message_list_ref_folder (message_list);
243 
244 	/* This also gets triggered when selecting a store name on
245 	 * the sidebar such as "On This Computer", in which case
246 	 * 'folder' will be NULL. */
247 	if (folder == NULL)
248 		return;
249 
250 	shell_view = e_mail_view_get_shell_view (view);
251 	key_file = e_shell_view_get_state_key_file (shell_view);
252 
253 	folder_uri = e_mail_folder_uri_from_folder (folder);
254 
255 	key = STATE_KEY_SELECTED_MESSAGE;
256 	group_name = g_strdup_printf ("Folder %s", folder_uri);
257 
258 	/* Only overwrite changes, do not delete the stored selected message,
259 	   when the current view has nothing (or multiple messages) selected. */
260 	if (message_uid != NULL) {
261 		EMailPanedView *paned_view = E_MAIL_PANED_VIEW (view);
262 
263 		g_key_file_set_string (key_file, group_name, key, message_uid);
264 
265 		g_clear_pointer (&paned_view->priv->last_selected_uid, g_free);
266 		paned_view->priv->last_selected_uid = g_strdup (message_uid);
267 	}
268 
269 	e_shell_view_set_state_dirty (shell_view);
270 
271 	g_free (group_name);
272 	g_free (folder_uri);
273 
274 	g_object_unref (folder);
275 }
276 
277 /* To recognize old values from new values */
278 #define PROPORTION_LOWER_LIMIT 1000000
279 
280 static gboolean
mail_paned_view_map_setting_to_proportion_cb(GValue * value,GVariant * variant,gpointer user_data)281 mail_paned_view_map_setting_to_proportion_cb (GValue *value,
282 					      GVariant *variant,
283 					      gpointer user_data)
284 {
285 	gint stored;
286 	gdouble proportion = 0.5;
287 
288 	stored = g_variant_get_int32 (variant);
289 
290 	if (stored >= PROPORTION_LOWER_LIMIT)
291 		proportion = (stored - PROPORTION_LOWER_LIMIT) / ((gdouble) PROPORTION_LOWER_LIMIT);
292 
293 	g_value_set_double (value, proportion);
294 
295 	return TRUE;
296 }
297 
298 static GVariant *
mail_paned_view_map_proportion_to_setting_cb(const GValue * value,const GVariantType * expected_type,gpointer user_data)299 mail_paned_view_map_proportion_to_setting_cb (const GValue *value,
300 					      const GVariantType *expected_type,
301 					      gpointer user_data)
302 {
303 	gdouble proportion;
304 
305 	proportion = g_value_get_double (value);
306 
307 	return g_variant_new_int32 (PROPORTION_LOWER_LIMIT + (gint32) (proportion * PROPORTION_LOWER_LIMIT));
308 }
309 
310 static void
mail_paned_view_notify_orientation_cb(GtkWidget * paned,GParamSpec * param,EShellWindow * shell_window)311 mail_paned_view_notify_orientation_cb (GtkWidget *paned,
312 				       GParamSpec *param,
313 				       EShellWindow *shell_window)
314 {
315 	GSettings *settings;
316 	const gchar *settings_key;
317 	guint32 add_flags = 0;
318 
319 	g_return_if_fail (E_IS_PANED (paned));
320 	g_return_if_fail (E_IS_SHELL_WINDOW (shell_window));
321 
322 	g_settings_unbind (paned, "proportion");
323 
324 	if (e_shell_window_is_main_instance (shell_window)) {
325 		if (gtk_orientable_get_orientation (GTK_ORIENTABLE (paned)) == GTK_ORIENTATION_HORIZONTAL)
326 			settings_key = "hpaned-size";
327 		else
328 			settings_key = "paned-size";
329 	} else {
330 		if (gtk_orientable_get_orientation (GTK_ORIENTABLE (paned)) == GTK_ORIENTATION_HORIZONTAL)
331 			settings_key = "hpaned-size-sub";
332 		else
333 			settings_key = "paned-size-sub";
334 
335 		add_flags = G_SETTINGS_BIND_GET_NO_CHANGES;
336 	}
337 
338 	settings = e_util_ref_settings ("org.gnome.evolution.mail");
339 
340 	g_settings_bind_with_mapping (settings, settings_key,
341 		paned, "proportion",
342 		G_SETTINGS_BIND_DEFAULT | add_flags,
343 		mail_paned_view_map_setting_to_proportion_cb,
344 		mail_paned_view_map_proportion_to_setting_cb,
345 		NULL, NULL);
346 
347 	g_object_unref (settings);
348 }
349 
350 static void
mail_paned_view_restore_state_cb(EShellWindow * shell_window,EShellView * shell_view,EMailPanedView * view)351 mail_paned_view_restore_state_cb (EShellWindow *shell_window,
352                                   EShellView *shell_view,
353                                   EMailPanedView *view)
354 {
355 	EMailPanedViewPrivate *priv;
356 
357 	priv = E_MAIL_PANED_VIEW (view)->priv;
358 
359 	g_signal_connect (priv->paned, "notify::orientation",
360 		G_CALLBACK (mail_paned_view_notify_orientation_cb), shell_window);
361 
362 	mail_paned_view_notify_orientation_cb (priv->paned, NULL, shell_window);
363 }
364 
365 static void
mail_paned_display_view_cb(GalViewInstance * view_instance,GalView * gal_view,EMailView * view)366 mail_paned_display_view_cb (GalViewInstance *view_instance,
367                             GalView *gal_view,
368                             EMailView *view)
369 {
370 	EMailReader *reader;
371 	EShellView *shell_view;
372 	GtkWidget *message_list;
373 
374 	shell_view = e_mail_view_get_shell_view (view);
375 	e_shell_view_set_view_instance (shell_view, view_instance);
376 
377 	reader = E_MAIL_READER (view);
378 	message_list = e_mail_reader_get_message_list (reader);
379 
380 	if (GAL_IS_VIEW_ETABLE (gal_view))
381 		gal_view_etable_attach_tree (
382 			GAL_VIEW_ETABLE (gal_view),
383 			E_TREE (message_list));
384 }
385 
386 static void
mail_paned_view_notify_group_by_threads_cb(EMailReader * reader)387 mail_paned_view_notify_group_by_threads_cb (EMailReader *reader)
388 {
389 	gboolean group_by_threads;
390 
391 	group_by_threads = e_mail_reader_get_group_by_threads (reader);
392 
393 	mail_paned_view_save_boolean (
394 		E_MAIL_VIEW (reader),
395 		STATE_KEY_GROUP_BY_THREADS, group_by_threads);
396 }
397 
398 static void
mail_paned_view_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)399 mail_paned_view_set_property (GObject *object,
400                               guint property_id,
401                               const GValue *value,
402                               GParamSpec *pspec)
403 {
404 	switch (property_id) {
405 		case PROP_FORWARD_STYLE:
406 			e_mail_reader_set_forward_style (
407 				E_MAIL_READER (object),
408 				g_value_get_enum (value));
409 			return;
410 
411 		case PROP_GROUP_BY_THREADS:
412 			e_mail_reader_set_group_by_threads (
413 				E_MAIL_READER (object),
414 				g_value_get_boolean (value));
415 			return;
416 
417 		case PROP_REPLY_STYLE:
418 			e_mail_reader_set_reply_style (
419 				E_MAIL_READER (object),
420 				g_value_get_enum (value));
421 			return;
422 
423 		case PROP_MARK_SEEN_ALWAYS:
424 			e_mail_reader_set_mark_seen_always (
425 				E_MAIL_READER (object),
426 				g_value_get_boolean (value));
427 			return;
428 
429 		case PROP_DELETE_SELECTS_PREVIOUS:
430 			e_mail_reader_set_delete_selects_previous (
431 				E_MAIL_READER (object),
432 				g_value_get_boolean (value));
433 			return;
434 	}
435 
436 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
437 }
438 
439 static void
mail_paned_view_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)440 mail_paned_view_get_property (GObject *object,
441                               guint property_id,
442                               GValue *value,
443                               GParamSpec *pspec)
444 {
445 	switch (property_id) {
446 		case PROP_FORWARD_STYLE:
447 			g_value_set_enum (
448 				value,
449 				e_mail_reader_get_forward_style (
450 				E_MAIL_READER (object)));
451 			return;
452 
453 		case PROP_GROUP_BY_THREADS:
454 			g_value_set_boolean (
455 				value,
456 				e_mail_reader_get_group_by_threads (
457 				E_MAIL_READER (object)));
458 			return;
459 
460 		case PROP_REPLY_STYLE:
461 			g_value_set_enum (
462 				value,
463 				e_mail_reader_get_reply_style (
464 				E_MAIL_READER (object)));
465 			return;
466 
467 		case PROP_MARK_SEEN_ALWAYS:
468 			g_value_set_boolean (
469 				value,
470 				e_mail_reader_get_mark_seen_always (
471 				E_MAIL_READER (object)));
472 			return;
473 
474 		case PROP_DELETE_SELECTS_PREVIOUS:
475 			g_value_set_boolean (
476 				value,
477 				e_mail_reader_get_delete_selects_previous (
478 				E_MAIL_READER (object)));
479 			return;
480 	}
481 
482 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
483 }
484 
485 static void
mail_paned_view_dispose(GObject * object)486 mail_paned_view_dispose (GObject *object)
487 {
488 	EMailPanedViewPrivate *priv;
489 
490 	priv = E_MAIL_PANED_VIEW_GET_PRIVATE (object);
491 
492 	e_mail_reader_dispose (E_MAIL_READER (object));
493 
494 	g_clear_object (&priv->paned);
495 	g_clear_object (&priv->scrolled_window);
496 
497 	if (priv->message_list != NULL) {
498 		/* It can be disconnected by EMailReader in e_mail_reader_dispose() */
499 		if (priv->message_list_built_id &&
500 		    g_signal_handler_is_connected (priv->message_list, priv->message_list_built_id)) {
501 			g_signal_handler_disconnect (priv->message_list, priv->message_list_built_id);
502 		}
503 
504 		priv->message_list_built_id = 0;
505 
506 		g_object_unref (priv->message_list);
507 		priv->message_list = NULL;
508 	}
509 
510 	g_clear_object (&priv->preview_pane);
511 	g_clear_object (&priv->view_instance);
512 
513 	g_clear_pointer (&priv->last_selected_uid, g_free);
514 
515 	priv->display = NULL;
516 
517 	/* Chain up to parent's dispose() method. */
518 	G_OBJECT_CLASS (e_mail_paned_view_parent_class)->dispose (object);
519 }
520 
521 static GtkActionGroup *
mail_paned_view_get_action_group(EMailReader * reader,EMailReaderActionGroup group)522 mail_paned_view_get_action_group (EMailReader *reader,
523                                   EMailReaderActionGroup group)
524 {
525 	EMailView *view;
526 	EShellView *shell_view;
527 	EShellWindow *shell_window;
528 	const gchar *group_name;
529 
530 	view = E_MAIL_VIEW (reader);
531 	shell_view = e_mail_view_get_shell_view (view);
532 	shell_window = e_shell_view_get_shell_window (shell_view);
533 
534 	switch (group) {
535 		case E_MAIL_READER_ACTION_GROUP_STANDARD:
536 			group_name = "mail";
537 			break;
538 		case E_MAIL_READER_ACTION_GROUP_SEARCH_FOLDERS:
539 			group_name = "search-folders";
540 			break;
541 		case E_MAIL_READER_ACTION_GROUP_LABELS:
542 			group_name = "mail-labels";
543 			break;
544 		default:
545 			g_return_val_if_reached (NULL);
546 	}
547 
548 	return e_shell_window_get_action_group (shell_window, group_name);
549 }
550 
551 static EAlertSink *
mail_paned_view_get_alert_sink(EMailReader * reader)552 mail_paned_view_get_alert_sink (EMailReader *reader)
553 {
554 	EMailView *view;
555 	EShellView *shell_view;
556 	EShellContent *shell_content;
557 
558 	view = E_MAIL_VIEW (reader);
559 	shell_view = e_mail_view_get_shell_view (view);
560 	shell_content = e_shell_view_get_shell_content (shell_view);
561 
562 	return E_ALERT_SINK (shell_content);
563 }
564 
565 static EMailBackend *
mail_paned_view_get_backend(EMailReader * reader)566 mail_paned_view_get_backend (EMailReader *reader)
567 {
568 	EMailView *view;
569 	EShellView *shell_view;
570 	EShellBackend *shell_backend;
571 
572 	view = E_MAIL_VIEW (reader);
573 	shell_view = e_mail_view_get_shell_view (view);
574 	shell_backend = e_shell_view_get_shell_backend (shell_view);
575 
576 	return E_MAIL_BACKEND (shell_backend);
577 }
578 
579 static EMailDisplay *
mail_paned_view_get_mail_display(EMailReader * reader)580 mail_paned_view_get_mail_display (EMailReader *reader)
581 {
582 	EMailPanedViewPrivate *priv;
583 
584 	priv = E_MAIL_PANED_VIEW (reader)->priv;
585 
586 	return priv->display;
587 }
588 
589 static gboolean
mail_paned_view_get_hide_deleted(EMailReader * reader)590 mail_paned_view_get_hide_deleted (EMailReader *reader)
591 {
592 	return !e_mail_view_get_show_deleted (E_MAIL_VIEW (reader));
593 }
594 
595 static GtkWidget *
mail_paned_view_get_message_list(EMailReader * reader)596 mail_paned_view_get_message_list (EMailReader *reader)
597 {
598 	EMailPanedView *paned_view;
599 
600 	paned_view = E_MAIL_PANED_VIEW (reader);
601 
602 	return paned_view->priv->message_list;
603 }
604 
605 static GtkMenu *
mail_paned_view_get_popup_menu(EMailReader * reader)606 mail_paned_view_get_popup_menu (EMailReader *reader)
607 {
608 	EMailView *view;
609 	EShellView *shell_view;
610 	EShellWindow *shell_window;
611 	GtkUIManager *ui_manager;
612 	GtkWidget *widget;
613 
614 	view = E_MAIL_VIEW (reader);
615 	shell_view = e_mail_view_get_shell_view (view);
616 	shell_window = e_shell_view_get_shell_window (shell_view);
617 
618 	ui_manager = e_shell_window_get_ui_manager (shell_window);
619 	widget = gtk_ui_manager_get_widget (ui_manager, "/mail-preview-popup");
620 
621 	return GTK_MENU (widget);
622 }
623 
624 static EPreviewPane *
mail_paned_view_get_preview_pane(EMailReader * reader)625 mail_paned_view_get_preview_pane (EMailReader *reader)
626 {
627 	EMailPanedView *paned_view;
628 
629 	paned_view = E_MAIL_PANED_VIEW (reader);
630 
631 	return E_PREVIEW_PANE (paned_view->priv->preview_pane);
632 }
633 
634 static GtkWindow *
mail_paned_view_get_window(EMailReader * reader)635 mail_paned_view_get_window (EMailReader *reader)
636 {
637 	EMailView *view;
638 	EShellView *shell_view;
639 	EShellWindow *shell_window;
640 
641 	view = E_MAIL_VIEW (reader);
642 	shell_view = e_mail_view_get_shell_view (view);
643 	shell_window = e_shell_view_get_shell_window (shell_view);
644 
645 	return GTK_WINDOW (shell_window);
646 }
647 
648 static void
mail_paned_view_set_folder(EMailReader * reader,CamelFolder * folder)649 mail_paned_view_set_folder (EMailReader *reader,
650                             CamelFolder *folder)
651 {
652 	EMailPanedViewPrivate *priv;
653 	EMailView *view;
654 	EShell *shell;
655 	EShellView *shell_view;
656 	EShellWindow *shell_window;
657 	GSettings *settings;
658 	EMailReaderInterface *default_interface;
659 	GtkWidget *message_list;
660 	GKeyFile *key_file;
661 	CamelFolder *previous_folder;
662 	gchar *folder_uri;
663 	gchar *group_name;
664 	const gchar *key;
665 	gboolean value, global_view_setting;
666 	GError *error = NULL;
667 
668 	priv = E_MAIL_PANED_VIEW_GET_PRIVATE (reader);
669 
670 	view = E_MAIL_VIEW (reader);
671 	shell_view = e_mail_view_get_shell_view (view);
672 
673 	/* Can be NULL, if the shell window was closed meanwhile */
674 	if (!shell_view)
675 		return;
676 
677 	previous_folder = e_mail_reader_ref_folder (reader);
678 	if (previous_folder == folder) {
679 		g_clear_object (&previous_folder);
680 		return;
681 	}
682 
683 	if (priv->last_selected_uid && previous_folder && folder &&
684 	    CAMEL_IS_VEE_FOLDER (previous_folder)) {
685 		CamelFolder *real_folder = NULL;
686 		gchar *message_uid = NULL;
687 
688 		em_utils_get_real_folder_and_message_uid (previous_folder, priv->last_selected_uid, &real_folder, NULL, &message_uid);
689 
690 		g_clear_pointer (&priv->last_selected_uid, g_free);
691 
692 		if (real_folder == folder && message_uid) {
693 			priv->last_selected_uid = message_uid;
694 			message_uid = NULL;
695 		}
696 
697 		g_free (message_uid);
698 		g_clear_object (&real_folder);
699 	} else {
700 		g_clear_pointer (&priv->last_selected_uid, g_free);
701 	}
702 
703 	g_clear_object (&previous_folder);
704 
705 	shell_window = e_shell_view_get_shell_window (shell_view);
706 
707 	shell = e_shell_window_get_shell (shell_window);
708 
709 	settings = e_util_ref_settings ("org.gnome.evolution.mail");
710 
711 	/* FIXME This should be an EMailReader property. */
712 	global_view_setting = g_settings_get_boolean (
713 		settings, "global-view-setting");
714 
715 	message_list = e_mail_reader_get_message_list (reader);
716 
717 	message_list_freeze (MESSAGE_LIST (message_list));
718 
719 	/* Chain up to interface's default set_folder() method. */
720 	default_interface = g_type_default_interface_peek (E_TYPE_MAIL_READER);
721 	default_interface->set_folder (reader, folder);
722 
723 	if (folder == NULL)
724 		goto exit;
725 
726 	/* Only refresh the folder if we're online. */
727 	if (e_shell_get_online (shell))
728 		e_mail_reader_refresh_folder (reader, folder);
729 
730 	priv->folder_just_set = TRUE;
731 
732 	/* Restore the folder's preview and threaded state. */
733 
734 	folder_uri = e_mail_folder_uri_from_folder (folder);
735 	key_file = e_shell_view_get_state_key_file (shell_view);
736 	group_name = g_strdup_printf ("Folder %s", folder_uri);
737 	g_free (folder_uri);
738 
739 	key = STATE_KEY_GROUP_BY_THREADS;
740 	value = g_key_file_get_boolean (key_file, global_view_setting ? STATE_GROUP_GLOBAL_FOLDER : group_name, key, &error);
741 	if (error != NULL) {
742 		g_clear_error (&error);
743 
744 		value = !global_view_setting ||
745 			g_key_file_get_boolean (key_file, STATE_GROUP_GLOBAL_FOLDER, key, &error);
746 		if (error != NULL) {
747 			g_clear_error (&error);
748 			value = TRUE;
749 		}
750 	}
751 
752 	e_mail_reader_set_group_by_threads (reader, value);
753 
754 	key = STATE_KEY_PREVIEW_VISIBLE;
755 	value = g_key_file_get_boolean (key_file, global_view_setting ? STATE_GROUP_GLOBAL_FOLDER : group_name, key, &error);
756 	if (error != NULL) {
757 		g_clear_error (&error);
758 
759 		value = !global_view_setting ||
760 			g_key_file_get_boolean (key_file, STATE_GROUP_GLOBAL_FOLDER, key, &error);
761 		if (error != NULL) {
762 			g_clear_error (&error);
763 			value = TRUE;
764 		}
765 	}
766 
767 	/* XXX This is a little confusing and needs rethought.  The
768 	 *     EShellWindow:safe-mode property blocks automatic message
769 	 *     selection, but the "safe-list" setting blocks both the
770 	 *     preview pane and automatic message selection. */
771 	if (g_settings_get_boolean (settings, "safe-list")) {
772 		g_settings_set_boolean (settings, "safe-list", FALSE);
773 		e_shell_window_set_safe_mode (shell_window, TRUE);
774 		value = FALSE;
775 	}
776 
777 	e_mail_view_set_preview_visible (E_MAIL_VIEW (reader), value);
778 
779 	g_free (group_name);
780 
781 exit:
782 	message_list_thaw (MESSAGE_LIST (message_list));
783 
784 	g_object_unref (settings);
785 }
786 
787 static guint
mail_paned_view_reader_open_selected_mail(EMailReader * reader)788 mail_paned_view_reader_open_selected_mail (EMailReader *reader)
789 {
790 	EMailPanedView *paned_view;
791 	EMailPanedViewClass *class;
792 
793 	paned_view = E_MAIL_PANED_VIEW (reader);
794 
795 	class = E_MAIL_PANED_VIEW_GET_CLASS (paned_view);
796 	g_return_val_if_fail (class->open_selected_mail != NULL, 0);
797 
798 	return class->open_selected_mail (paned_view);
799 }
800 
801 static void
mail_paned_view_constructed(GObject * object)802 mail_paned_view_constructed (GObject *object)
803 {
804 	EMailPanedViewPrivate *priv;
805 	EShellBackend *shell_backend;
806 	EShellWindow *shell_window;
807 	EShellView *shell_view;
808 	GSettings *settings;
809 	EMailReader *reader;
810 	EMailBackend *backend;
811 	EMailSession *session;
812 	EMailView *view;
813 	GtkWidget *message_list;
814 	GtkWidget *container;
815 	GtkWidget *widget, *vbox;
816 
817 	priv = E_MAIL_PANED_VIEW_GET_PRIVATE (object);
818 
819 	view = E_MAIL_VIEW (object);
820 	shell_view = e_mail_view_get_shell_view (view);
821 	shell_window = e_shell_view_get_shell_window (shell_view);
822 	shell_backend = e_shell_view_get_shell_backend (shell_view);
823 
824 	backend = E_MAIL_BACKEND (shell_backend);
825 	session = e_mail_backend_get_session (backend);
826 
827 	priv->display = g_object_new (E_TYPE_MAIL_DISPLAY,
828 		"headers-collapsable", TRUE,
829 		"remote-content", e_mail_backend_get_remote_content (backend),
830 		NULL);
831 
832 	/* FIXME This should be an EMailPanedView property, so
833 	 *       it can be configured from the settings module. */
834 
835 	settings = e_util_ref_settings ("org.gnome.evolution.mail");
836 
837 	g_settings_bind (
838 		settings, "headers-collapsed",
839 		priv->display, "headers-collapsed",
840 		G_SETTINGS_BIND_DEFAULT);
841 
842 	g_object_unref (settings);
843 
844 	/* Build content widgets. */
845 
846 	container = GTK_WIDGET (object);
847 
848 	widget = e_paned_new (GTK_ORIENTATION_VERTICAL);
849 	e_paned_set_fixed_resize (E_PANED (widget), FALSE);
850 	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
851 	priv->paned = g_object_ref (widget);
852 	gtk_widget_show (widget);
853 
854 	e_binding_bind_property (
855 		object, "orientation",
856 		widget, "orientation",
857 		G_BINDING_SYNC_CREATE);
858 
859 	container = priv->paned;
860 
861 	widget = gtk_scrolled_window_new (NULL, NULL);
862 	gtk_scrolled_window_set_policy (
863 		GTK_SCROLLED_WINDOW (widget),
864 		GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
865 	gtk_paned_pack1 (GTK_PANED (container), widget, TRUE, FALSE);
866 	priv->scrolled_window = g_object_ref (widget);
867 	gtk_widget_show (widget);
868 
869 	container = widget;
870 
871 	widget = message_list_new (session);
872 	gtk_container_add (GTK_CONTAINER (container), widget);
873 	priv->message_list = g_object_ref (widget);
874 	gtk_widget_show (widget);
875 
876 	priv->message_list_built_id = g_signal_connect_swapped (
877 		priv->message_list, "message-list-built",
878 		G_CALLBACK (mail_paned_view_message_list_built_cb),
879 		object);
880 
881 	container = priv->paned;
882 
883 	vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
884 	widget = e_preview_pane_new (E_WEB_VIEW (priv->display));
885 
886 	gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0);
887 	gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (e_mail_display_get_attachment_view (priv->display)), FALSE, FALSE, 0);
888 
889 	gtk_paned_pack2 (GTK_PANED (container), vbox, FALSE, FALSE);
890 	priv->preview_pane = g_object_ref (widget);
891 	gtk_widget_show (GTK_WIDGET (priv->display));
892 	gtk_widget_show (widget);
893 
894 	e_binding_bind_property (
895 		object, "preview-visible",
896 		widget, "visible",
897 		G_BINDING_SYNC_CREATE);
898 
899 	e_binding_bind_property (
900 		object, "preview-visible",
901 		vbox, "visible",
902 		G_BINDING_SYNC_CREATE);
903 
904 	/* Load the view instance. */
905 
906 	e_mail_view_update_view_instance (E_MAIL_VIEW (object));
907 
908 	/* Message list customizations. */
909 
910 	e_mail_reader_init (E_MAIL_READER (object), FALSE, TRUE);
911 
912 	reader = E_MAIL_READER (object);
913 	message_list = e_mail_reader_get_message_list (reader);
914 
915 	g_signal_connect_swapped (
916 		message_list, "message-selected",
917 		G_CALLBACK (mail_paned_view_message_selected_cb),
918 		object);
919 
920 	/* Restore pane positions from the last session once
921 	 * the shell view is fully initialized and visible. */
922 	g_signal_connect (
923 		shell_window, "shell-view-created::mail",
924 		G_CALLBACK (mail_paned_view_restore_state_cb),
925 		object);
926 
927 	/* Do this after creating the message list.  Our
928 	 * set_preview_visible() method relies on it. */
929 	e_mail_view_set_preview_visible (view, TRUE);
930 
931 	e_extensible_load_extensions (E_EXTENSIBLE (object));
932 
933 	/* Chain up to parent's constructed() method. */
934 	G_OBJECT_CLASS (e_mail_paned_view_parent_class)->constructed (object);
935 }
936 
937 static void
mail_paned_view_set_search_strings(EMailView * view,GSList * search_strings)938 mail_paned_view_set_search_strings (EMailView *view,
939                                     GSList *search_strings)
940 {
941 	EMailDisplay *display;
942 	EWebView *web_view;
943 	EMailReader *reader;
944 
945 	reader = E_MAIL_READER (view);
946 	display = e_mail_reader_get_mail_display (reader);
947 	if (!display)
948 		return;
949 
950 	web_view = E_WEB_VIEW (display);
951 
952 	e_web_view_clear_highlights (web_view);
953 
954 	while (search_strings != NULL) {
955 		e_web_view_add_highlight (web_view, search_strings->data);
956 		search_strings = g_slist_next (search_strings);
957 	}
958 }
959 
960 static GalViewInstance *
mail_paned_view_get_view_instance(EMailView * view)961 mail_paned_view_get_view_instance (EMailView *view)
962 {
963 	EMailPanedView *paned_view;
964 
965 	paned_view = E_MAIL_PANED_VIEW (view);
966 
967 	return paned_view->priv->view_instance;
968 }
969 
970 static gchar *
empv_create_view_id(CamelFolder * folder)971 empv_create_view_id (CamelFolder *folder)
972 {
973 	GChecksum *checksum;
974 	gchar *res, *folder_uri;
975 
976 	g_return_val_if_fail (folder != NULL, NULL);
977 
978 	folder_uri = e_mail_folder_uri_from_folder (folder);
979 	g_return_val_if_fail (folder_uri != NULL, NULL);
980 
981 	/* to be able to migrate previously saved views */
982 	e_util_make_safe_filename (folder_uri);
983 
984 	/* use MD5 checksum of the folder URI, to not depend on its length */
985 	checksum = g_checksum_new (G_CHECKSUM_MD5);
986 	g_checksum_update (checksum, (const guchar *) folder_uri, -1);
987 
988 	res = g_strdup (g_checksum_get_string (checksum));
989 
990 	g_checksum_free (checksum);
991 	g_free (folder_uri);
992 
993 	return res;
994 }
995 
996 static gboolean
empv_folder_or_parent_is_outgoing(MailFolderCache * folder_cache,CamelStore * store,const gchar * fullname)997 empv_folder_or_parent_is_outgoing (MailFolderCache *folder_cache,
998 				   CamelStore *store,
999 				   const gchar *fullname)
1000 {
1001 	CamelFolderInfoFlags info_flags;
1002 	gchar *path, *dash;
1003 	gboolean res = FALSE;
1004 
1005 	g_return_val_if_fail (MAIL_IS_FOLDER_CACHE (folder_cache), FALSE);
1006 	g_return_val_if_fail (CAMEL_IS_STORE (store), FALSE);
1007 	g_return_val_if_fail (fullname != NULL, FALSE);
1008 
1009 	if (!mail_folder_cache_get_folder_info_flags (folder_cache, store, fullname, &info_flags))
1010 		info_flags = 0;
1011 
1012 	if ((info_flags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_OUTBOX ||
1013 	    (info_flags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_SENT)
1014 		return TRUE;
1015 
1016 	dash = strrchr (fullname, '/');
1017 	if (!dash)
1018 		return FALSE;
1019 
1020 	path = g_strdup (fullname);
1021 
1022 	while (path && *path) {
1023 		dash = strrchr (path, '/');
1024 		if (!dash)
1025 			break;
1026 
1027 		*dash = '\0';
1028 
1029 		if (!mail_folder_cache_get_folder_info_flags (folder_cache, store, path, &info_flags))
1030 			continue;
1031 
1032 		if ((info_flags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_OUTBOX ||
1033 		    (info_flags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_SENT) {
1034 			res = TRUE;
1035 			break;
1036 		}
1037 	}
1038 
1039 	g_free (path);
1040 
1041 	return res;
1042 }
1043 
1044 static void
mail_paned_view_update_view_instance(EMailView * view)1045 mail_paned_view_update_view_instance (EMailView *view)
1046 {
1047 	EMailPanedViewPrivate *priv;
1048 	EMailReader *reader;
1049 	EShell *shell;
1050 	EShellView *shell_view;
1051 	EShellWindow *shell_window;
1052 	EShellViewClass *shell_view_class;
1053 	ESourceRegistry *registry;
1054 	GalViewCollection *view_collection;
1055 	GalViewInstance *view_instance;
1056 	MailFolderCache *folder_cache;
1057 	CamelFolder *folder;
1058 	GtkOrientable *orientable;
1059 	GtkOrientation orientation;
1060 	GSettings *settings;
1061 	gboolean outgoing_folder;
1062 	gboolean show_vertical_view;
1063 	gboolean global_view_setting;
1064 	gchar *view_id;
1065 
1066 	priv = E_MAIL_PANED_VIEW_GET_PRIVATE (view);
1067 
1068 	shell_view = e_mail_view_get_shell_view (view);
1069 	shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view);
1070 	view_collection = shell_view_class->view_collection;
1071 
1072 	shell_window = e_shell_view_get_shell_window (shell_view);
1073 	shell = e_shell_window_get_shell (shell_window);
1074 	registry = e_shell_get_registry (shell);
1075 
1076 	reader = E_MAIL_READER (view);
1077 	folder = e_mail_reader_ref_folder (reader);
1078 
1079 	/* If no folder is selected, return silently. */
1080 	if (folder == NULL)
1081 		return;
1082 
1083 	g_clear_object (&priv->view_instance);
1084 
1085 	view_id = empv_create_view_id (folder);
1086 	e_util_make_safe_filename (view_id);
1087 
1088 	folder_cache = e_mail_session_get_folder_cache (e_mail_backend_get_session (e_mail_reader_get_backend (reader)));
1089 
1090 	outgoing_folder =
1091 		empv_folder_or_parent_is_outgoing (folder_cache, camel_folder_get_parent_store (folder), camel_folder_get_full_name (folder)) ||
1092 		em_utils_folder_is_drafts (registry, folder) ||
1093 		em_utils_folder_is_outbox (registry, folder) ||
1094 		em_utils_folder_is_sent (registry, folder);
1095 
1096 	settings = e_util_ref_settings ("org.gnome.evolution.mail");
1097 	global_view_setting = g_settings_get_boolean (
1098 		settings, "global-view-setting");
1099 	g_object_unref (settings);
1100 
1101 	if (global_view_setting) {
1102 		if (outgoing_folder) {
1103 			view_instance = e_shell_view_new_view_instance (
1104 				shell_view, "global_view_sent_setting");
1105 		} else {
1106 			view_instance = e_shell_view_new_view_instance (
1107 				shell_view, "global_view_setting");
1108 		}
1109 	} else {
1110 		view_instance = e_shell_view_new_view_instance (
1111 			shell_view, view_id);
1112 	}
1113 
1114 	priv->view_instance = g_object_ref (view_instance);
1115 
1116 	orientable = GTK_ORIENTABLE (view);
1117 	orientation = gtk_orientable_get_orientation (orientable);
1118 	show_vertical_view =
1119 		!global_view_setting &&
1120 		(orientation == GTK_ORIENTATION_HORIZONTAL);
1121 
1122 	if (show_vertical_view) {
1123 		const gchar *user_directory;
1124 		gchar *filename;
1125 
1126 		/* Force the view instance into vertical view. */
1127 
1128 		g_free (view_instance->custom_filename);
1129 		g_free (view_instance->current_view_filename);
1130 
1131 		user_directory = gal_view_collection_get_user_directory (
1132 			view_collection);
1133 
1134 		filename = g_strdup_printf (
1135 			"custom_wide_view-%s.xml", view_id);
1136 		view_instance->custom_filename =
1137 			g_build_filename (user_directory, filename, NULL);
1138 		g_free (filename);
1139 
1140 		filename = g_strdup_printf (
1141 			"current_wide_view-%s.xml", view_id);
1142 		view_instance->current_view_filename =
1143 			g_build_filename (user_directory, filename, NULL);
1144 		g_free (filename);
1145 	}
1146 
1147 	g_free (view_id);
1148 
1149 	if (outgoing_folder) {
1150 		if (show_vertical_view)
1151 			gal_view_instance_set_default_view (
1152 				view_instance, "Wide_View_Sent");
1153 		else
1154 			gal_view_instance_set_default_view (
1155 				view_instance, "As_Sent_Folder");
1156 	} else if (show_vertical_view) {
1157 		gal_view_instance_set_default_view (
1158 			view_instance, "Wide_View_Normal");
1159 	}
1160 
1161 	gal_view_instance_load (view_instance);
1162 
1163 	if (!gal_view_instance_exists (view_instance)) {
1164 		gchar *state_filename;
1165 
1166 		state_filename = mail_config_folder_to_cachename (
1167 			folder, "et-header-");
1168 
1169 		if (g_file_test (state_filename, G_FILE_TEST_IS_REGULAR)) {
1170 			GalView *gal_view;
1171 
1172 			gal_view = gal_view_etable_new ("");
1173 
1174 			/* XXX This only stashes the filename in the view.
1175 			 *     The state file is not actually loaded until
1176 			 *     the MessageList is attached to the view. */
1177 			gal_view_load (gal_view, state_filename);
1178 
1179 			gal_view_instance_set_custom_view (
1180 				view_instance, gal_view);
1181 
1182 			g_object_unref (gal_view);
1183 		}
1184 
1185 		g_free (state_filename);
1186 	}
1187 
1188 	g_signal_connect (
1189 		view_instance, "display-view",
1190 		G_CALLBACK (mail_paned_display_view_cb), view);
1191 
1192 	mail_paned_display_view_cb (
1193 		view_instance,
1194 		gal_view_instance_get_current_view (view_instance),
1195 		view);
1196 
1197 	view_id = gal_view_instance_get_current_view_id (view_instance);
1198 	e_shell_view_set_view_id (shell_view, view_id);
1199 	g_free (view_id);
1200 
1201 	g_object_unref (view_instance);
1202 
1203 	g_clear_object (&folder);
1204 }
1205 
1206 static void
mail_paned_view_set_preview_visible(EMailView * view,gboolean preview_visible)1207 mail_paned_view_set_preview_visible (EMailView *view,
1208                                      gboolean preview_visible)
1209 {
1210 	EMailViewClass *parent_class;
1211 
1212 	/* If we're showing the preview, tell EMailReader to reload the
1213 	 * selected message.  This should force it to download the full
1214 	 * message if necessary, so we don't get an empty preview. */
1215 	if (preview_visible) {
1216 		EMailReader *reader;
1217 		GtkWidget *message_list;
1218 		const gchar *cursor_uid;
1219 
1220 		reader = E_MAIL_READER (view);
1221 		message_list = e_mail_reader_get_message_list (reader);
1222 		cursor_uid = MESSAGE_LIST (message_list)->cursor_uid;
1223 
1224 		if (cursor_uid != NULL)
1225 			e_mail_reader_set_message (reader, cursor_uid);
1226 	}
1227 
1228 	mail_paned_view_save_boolean (
1229 		E_MAIL_VIEW (view),
1230 		STATE_KEY_PREVIEW_VISIBLE, preview_visible);
1231 
1232 	/* Chain up to parent's set_preview_visible() method. */
1233 	parent_class = E_MAIL_VIEW_CLASS (e_mail_paned_view_parent_class);
1234 	parent_class->set_preview_visible (view, preview_visible);
1235 }
1236 
1237 static guint
mail_paned_view_open_selected_mail(EMailPanedView * view)1238 mail_paned_view_open_selected_mail (EMailPanedView *view)
1239 {
1240 	return e_mail_reader_open_selected (E_MAIL_READER (view));
1241 }
1242 
1243 static void
e_mail_paned_view_class_init(EMailPanedViewClass * class)1244 e_mail_paned_view_class_init (EMailPanedViewClass *class)
1245 {
1246 	GObjectClass *object_class;
1247 	EMailViewClass *mail_view_class;
1248 
1249 	g_type_class_add_private (class, sizeof (EMailPanedViewPrivate));
1250 
1251 	object_class = G_OBJECT_CLASS (class);
1252 	object_class->dispose = mail_paned_view_dispose;
1253 	object_class->constructed = mail_paned_view_constructed;
1254 	object_class->set_property = mail_paned_view_set_property;
1255 	object_class->get_property = mail_paned_view_get_property;
1256 
1257 	mail_view_class = E_MAIL_VIEW_CLASS (class);
1258 	mail_view_class->set_search_strings = mail_paned_view_set_search_strings;
1259 	mail_view_class->get_view_instance = mail_paned_view_get_view_instance;
1260 	mail_view_class->update_view_instance = mail_paned_view_update_view_instance;
1261 
1262 	mail_view_class->set_preview_visible = mail_paned_view_set_preview_visible;
1263 
1264 	class->open_selected_mail = mail_paned_view_open_selected_mail;
1265 
1266 	/* Inherited from EMailReader */
1267 	g_object_class_override_property (
1268 		object_class,
1269 		PROP_FORWARD_STYLE,
1270 		"forward-style");
1271 
1272 	/* Inherited from EMailReader */
1273 	g_object_class_override_property (
1274 		object_class,
1275 		PROP_GROUP_BY_THREADS,
1276 		"group-by-threads");
1277 
1278 	/* Inherited from EMailReader */
1279 	g_object_class_override_property (
1280 		object_class,
1281 		PROP_REPLY_STYLE,
1282 		"reply-style");
1283 
1284 	/* Inherited from EMailReader */
1285 	g_object_class_override_property (
1286 		object_class,
1287 		PROP_MARK_SEEN_ALWAYS,
1288 		"mark-seen-always");
1289 
1290 	/* Inherited from EMailReader */
1291 	g_object_class_override_property (
1292 		object_class,
1293 		PROP_DELETE_SELECTS_PREVIOUS,
1294 		"delete-selects-previous");
1295 }
1296 
1297 static void
e_mail_paned_view_reader_init(EMailReaderInterface * iface)1298 e_mail_paned_view_reader_init (EMailReaderInterface *iface)
1299 {
1300 	iface->get_action_group = mail_paned_view_get_action_group;
1301 	iface->get_alert_sink = mail_paned_view_get_alert_sink;
1302 	iface->get_backend = mail_paned_view_get_backend;
1303 	iface->get_mail_display = mail_paned_view_get_mail_display;
1304 	iface->get_hide_deleted = mail_paned_view_get_hide_deleted;
1305 	iface->get_message_list = mail_paned_view_get_message_list;
1306 	iface->get_popup_menu = mail_paned_view_get_popup_menu;
1307 	iface->get_preview_pane = mail_paned_view_get_preview_pane;
1308 	iface->get_window = mail_paned_view_get_window;
1309 	iface->set_folder = mail_paned_view_set_folder;
1310 	iface->open_selected_mail = mail_paned_view_reader_open_selected_mail;
1311 }
1312 
1313 static void
e_mail_paned_view_init(EMailPanedView * view)1314 e_mail_paned_view_init (EMailPanedView *view)
1315 {
1316 	view->priv = E_MAIL_PANED_VIEW_GET_PRIVATE (view);
1317 
1318 	e_signal_connect_notify (
1319 		view, "notify::group-by-threads",
1320 		G_CALLBACK (mail_paned_view_notify_group_by_threads_cb),
1321 		NULL);
1322 }
1323 
1324 GtkWidget *
e_mail_paned_view_new(EShellView * shell_view)1325 e_mail_paned_view_new (EShellView *shell_view)
1326 {
1327 	g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL);
1328 
1329 	return g_object_new (
1330 		E_TYPE_MAIL_PANED_VIEW,
1331 		"shell-view", shell_view, NULL);
1332 }
1333 
1334 void
e_mail_paned_view_hide_message_list_pane(EMailPanedView * view,gboolean visible)1335 e_mail_paned_view_hide_message_list_pane (EMailPanedView *view,
1336                                           gboolean visible)
1337 {
1338 	g_return_if_fail (E_IS_MAIL_PANED_VIEW (view));
1339 
1340 	if (visible)
1341 		gtk_widget_show (view->priv->scrolled_window);
1342 	else
1343 		gtk_widget_hide (view->priv->scrolled_window);
1344 }
1345 
1346 GtkWidget *
e_mail_paned_view_get_preview(EMailPanedView * view)1347 e_mail_paned_view_get_preview (EMailPanedView *view)
1348 {
1349 	g_return_val_if_fail (E_IS_MAIL_PANED_VIEW (view), NULL);
1350 
1351 	return GTK_WIDGET (mail_paned_view_get_mail_display (E_MAIL_READER (view)));
1352 }
1353 
1354