1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include <glib/gi18n.h>
31 #include <tny-account-store.h>
32 #include <tny-simple-list.h>
33 #include <tny-header.h>
34 #include "modest-platform.h"
35 #include <modest-tny-msg.h>
36 #include <modest-msg-view-window.h>
37 #include <modest-main-window-ui.h>
38 #include <modest-widget-memory.h>
39 #include <modest-runtime.h>
40 #include <modest-window-priv.h>
41 #include <modest-tny-folder.h>
42 #include <modest-text-utils.h>
43 #include "modest-hildon-includes.h"
44 #include <gtkhtml/gtkhtml-search.h>
45 #include <gdk/gdkkeysyms.h>
47 static void modest_msg_view_window_class_init (ModestMsgViewWindowClass *klass);
48 static void modest_msg_view_window_init (ModestMsgViewWindow *obj);
49 static void modest_msg_view_window_finalize (GObject *obj);
50 static void modest_msg_view_window_toggle_find_toolbar (GtkToggleAction *obj,
52 static void modest_msg_view_window_find_toolbar_close (GtkWidget *widget,
53 ModestMsgViewWindow *obj);
54 static void modest_msg_view_window_find_toolbar_search (GtkWidget *widget,
55 ModestMsgViewWindow *obj);
57 static void modest_msg_view_window_set_zoom (ModestWindow *window,
59 static gdouble modest_msg_view_window_get_zoom (ModestWindow *window);
60 static gboolean modest_msg_view_window_zoom_minus (ModestWindow *window);
61 static gboolean modest_msg_view_window_zoom_plus (ModestWindow *window);
62 static gboolean modest_msg_view_window_key_release_event (GtkWidget *window,
65 static gboolean modest_msg_view_window_window_state_event (GtkWidget *widget,
66 GdkEventWindowState *event,
68 static void modest_msg_view_window_scroll_up (ModestWindow *window);
69 static void modest_msg_view_window_scroll_down (ModestWindow *window);
70 static gboolean modest_msg_view_window_is_last_message (ModestMsgViewWindow *window);
71 static gboolean modest_msg_view_window_is_first_message (ModestMsgViewWindow *window);
72 static TnyFolderType modest_msg_view_window_get_folder_type (ModestMsgViewWindow *window);
73 static void modest_msg_view_window_update_dimmed (ModestMsgViewWindow *window);
74 static void modest_msg_view_window_update_priority (ModestMsgViewWindow *window);
76 static void modest_msg_view_window_show_toolbar (ModestWindow *window,
77 gboolean show_toolbar);
79 static void modest_msg_view_window_clipboard_owner_change (GtkClipboard *clipboard,
81 ModestMsgViewWindow *window);
91 static const GtkToggleActionEntry msg_view_toggle_action_entries [] = {
92 { "FindInMessage", GTK_STOCK_FIND, N_("qgn_toolb_gene_find"), NULL, NULL, G_CALLBACK (modest_msg_view_window_toggle_find_toolbar), FALSE },
95 static const GtkRadioActionEntry msg_view_zoom_action_entries [] = {
96 { "Zoom50", NULL, N_("mcen_me_viewer_50"), NULL, NULL, 50 },
97 { "Zoom80", NULL, N_("mcen_me_viewer_80"), NULL, NULL, 80 },
98 { "Zoom100", NULL, N_("mcen_me_viewer_100"), NULL, NULL, 100 },
99 { "Zoom120", NULL, N_("mcen_me_viewer_120"), NULL, NULL, 120 },
100 { "Zoom150", NULL, N_("mcen_me_viewer_150"), NULL, NULL, 150 },
101 { "Zoom200", NULL, N_("mcen_me_viewer_200"), NULL, NULL, 200 }
104 typedef struct _ModestMsgViewWindowPrivate ModestMsgViewWindowPrivate;
105 struct _ModestMsgViewWindowPrivate {
108 GtkWidget *main_scroll;
109 GtkWidget *find_toolbar;
112 GtkTreeModel *header_model;
115 guint clipboard_change_handler;
118 #define MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
119 MODEST_TYPE_MSG_VIEW_WINDOW, \
120 ModestMsgViewWindowPrivate))
122 static GtkWindowClass *parent_class = NULL;
124 /* uncomment the following if you have defined any signals */
125 /* static guint signals[LAST_SIGNAL] = {0}; */
128 modest_msg_view_window_get_type (void)
130 static GType my_type = 0;
132 static const GTypeInfo my_info = {
133 sizeof(ModestMsgViewWindowClass),
134 NULL, /* base init */
135 NULL, /* base finalize */
136 (GClassInitFunc) modest_msg_view_window_class_init,
137 NULL, /* class finalize */
138 NULL, /* class data */
139 sizeof(ModestMsgViewWindow),
141 (GInstanceInitFunc) modest_msg_view_window_init,
144 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
145 "ModestMsgViewWindow",
152 modest_msg_view_window_class_init (ModestMsgViewWindowClass *klass)
154 GObjectClass *gobject_class;
155 ModestWindowClass *modest_window_class;
156 gobject_class = (GObjectClass*) klass;
157 modest_window_class = (ModestWindowClass *) klass;
159 parent_class = g_type_class_peek_parent (klass);
160 gobject_class->finalize = modest_msg_view_window_finalize;
162 modest_window_class->set_zoom_func = modest_msg_view_window_set_zoom;
163 modest_window_class->get_zoom_func = modest_msg_view_window_get_zoom;
164 modest_window_class->zoom_minus_func = modest_msg_view_window_zoom_minus;
165 modest_window_class->zoom_plus_func = modest_msg_view_window_zoom_plus;
166 modest_window_class->show_toolbar_func = modest_msg_view_window_show_toolbar;
168 g_type_class_add_private (gobject_class, sizeof(ModestMsgViewWindowPrivate));
172 modest_msg_view_window_init (ModestMsgViewWindow *obj)
174 ModestMsgViewWindowPrivate *priv;
175 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(obj);
177 priv->msg_view = NULL;
178 priv->header_model = NULL;
179 priv->clipboard_change_handler = 0;
183 save_settings (ModestMsgViewWindow *self)
185 modest_widget_memory_save (modest_runtime_get_conf (),
186 G_OBJECT(self), "modest-msg-view-window");
191 restore_settings (ModestMsgViewWindow *self)
193 modest_widget_memory_restore (modest_runtime_get_conf (),
194 G_OBJECT(self), "modest-msg-view-window");
200 menubar_to_menu (GtkUIManager *ui_manager)
202 GtkWidget *main_menu;
206 /* Create new main menu */
207 main_menu = gtk_menu_new();
209 /* Get the menubar from the UI manager */
210 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
212 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
216 menu = GTK_WIDGET (iter->data);
217 gtk_widget_reparent(menu, main_menu);
219 iter = g_list_next (iter);
225 init_window (ModestMsgViewWindow *obj, TnyMsg *msg)
227 GtkWidget *main_vbox;
228 ModestMsgViewWindowPrivate *priv;
229 ModestWindowPrivate *parent_priv;
231 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(obj);
232 parent_priv = MODEST_WINDOW_GET_PRIVATE(obj);
234 priv->msg_view = modest_msg_view_new (msg);
235 modest_msg_view_set_shadow_type (MODEST_MSG_VIEW (priv->msg_view), GTK_SHADOW_NONE);
236 main_vbox = gtk_vbox_new (FALSE, 6);
239 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
240 gtk_widget_show_all (GTK_WIDGET(parent_priv->menubar));
241 hildon_window_set_menu (HILDON_WINDOW(obj), GTK_MENU(parent_priv->menubar));
243 priv->main_scroll = gtk_scrolled_window_new (NULL, NULL);
244 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->main_scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
245 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->main_scroll), GTK_SHADOW_NONE);
247 gtk_container_add (GTK_CONTAINER (priv->main_scroll), priv->msg_view);
248 gtk_box_pack_start (GTK_BOX(main_vbox), priv->main_scroll, TRUE, TRUE, 0);
249 gtk_container_add (GTK_CONTAINER(obj), main_vbox);
251 priv->find_toolbar = hildon_find_toolbar_new (NULL);
252 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
253 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_view_window_find_toolbar_close), obj);
254 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_view_window_find_toolbar_search), obj);
256 priv->clipboard_change_handler = g_signal_connect (G_OBJECT (gtk_clipboard_get (GDK_SELECTION_PRIMARY)), "owner-change", G_CALLBACK (modest_msg_view_window_clipboard_owner_change), obj);
257 modest_msg_view_window_clipboard_owner_change (gtk_clipboard_get (GDK_SELECTION_PRIMARY), NULL, obj);
258 gtk_widget_show_all (GTK_WIDGET(main_vbox));
259 gtk_box_pack_end (GTK_BOX (main_vbox), priv->find_toolbar, FALSE, FALSE, 0);
264 modest_msg_view_window_finalize (GObject *obj)
266 ModestMsgViewWindowPrivate *priv;
268 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (obj);
269 if (priv->header_model != NULL) {
270 g_object_unref (priv->header_model);
271 priv->header_model = NULL;
273 if (priv->clipboard_change_handler > 0) {
274 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY), priv->clipboard_change_handler);
275 priv->clipboard_change_handler = 0;
278 G_OBJECT_CLASS(parent_class)->finalize (obj);
284 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestMsgViewWindow *self)
286 save_settings (self);
291 modest_msg_view_window_new_with_header_model (TnyMsg *msg, const gchar *account_name,
292 GtkTreeModel *model, GtkTreeIter iter)
294 ModestMsgViewWindow *window = NULL;
295 ModestMsgViewWindowPrivate *priv = NULL;
297 window = MODEST_MSG_VIEW_WINDOW(modest_msg_view_window_new (msg, account_name));
298 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), NULL);
300 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
302 g_object_ref (model);
303 priv->header_model = model;
306 modest_msg_view_window_update_priority (window);
308 modest_msg_view_window_update_dimmed (window);
310 return MODEST_WINDOW(window);
315 modest_msg_view_window_new (TnyMsg *msg, const gchar *account_name)
318 ModestMsgViewWindowPrivate *priv;
319 ModestWindowPrivate *parent_priv;
320 GtkActionGroup *action_group;
321 GError *error = NULL;
322 GdkPixbuf *window_icon = NULL;
324 g_return_val_if_fail (msg, NULL);
326 obj = g_object_new(MODEST_TYPE_MSG_VIEW_WINDOW, NULL);
327 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(obj);
328 parent_priv = MODEST_WINDOW_GET_PRIVATE(obj);
330 parent_priv->ui_manager = gtk_ui_manager_new();
331 action_group = gtk_action_group_new ("ModestMsgViewWindowActions");
332 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
334 /* Add common actions */
335 gtk_action_group_add_actions (action_group,
336 modest_action_entries,
337 G_N_ELEMENTS (modest_action_entries),
339 gtk_action_group_add_toggle_actions (action_group,
340 modest_toggle_action_entries,
341 G_N_ELEMENTS (modest_toggle_action_entries),
343 gtk_action_group_add_toggle_actions (action_group,
344 msg_view_toggle_action_entries,
345 G_N_ELEMENTS (msg_view_toggle_action_entries),
347 gtk_action_group_add_radio_actions (action_group,
348 msg_view_zoom_action_entries,
349 G_N_ELEMENTS (msg_view_zoom_action_entries),
351 G_CALLBACK (modest_ui_actions_on_change_zoom),
354 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
355 g_object_unref (action_group);
357 /* Load the UI definition */
358 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-view-window-ui.xml",
361 g_printerr ("modest: could not merge modest-msg-view-window-ui.xml: %s\n", error->message);
362 g_error_free (error);
367 /* Add accelerators */
368 gtk_window_add_accel_group (GTK_WINDOW (obj),
369 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
372 init_window (MODEST_MSG_VIEW_WINDOW(obj), msg);
373 restore_settings (MODEST_MSG_VIEW_WINDOW(obj));
375 g_signal_connect (G_OBJECT(obj), "delete-event", G_CALLBACK(on_delete_event), obj);
377 g_signal_connect (G_OBJECT(priv->msg_view), "link_clicked",
378 G_CALLBACK (modest_ui_actions_on_msg_link_clicked), obj);
379 g_signal_connect (G_OBJECT(priv->msg_view), "link_hover",
380 G_CALLBACK (modest_ui_actions_on_msg_link_hover), obj);
381 g_signal_connect (G_OBJECT(priv->msg_view), "attachment_clicked",
382 G_CALLBACK (modest_ui_actions_on_msg_attachment_clicked), obj);
383 g_signal_connect (G_OBJECT(priv->msg_view), "recpt_activated",
384 G_CALLBACK (modest_ui_actions_on_msg_recpt_activated), obj);
385 g_signal_connect (G_OBJECT(priv->msg_view), "link_contextual",
386 G_CALLBACK (modest_ui_actions_on_msg_link_contextual), obj);
388 g_signal_connect (G_OBJECT (obj), "key-release-event",
389 G_CALLBACK (modest_msg_view_window_key_release_event),
392 g_signal_connect (G_OBJECT (obj), "window-state-event",
393 G_CALLBACK (modest_msg_view_window_window_state_event),
396 modest_window_set_active_account (MODEST_WINDOW(obj), account_name);
398 priv->last_search = NULL;
400 modest_msg_view_window_update_dimmed (MODEST_MSG_VIEW_WINDOW (obj));
402 /* Set window icon */
403 window_icon = modest_platform_get_icon (MODEST_APP_MSG_VIEW_ICON);
404 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
406 gtk_widget_grab_focus (priv->msg_view);
408 return MODEST_WINDOW(obj);
414 modest_msg_view_window_get_message (ModestMsgViewWindow *self)
416 ModestMsgView *msg_view;
417 ModestMsgViewWindowPrivate *priv;
419 g_return_val_if_fail (self, NULL);
421 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
423 msg_view = MODEST_MSG_VIEW (priv->msg_view);
425 return modest_msg_view_get_message (msg_view);
429 modest_msg_view_window_get_message_uid (ModestMsgViewWindow *self)
433 const gchar *retval = NULL;
435 msg = modest_msg_view_window_get_message (self);
440 header = tny_msg_get_header (msg);
442 retval = tny_header_get_uid (header);
443 g_object_unref (header);
449 modest_msg_view_window_toggle_find_toolbar (GtkToggleAction *toggle,
452 ModestMsgViewWindow *window = MODEST_MSG_VIEW_WINDOW (data);
453 ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
455 if (gtk_toggle_action_get_active (toggle)) {
456 gtk_widget_show (priv->find_toolbar);
458 gtk_widget_hide (priv->find_toolbar);
465 modest_msg_view_window_find_toolbar_close (GtkWidget *widget,
466 ModestMsgViewWindow *obj)
468 GtkToggleAction *toggle;
469 ModestWindowPrivate *parent_priv;
470 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
472 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/FindInMessage"));
473 gtk_toggle_action_set_active (toggle, FALSE);
477 modest_msg_view_window_find_toolbar_search (GtkWidget *widget,
478 ModestMsgViewWindow *obj)
480 gchar *current_search;
481 ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (obj);
483 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
485 if ((current_search == NULL) && (strcmp (current_search, "") == 0)) {
486 g_free (current_search);
490 if ((priv->last_search == NULL) || (strcmp (priv->last_search, current_search) != 0)) {
492 g_free (priv->last_search);
493 priv->last_search = g_strdup (current_search);
494 result = modest_msg_view_search (MODEST_MSG_VIEW (priv->msg_view),
497 modest_msg_view_search_next (MODEST_MSG_VIEW (priv->msg_view));
500 g_free (current_search);
505 modest_msg_view_window_set_zoom (ModestWindow *window,
508 ModestMsgViewWindowPrivate *priv;
510 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
512 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
513 modest_msg_view_set_zoom (MODEST_MSG_VIEW (priv->msg_view), zoom);
517 modest_msg_view_window_get_zoom (ModestWindow *window)
519 ModestMsgViewWindowPrivate *priv;
521 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), 1.0);
523 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
524 return modest_msg_view_get_zoom (MODEST_MSG_VIEW (priv->msg_view));
528 modest_msg_view_window_zoom_plus (ModestWindow *window)
530 ModestWindowPrivate *parent_priv;
531 GtkRadioAction *zoom_radio_action;
532 GSList *group, *node;
534 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
535 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
536 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
538 group = gtk_radio_action_get_group (zoom_radio_action);
540 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
541 hildon_banner_show_information (NULL, NULL, _("mcen_ib_max_zoom_level"));
545 for (node = group; node != NULL; node = g_slist_next (node)) {
546 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
547 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
555 modest_msg_view_window_zoom_minus (ModestWindow *window)
557 ModestWindowPrivate *parent_priv;
558 GtkRadioAction *zoom_radio_action;
559 GSList *group, *node;
561 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
562 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
563 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
565 group = gtk_radio_action_get_group (zoom_radio_action);
567 for (node = group; node != NULL; node = g_slist_next (node)) {
568 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
569 if (node->next != NULL) {
570 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
573 hildon_banner_show_information (NULL, NULL, _("mcen_ib_min_zoom_level"));
583 modest_msg_view_window_key_release_event (GtkWidget *window,
587 if (event->type == GDK_KEY_RELEASE) {
588 switch (event->keyval) {
590 modest_msg_view_window_scroll_up (MODEST_WINDOW (window));
594 modest_msg_view_window_scroll_down (MODEST_WINDOW (window));
607 modest_msg_view_window_scroll_up (ModestWindow *window)
609 ModestMsgViewWindowPrivate *priv;
611 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
612 g_signal_emit_by_name (G_OBJECT (priv->main_scroll), "scroll-child", GTK_SCROLL_STEP_UP, FALSE);
616 modest_msg_view_window_scroll_down (ModestWindow *window)
618 ModestMsgViewWindowPrivate *priv;
620 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
621 g_signal_emit_by_name (G_OBJECT (priv->main_scroll), "scroll-child", GTK_SCROLL_STEP_DOWN, FALSE);
625 modest_msg_view_window_is_last_message (ModestMsgViewWindow *window)
628 ModestMsgViewWindowPrivate *priv;
629 GtkTreeIter tmp_iter;
630 gboolean has_next = FALSE;
632 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), TRUE);
633 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
635 if (priv->header_model) {
636 path = gtk_tree_model_get_path (priv->header_model, &priv->iter);
641 gtk_tree_path_next (path);
642 if (!gtk_tree_model_get_iter (priv->header_model, &tmp_iter, path))
644 gtk_tree_model_get (priv->header_model, &tmp_iter, TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
646 if (!(tny_header_get_flags(header)&TNY_HEADER_FLAG_DELETED)) {
652 gtk_tree_path_free (path);
661 modest_msg_view_window_is_first_message (ModestMsgViewWindow *window)
664 ModestMsgViewWindowPrivate *priv;
666 GtkTreeIter tmp_iter;
668 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), TRUE);
669 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
671 if (priv->header_model) {
673 path = gtk_tree_model_get_path (priv->header_model, &priv->iter);
677 path_string = gtk_tree_path_to_string (path);
678 result = (strcmp (path_string, "0")==0);
680 g_free (path_string);
681 gtk_tree_path_free (path);
688 gtk_tree_path_prev (path);
690 if (!gtk_tree_model_get_iter (priv->header_model, &tmp_iter, path))
692 gtk_tree_model_get (priv->header_model, &tmp_iter, TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
694 if (!(tny_header_get_flags(header)&TNY_HEADER_FLAG_DELETED)) {
699 path_string = gtk_tree_path_to_string (path);
700 if (strcmp(path_string, "0")==0) {
701 g_free (path_string);
704 g_free (path_string);
706 gtk_tree_path_free (path);
715 modest_msg_view_window_select_next_message (ModestMsgViewWindow *window)
717 ModestMsgViewWindowPrivate *priv;
718 GtkTreeIter tmp_iter;
719 gboolean has_next = FALSE;
721 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), FALSE);
722 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
724 if (priv->header_model) {
725 tmp_iter = priv->iter;
726 while (gtk_tree_model_iter_next (priv->header_model, &tmp_iter)) {
731 priv->iter = tmp_iter;
732 gtk_tree_model_get (priv->header_model, &(priv->iter), TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
736 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_DELETED)
739 folder = tny_header_get_folder (header);
742 msg = tny_folder_get_msg (folder, header, NULL);
744 g_object_unref (folder);
748 modest_msg_view_set_message (MODEST_MSG_VIEW (priv->msg_view), msg);
749 modest_msg_view_window_update_dimmed (window);
750 modest_msg_view_window_update_priority (window);
751 gtk_widget_grab_focus (priv->msg_view);
753 g_object_unref (msg);
764 modest_msg_view_window_select_previous_message (ModestMsgViewWindow *window)
766 ModestMsgViewWindowPrivate *priv;
768 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), FALSE);
769 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
771 if (priv->header_model) {
773 gboolean has_prev = FALSE;
775 path = gtk_tree_model_get_path (priv->header_model, &(priv->iter));
776 while (gtk_tree_path_prev (path)) {
781 gtk_tree_model_get_iter (priv->header_model, &(priv->iter), path);
782 gtk_tree_model_get (priv->header_model, &(priv->iter), TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
786 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_DELETED)
788 folder = tny_header_get_folder (header);
791 msg = tny_folder_get_msg (folder, header, NULL);
793 g_object_unref (folder);
797 modest_msg_view_set_message (MODEST_MSG_VIEW (priv->msg_view), msg);
798 modest_msg_view_window_update_dimmed (window);
799 modest_msg_view_window_update_priority (window);
800 gtk_widget_grab_focus (priv->msg_view);
802 g_object_unref (msg);
805 gtk_tree_path_free (path);
813 modest_msg_view_window_get_folder_type (ModestMsgViewWindow *window)
815 ModestMsgViewWindowPrivate *priv;
817 TnyFolderType folder_type;
819 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
821 folder_type = TNY_FOLDER_TYPE_UNKNOWN;
823 msg = modest_msg_view_get_message (MODEST_MSG_VIEW (priv->msg_view));
827 folder = tny_msg_get_folder (msg);
830 folder_type = tny_folder_get_folder_type (folder);
832 if (folder_type == TNY_FOLDER_TYPE_NORMAL || folder_type == TNY_FOLDER_TYPE_UNKNOWN) {
833 const gchar *fname = tny_folder_get_name (folder);
834 folder_type = modest_tny_folder_guess_folder_type_from_name (fname);
837 g_object_unref (folder);
845 modest_msg_view_window_update_dimmed (ModestMsgViewWindow *window)
847 ModestWindowPrivate *parent_priv;
849 gboolean is_first, is_last;
850 TnyFolderType folder_type;
851 gboolean is_not_sent;
853 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
855 is_first = modest_msg_view_window_is_first_message (window);
856 is_last = modest_msg_view_window_is_last_message (window);
858 widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarMessageBack");
859 gtk_action_set_sensitive (widget, !is_first);
860 widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewPreviousMessageMenu");
861 gtk_action_set_sensitive (widget, !is_first);
863 widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNext");
864 gtk_action_set_sensitive (widget, !is_last);
865 widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewNextMessageMenu");
866 gtk_action_set_sensitive (widget, !is_last);
868 folder_type = modest_msg_view_window_get_folder_type (MODEST_MSG_VIEW_WINDOW (window));
869 is_not_sent = ((folder_type == TNY_FOLDER_TYPE_DRAFTS)||(folder_type == TNY_FOLDER_TYPE_OUTBOX));
870 widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply");
871 gtk_action_set_sensitive (widget, !is_not_sent);
872 widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/MessageMenu/MessageReplyMenu");
873 gtk_action_set_sensitive (widget, !is_not_sent);
874 widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/MessageMenu/MessageReplyAllMenu");
875 gtk_action_set_sensitive (widget, !is_not_sent);
876 widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/MessageMenu/MessageForwardMenu");
877 gtk_action_set_sensitive (widget, !is_not_sent);
882 modest_msg_view_window_update_priority (ModestMsgViewWindow *window)
884 ModestMsgViewWindowPrivate *priv;
885 TnyHeaderFlags flags = 0;
887 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
889 if (priv->header_model) {
892 gtk_tree_model_get (priv->header_model, &(priv->iter), TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
894 flags = tny_header_get_flags (header);
897 modest_msg_view_set_priority (MODEST_MSG_VIEW(priv->msg_view), flags);
902 modest_msg_view_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
904 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
905 ModestWindowPrivate *parent_priv;
906 ModestWindowMgr *mgr;
907 gboolean is_fullscreen;
908 GtkAction *fs_toggle_action;
911 mgr = modest_runtime_get_window_mgr ();
912 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
914 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
916 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
917 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
918 if (is_fullscreen != active) {
919 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
928 modest_msg_view_window_toggle_fullscreen (ModestMsgViewWindow *window)
930 ModestWindowPrivate *parent_priv;
931 GtkAction *fs_toggle_action;
932 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
934 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
935 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action),
936 !gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)));
940 set_homogeneous (GtkWidget *widget,
943 if (GTK_IS_TOOL_ITEM (widget)) {
944 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
945 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
950 modest_msg_view_window_show_toolbar (ModestWindow *self,
951 gboolean show_toolbar)
953 ModestWindowPrivate *parent_priv;
954 GtkWidget *reply_button = NULL, *menu = NULL;
956 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
958 if (!parent_priv->toolbar && show_toolbar) {
959 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
962 /* Set homogeneous toolbar */
963 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
964 set_homogeneous, NULL);
967 hildon_window_add_toolbar (HILDON_WINDOW (self),
968 GTK_TOOLBAR (parent_priv->toolbar));
971 /* Set reply button tap and hold menu */
972 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
973 "/ToolBar/ToolbarMessageReply");
974 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
976 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
979 /* TODO: Why is this sometimes NULL? murrayc */
980 if (parent_priv->toolbar) {
982 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
984 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
989 modest_msg_view_window_clipboard_owner_change (GtkClipboard *clipboard,
991 ModestMsgViewWindow *window)
993 ModestWindowPrivate *parent_priv;
998 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
999 selection = gtk_clipboard_wait_for_text (clipboard);
1001 g_message ("SELECTION %s", selection);
1002 is_address = ((selection != NULL) && (modest_text_utils_validate_recipient (selection)));
1005 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/ToolsAddToContactsMenu");
1006 gtk_action_set_sensitive (action, is_address);