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