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>
34 #include <tny-mime-part.h>
35 #include <tny-vfs-stream.h>
36 #include "modest-marshal.h"
37 #include "modest-platform.h"
38 #include <modest-maemo-utils.h>
39 #include <modest-tny-msg.h>
40 #include <modest-msg-view-window.h>
41 #include <modest-attachments-view.h>
42 #include <modest-main-window-ui.h>
43 #include "modest-msg-view-window-ui-dimming.h"
44 #include <modest-widget-memory.h>
45 #include <modest-runtime.h>
46 #include <modest-window-priv.h>
47 #include <modest-tny-folder.h>
48 #include <modest-text-utils.h>
49 #include <modest-account-mgr-helpers.h>
50 #include "modest-progress-bar-widget.h"
51 #include "modest-defs.h"
52 #include "modest-hildon-includes.h"
53 #include <gtkhtml/gtkhtml-search.h>
54 #include "modest-ui-dimming-manager.h"
55 #include <gdk/gdkkeysyms.h>
56 #include <modest-tny-account.h>
58 #define DEFAULT_FOLDER "MyDocs/.documents"
60 static void modest_msg_view_window_class_init (ModestMsgViewWindowClass *klass);
61 static void modest_msg_view_window_init (ModestMsgViewWindow *obj);
62 static void modest_msg_view_window_finalize (GObject *obj);
63 static void modest_msg_view_window_toggle_find_toolbar (GtkToggleAction *obj,
65 static void modest_msg_view_window_find_toolbar_close (GtkWidget *widget,
66 ModestMsgViewWindow *obj);
67 static void modest_msg_view_window_find_toolbar_search (GtkWidget *widget,
68 ModestMsgViewWindow *obj);
70 static void modest_msg_view_window_disconnect_signals (ModestWindow *self);
71 static void modest_msg_view_window_set_zoom (ModestWindow *window,
73 static gdouble modest_msg_view_window_get_zoom (ModestWindow *window);
74 static gboolean modest_msg_view_window_zoom_minus (ModestWindow *window);
75 static gboolean modest_msg_view_window_zoom_plus (ModestWindow *window);
76 static gboolean modest_msg_view_window_key_release_event (GtkWidget *window,
79 static gboolean modest_msg_view_window_window_state_event (GtkWidget *widget,
80 GdkEventWindowState *event,
82 static void modest_msg_view_window_scroll_up (ModestWindow *window);
83 static void modest_msg_view_window_scroll_down (ModestWindow *window);
84 static void modest_msg_view_window_update_priority (ModestMsgViewWindow *window);
86 static void modest_msg_view_window_show_toolbar (ModestWindow *window,
87 gboolean show_toolbar);
89 static void modest_msg_view_window_clipboard_owner_change (GtkClipboard *clipboard,
91 ModestMsgViewWindow *window);
93 static void cancel_progressbar (GtkToolButton *toolbutton,
94 ModestMsgViewWindow *self);
96 static void on_queue_changed (ModestMailOperationQueue *queue,
97 ModestMailOperation *mail_op,
98 ModestMailOperationQueueNotification type,
99 ModestMsgViewWindow *self);
101 static void on_account_removed (TnyAccountStore *account_store,
105 static void view_msg_cb (ModestMailOperation *mail_op,
110 static void set_toolbar_mode (ModestMsgViewWindow *self,
111 ModestToolBarModes mode);
113 static void update_window_title (ModestMsgViewWindow *window);
115 static gboolean set_toolbar_transfer_mode (ModestMsgViewWindow *self);
118 /* list my signals */
124 static const GtkToggleActionEntry msg_view_toggle_action_entries [] = {
125 { "FindInMessage", MODEST_TOOLBAR_ICON_FIND, N_("qgn_toolb_gene_find"), NULL, NULL, G_CALLBACK (modest_msg_view_window_toggle_find_toolbar), FALSE },
126 { "ToolsFindInMessage", NULL, N_("mcen_me_viewer_find"), NULL, NULL, G_CALLBACK (modest_msg_view_window_toggle_find_toolbar), FALSE },
129 static const GtkRadioActionEntry msg_view_zoom_action_entries [] = {
130 { "Zoom50", NULL, N_("mcen_me_viewer_50"), NULL, NULL, 50 },
131 { "Zoom80", NULL, N_("mcen_me_viewer_80"), NULL, NULL, 80 },
132 { "Zoom100", NULL, N_("mcen_me_viewer_100"), NULL, NULL, 100 },
133 { "Zoom120", NULL, N_("mcen_me_viewer_120"), NULL, NULL, 120 },
134 { "Zoom150", NULL, N_("mcen_me_viewer_150"), NULL, NULL, 150 },
135 { "Zoom200", NULL, N_("mcen_me_viewer_200"), NULL, NULL, 200 }
138 typedef struct _ModestMsgViewWindowPrivate ModestMsgViewWindowPrivate;
139 struct _ModestMsgViewWindowPrivate {
142 GtkWidget *main_scroll;
143 GtkWidget *find_toolbar;
146 /* Progress observers */
147 GtkWidget *progress_bar;
148 GSList *progress_widgets;
151 GtkWidget *progress_toolitem;
152 GtkWidget *cancel_toolitem;
153 GtkWidget *prev_toolitem;
154 GtkWidget *next_toolitem;
155 ModestToolBarModes current_toolbar_mode;
157 /* Optimized view enabled */
158 gboolean optimized_view;
160 GtkTreeModel *header_model;
161 GtkTreeRowReference *row_reference;
162 GtkTreeRowReference *next_row_reference;
164 guint clipboard_change_handler;
165 guint queue_change_handler;
166 guint account_removed_handler;
168 guint progress_bar_timeout;
173 #define MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
174 MODEST_TYPE_MSG_VIEW_WINDOW, \
175 ModestMsgViewWindowPrivate))
177 static GtkWindowClass *parent_class = NULL;
179 /* uncomment the following if you have defined any signals */
180 static guint signals[LAST_SIGNAL] = {0};
183 modest_msg_view_window_get_type (void)
185 static GType my_type = 0;
187 static const GTypeInfo my_info = {
188 sizeof(ModestMsgViewWindowClass),
189 NULL, /* base init */
190 NULL, /* base finalize */
191 (GClassInitFunc) modest_msg_view_window_class_init,
192 NULL, /* class finalize */
193 NULL, /* class data */
194 sizeof(ModestMsgViewWindow),
196 (GInstanceInitFunc) modest_msg_view_window_init,
199 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
200 "ModestMsgViewWindow",
207 save_state (ModestWindow *self)
209 modest_widget_memory_save (modest_runtime_get_conf (),
211 MODEST_CONF_MSG_VIEW_WINDOW_KEY);
216 restore_settings (ModestMsgViewWindow *self)
218 modest_widget_memory_restore (modest_runtime_get_conf (),
220 MODEST_CONF_MSG_VIEW_WINDOW_KEY);
224 modest_msg_view_window_class_init (ModestMsgViewWindowClass *klass)
226 GObjectClass *gobject_class;
227 ModestWindowClass *modest_window_class;
228 gobject_class = (GObjectClass*) klass;
229 modest_window_class = (ModestWindowClass *) klass;
231 parent_class = g_type_class_peek_parent (klass);
232 gobject_class->finalize = modest_msg_view_window_finalize;
234 modest_window_class->set_zoom_func = modest_msg_view_window_set_zoom;
235 modest_window_class->get_zoom_func = modest_msg_view_window_get_zoom;
236 modest_window_class->zoom_minus_func = modest_msg_view_window_zoom_minus;
237 modest_window_class->zoom_plus_func = modest_msg_view_window_zoom_plus;
238 modest_window_class->show_toolbar_func = modest_msg_view_window_show_toolbar;
239 modest_window_class->disconnect_signals_func = modest_msg_view_window_disconnect_signals;
241 g_type_class_add_private (gobject_class, sizeof(ModestMsgViewWindowPrivate));
243 modest_window_class->save_state_func = save_state;
245 signals[MSG_CHANGED_SIGNAL] =
246 g_signal_new ("msg-changed",
247 G_TYPE_FROM_CLASS (gobject_class),
249 G_STRUCT_OFFSET (ModestMsgViewWindowClass, msg_changed),
251 modest_marshal_VOID__POINTER_POINTER,
252 G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER);
256 modest_msg_view_window_init (ModestMsgViewWindow *obj)
258 ModestMsgViewWindowPrivate *priv;
259 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(obj);
261 priv->msg_view = NULL;
262 priv->header_model = NULL;
263 priv->clipboard_change_handler = 0;
264 priv->queue_change_handler = 0;
265 priv->account_removed_handler = 0;
266 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
268 priv->optimized_view = FALSE;
269 priv->progress_bar_timeout = 0;
270 priv->msg_uid = NULL;
275 set_toolbar_transfer_mode (ModestMsgViewWindow *self)
277 ModestMsgViewWindowPrivate *priv = NULL;
279 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), FALSE);
281 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
283 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
285 if (priv->progress_bar_timeout > 0) {
286 g_source_remove (priv->progress_bar_timeout);
287 priv->progress_bar_timeout = 0;
294 set_toolbar_mode (ModestMsgViewWindow *self,
295 ModestToolBarModes mode)
297 ModestWindowPrivate *parent_priv;
298 ModestMsgViewWindowPrivate *priv;
299 /* GtkWidget *widget = NULL; */
301 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self));
303 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
304 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
306 /* Sets current toolbar mode */
307 priv->current_toolbar_mode = mode;
309 /* Update toolbar dimming state */
310 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
313 case TOOLBAR_MODE_NORMAL:
314 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply"); */
315 /* gtk_action_set_sensitive (widget, TRUE); */
316 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage"); */
317 /* gtk_action_set_sensitive (widget, TRUE); */
318 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarMessageMoveTo"); */
319 /* gtk_action_set_sensitive (widget, TRUE); */
320 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/FindInMessage"); */
321 /* gtk_action_set_sensitive (widget, TRUE); */
323 if (priv->prev_toolitem)
324 gtk_widget_show (priv->prev_toolitem);
326 if (priv->next_toolitem)
327 gtk_widget_show (priv->next_toolitem);
329 if (priv->progress_toolitem)
330 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
331 if (priv->progress_bar)
332 gtk_widget_hide (priv->progress_bar);
334 if (priv->cancel_toolitem)
335 gtk_widget_hide (priv->cancel_toolitem);
337 /* Hide toolbar if optimized view is enabled */
338 if (priv->optimized_view) {
339 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
340 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
344 case TOOLBAR_MODE_TRANSFER:
345 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply"); */
346 /* gtk_action_set_sensitive (widget, FALSE); */
347 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage"); */
348 /* gtk_action_set_sensitive (widget, FALSE); */
349 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarMessageMoveTo"); */
350 /* gtk_action_set_sensitive (widget, FALSE); */
351 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/FindInMessage"); */
352 /* gtk_action_set_sensitive (widget, FALSE); */
354 if (priv->prev_toolitem)
355 gtk_widget_hide (priv->prev_toolitem);
357 if (priv->next_toolitem)
358 gtk_widget_hide (priv->next_toolitem);
360 if (priv->progress_toolitem)
361 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
362 if (priv->progress_bar)
363 gtk_widget_show (priv->progress_bar);
365 if (priv->cancel_toolitem)
366 gtk_widget_show (priv->cancel_toolitem);
368 /* Show toolbar if it's hiden (optimized view ) */
369 if (priv->optimized_view) {
370 gtk_widget_set_no_show_all (parent_priv->toolbar, FALSE);
371 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
376 g_return_if_reached ();
383 menubar_to_menu (GtkUIManager *ui_manager)
385 GtkWidget *main_menu;
389 /* Create new main menu */
390 main_menu = gtk_menu_new();
392 /* Get the menubar from the UI manager */
393 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
395 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
399 menu = GTK_WIDGET (iter->data);
400 gtk_widget_reparent(menu, main_menu);
402 iter = g_list_next (iter);
408 init_window (ModestMsgViewWindow *obj, TnyMsg *msg)
410 GtkWidget *main_vbox;
411 ModestMsgViewWindowPrivate *priv;
412 ModestWindowPrivate *parent_priv;
414 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(obj);
415 parent_priv = MODEST_WINDOW_GET_PRIVATE(obj);
417 priv->msg_view = modest_msg_view_new (msg);
418 modest_msg_view_set_shadow_type (MODEST_MSG_VIEW (priv->msg_view), GTK_SHADOW_NONE);
419 main_vbox = gtk_vbox_new (FALSE, 6);
422 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
423 gtk_widget_show_all (GTK_WIDGET(parent_priv->menubar));
424 hildon_window_set_menu (HILDON_WINDOW(obj), GTK_MENU(parent_priv->menubar));
426 priv->main_scroll = gtk_scrolled_window_new (NULL, NULL);
427 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->main_scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
428 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->main_scroll), GTK_SHADOW_NONE);
429 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->main_scroll), TRUE);
431 gtk_container_add (GTK_CONTAINER (priv->main_scroll), priv->msg_view);
432 gtk_box_pack_start (GTK_BOX(main_vbox), priv->main_scroll, TRUE, TRUE, 0);
433 gtk_container_add (GTK_CONTAINER(obj), main_vbox);
435 priv->find_toolbar = hildon_find_toolbar_new (NULL);
436 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
437 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
438 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_view_window_find_toolbar_close), obj);
439 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_view_window_find_toolbar_search), obj);
441 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);
442 gtk_widget_show_all (GTK_WIDGET(main_vbox));
446 modest_msg_view_window_disconnect_signals (ModestWindow *self)
448 ModestMsgViewWindowPrivate *priv;
450 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
452 if (g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
453 priv->clipboard_change_handler))
454 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
455 priv->clipboard_change_handler);
457 if (g_signal_handler_is_connected (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
458 priv->queue_change_handler))
459 g_signal_handler_disconnect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
460 priv->queue_change_handler);
462 if (g_signal_handler_is_connected (G_OBJECT (modest_runtime_get_account_store ()),
463 priv->account_removed_handler))
464 g_signal_handler_disconnect (G_OBJECT (modest_runtime_get_account_store ()),
465 priv->account_removed_handler);
469 modest_msg_view_window_finalize (GObject *obj)
471 ModestMsgViewWindowPrivate *priv;
473 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (obj);
475 /* Sanity check: shouldn't be needed, the window mgr should
476 call this function before */
477 modest_msg_view_window_disconnect_signals (MODEST_WINDOW (obj));
479 if (priv->header_model != NULL) {
480 g_object_unref (priv->header_model);
481 priv->header_model = NULL;
484 if (priv->progress_bar_timeout > 0) {
485 g_source_remove (priv->progress_bar_timeout);
486 priv->progress_bar_timeout = 0;
489 if (priv->row_reference) {
490 gtk_tree_row_reference_free (priv->row_reference);
491 priv->row_reference = NULL;
494 if (priv->next_row_reference) {
495 gtk_tree_row_reference_free (priv->next_row_reference);
496 priv->next_row_reference = NULL;
500 g_free (priv->msg_uid);
501 priv->msg_uid = NULL;
504 G_OBJECT_CLASS(parent_class)->finalize (obj);
508 select_next_valid_row (GtkTreeModel *model,
509 GtkTreeRowReference **row_reference,
512 GtkTreeIter tmp_iter;
513 GtkTreePath *path, *next;
514 gboolean retval = FALSE;
516 g_return_val_if_fail (gtk_tree_row_reference_valid (*row_reference), FALSE);
518 path = gtk_tree_row_reference_get_path (*row_reference);
519 gtk_tree_model_get_iter (model, &tmp_iter, path);
520 gtk_tree_row_reference_free (*row_reference);
521 *row_reference = NULL;
523 if (gtk_tree_model_iter_next (model, &tmp_iter)) {
524 next = gtk_tree_model_get_path (model, &tmp_iter);
525 *row_reference = gtk_tree_row_reference_new (model, next);
527 } else if (cycle && gtk_tree_model_get_iter_first (model, &tmp_iter)) {
528 next = gtk_tree_model_get_path (model, &tmp_iter);
530 /* Ensure that we are not selecting the same */
531 if (gtk_tree_path_compare (path, next) != 0) {
532 *row_reference = gtk_tree_row_reference_new (model, next);
538 gtk_tree_path_free (path);
544 modest_msg_view_window_new_with_header_model (TnyMsg *msg,
545 const gchar *modest_account_name,
546 const gchar *msg_uid,
548 GtkTreeRowReference *row_reference)
550 ModestMsgViewWindow *window = NULL;
551 ModestMsgViewWindowPrivate *priv = NULL;
553 window = MODEST_MSG_VIEW_WINDOW(modest_msg_view_window_new (msg, modest_account_name, msg_uid));
554 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), NULL);
556 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
558 g_object_ref (model);
559 priv->header_model = model;
560 priv->row_reference = gtk_tree_row_reference_copy (row_reference);
561 priv->next_row_reference = gtk_tree_row_reference_copy (row_reference);
562 select_next_valid_row (model, &(priv->next_row_reference), TRUE);
564 modest_msg_view_window_update_priority (window);
566 /* Check toolbar dimming rules */
567 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
569 return MODEST_WINDOW(window);
574 modest_msg_view_window_new (TnyMsg *msg,
575 const gchar *modest_account_name,
576 const gchar *msg_uid)
578 ModestMsgViewWindow *self = NULL;
580 ModestMsgViewWindowPrivate *priv = NULL;
581 ModestWindowPrivate *parent_priv = NULL;
582 ModestDimmingRulesGroup *menu_rules_group = NULL;
583 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
584 GtkActionGroup *action_group = NULL;
585 GError *error = NULL;
586 GdkPixbuf *window_icon;
588 g_return_val_if_fail (msg, NULL);
590 obj = g_object_new(MODEST_TYPE_MSG_VIEW_WINDOW, NULL);
591 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(obj);
592 parent_priv = MODEST_WINDOW_GET_PRIVATE(obj);
593 self = MODEST_MSG_VIEW_WINDOW (obj);
595 priv->msg_uid = g_strdup (msg_uid);
597 parent_priv->ui_manager = gtk_ui_manager_new();
598 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
600 action_group = gtk_action_group_new ("ModestMsgViewWindowActions");
601 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
603 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
604 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
606 /* Add common actions */
607 gtk_action_group_add_actions (action_group,
608 modest_action_entries,
609 G_N_ELEMENTS (modest_action_entries),
611 gtk_action_group_add_toggle_actions (action_group,
612 modest_toggle_action_entries,
613 G_N_ELEMENTS (modest_toggle_action_entries),
615 gtk_action_group_add_toggle_actions (action_group,
616 msg_view_toggle_action_entries,
617 G_N_ELEMENTS (msg_view_toggle_action_entries),
619 gtk_action_group_add_radio_actions (action_group,
620 msg_view_zoom_action_entries,
621 G_N_ELEMENTS (msg_view_zoom_action_entries),
623 G_CALLBACK (modest_ui_actions_on_change_zoom),
626 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
627 g_object_unref (action_group);
629 /* Load the UI definition */
630 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-view-window-ui.xml",
633 g_printerr ("modest: could not merge modest-msg-view-window-ui.xml: %s\n", error->message);
634 g_error_free (error);
639 /* Add common dimming rules */
640 modest_dimming_rules_group_add_rules (menu_rules_group,
641 modest_msg_view_menu_dimming_entries,
642 G_N_ELEMENTS (modest_msg_view_menu_dimming_entries),
644 modest_dimming_rules_group_add_rules (toolbar_rules_group,
645 modest_msg_view_toolbar_dimming_entries,
646 G_N_ELEMENTS (modest_msg_view_toolbar_dimming_entries),
649 /* Insert dimming rules group for this window */
650 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
651 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
652 g_object_unref (menu_rules_group);
653 g_object_unref (toolbar_rules_group);
655 /* Add accelerators */
656 gtk_window_add_accel_group (GTK_WINDOW (obj),
657 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
660 init_window (MODEST_MSG_VIEW_WINDOW(obj), msg);
661 restore_settings (MODEST_MSG_VIEW_WINDOW(obj));
663 /* Set window icon */
664 window_icon = modest_platform_get_icon (MODEST_APP_MSG_VIEW_ICON);
666 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
667 g_object_unref (window_icon);
670 /* g_signal_connect (G_OBJECT(obj), "delete-event", G_CALLBACK(on_delete_event), obj); */
672 g_signal_connect (G_OBJECT(priv->msg_view), "link_clicked",
673 G_CALLBACK (modest_ui_actions_on_msg_link_clicked), obj);
674 g_signal_connect (G_OBJECT(priv->msg_view), "link_hover",
675 G_CALLBACK (modest_ui_actions_on_msg_link_hover), obj);
676 g_signal_connect (G_OBJECT(priv->msg_view), "attachment_clicked",
677 G_CALLBACK (modest_ui_actions_on_msg_attachment_clicked), obj);
678 g_signal_connect (G_OBJECT(priv->msg_view), "recpt_activated",
679 G_CALLBACK (modest_ui_actions_on_msg_recpt_activated), obj);
680 g_signal_connect (G_OBJECT(priv->msg_view), "link_contextual",
681 G_CALLBACK (modest_ui_actions_on_msg_link_contextual), obj);
683 g_signal_connect (G_OBJECT (obj), "key-release-event",
684 G_CALLBACK (modest_msg_view_window_key_release_event),
687 g_signal_connect (G_OBJECT (obj), "window-state-event",
688 G_CALLBACK (modest_msg_view_window_window_state_event),
691 /* Mail Operation Queue */
692 priv->queue_change_handler = g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
694 G_CALLBACK (on_queue_changed),
697 /* Account manager */
698 priv->account_removed_handler = g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
700 G_CALLBACK(on_account_removed),
703 modest_window_set_active_account (MODEST_WINDOW(obj), modest_account_name);
705 priv->last_search = NULL;
707 /* Init the clipboard actions dim status */
708 modest_msg_view_grab_focus(MODEST_MSG_VIEW (priv->msg_view));
710 update_window_title (MODEST_MSG_VIEW_WINDOW (obj));
712 /* Check toolbar dimming rules */
713 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
715 return MODEST_WINDOW(obj);
720 modest_msg_view_window_toolbar_on_transfer_mode (ModestMsgViewWindow *self)
722 ModestMsgViewWindowPrivate *priv= NULL;
724 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), FALSE);
725 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
727 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
731 modest_msg_view_window_get_header (ModestMsgViewWindow *self)
733 ModestMsgViewWindowPrivate *priv= NULL;
735 TnyHeader *header = NULL;
736 GtkTreePath *path = NULL;
739 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), NULL);
740 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
742 /* Message is not obtained from a treemodel (Attachment ?) */
743 if (priv->header_model == NULL) {
744 msg = modest_msg_view_window_get_message (self);
745 header = tny_msg_get_header (msg);
746 g_object_unref (msg);
750 /* Get current message iter */
751 path = gtk_tree_row_reference_get_path (priv->row_reference);
752 g_return_val_if_fail (path != NULL, NULL);
753 gtk_tree_model_get_iter (priv->header_model,
757 /* Get current message header */
758 gtk_tree_model_get (priv->header_model, &iter,
759 TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
762 gtk_tree_path_free (path);
767 modest_msg_view_window_get_message (ModestMsgViewWindow *self)
769 ModestMsgView *msg_view;
770 ModestMsgViewWindowPrivate *priv;
772 g_return_val_if_fail (self, NULL);
774 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
776 msg_view = MODEST_MSG_VIEW (priv->msg_view);
778 return modest_msg_view_get_message (msg_view);
782 modest_msg_view_window_get_message_uid (ModestMsgViewWindow *self)
784 ModestMsgViewWindowPrivate *priv;
786 g_return_val_if_fail (self, NULL);
788 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
790 return (const gchar*) priv->msg_uid;
794 modest_msg_view_window_toggle_find_toolbar (GtkToggleAction *toggle,
797 ModestMsgViewWindow *window = MODEST_MSG_VIEW_WINDOW (data);
798 ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
799 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
803 is_active = gtk_toggle_action_get_active (toggle);
806 gtk_widget_show (priv->find_toolbar);
807 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
809 gtk_widget_hide (priv->find_toolbar);
812 /* update the toggle buttons status */
813 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/FindInMessage");
814 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), is_active);
815 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/ToolsFindInMessageMenu");
816 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), is_active);
821 modest_msg_view_window_find_toolbar_close (GtkWidget *widget,
822 ModestMsgViewWindow *obj)
824 GtkToggleAction *toggle;
825 ModestWindowPrivate *parent_priv;
826 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
828 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/FindInMessage"));
829 gtk_toggle_action_set_active (toggle, FALSE);
833 modest_msg_view_window_find_toolbar_search (GtkWidget *widget,
834 ModestMsgViewWindow *obj)
836 gchar *current_search;
837 ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (obj);
839 if (modest_msg_view_get_message_is_empty (MODEST_MSG_VIEW (priv->msg_view))) {
840 hildon_banner_show_information (NULL, NULL, _("mail_ib_nothing_to_find"));
844 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
846 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
847 g_free (current_search);
848 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
852 if ((priv->last_search == NULL) || (strcmp (priv->last_search, current_search) != 0)) {
854 g_free (priv->last_search);
855 priv->last_search = g_strdup (current_search);
856 result = modest_msg_view_search (MODEST_MSG_VIEW (priv->msg_view),
859 hildon_banner_show_information (NULL, NULL, dgettext("hildon-libs", "ckct_ib_find_no_matches"));
860 g_free (priv->last_search);
861 priv->last_search = NULL;
864 if (!modest_msg_view_search_next (MODEST_MSG_VIEW (priv->msg_view))) {
865 hildon_banner_show_information (NULL, NULL, dgettext("hildon-libs", "ckct_ib_find_search_complete"));
866 g_free (priv->last_search);
867 priv->last_search = NULL;
871 g_free (current_search);
876 modest_msg_view_window_set_zoom (ModestWindow *window,
879 ModestMsgViewWindowPrivate *priv;
881 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
883 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
884 modest_msg_view_set_zoom (MODEST_MSG_VIEW (priv->msg_view), zoom);
888 modest_msg_view_window_get_zoom (ModestWindow *window)
890 ModestMsgViewWindowPrivate *priv;
892 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), 1.0);
894 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
895 return modest_msg_view_get_zoom (MODEST_MSG_VIEW (priv->msg_view));
899 modest_msg_view_window_zoom_plus (ModestWindow *window)
901 ModestWindowPrivate *parent_priv;
902 GtkRadioAction *zoom_radio_action;
903 GSList *group, *node;
905 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
906 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
907 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
909 group = gtk_radio_action_get_group (zoom_radio_action);
911 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
912 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
916 for (node = group; node != NULL; node = g_slist_next (node)) {
917 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
918 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
926 modest_msg_view_window_zoom_minus (ModestWindow *window)
928 ModestWindowPrivate *parent_priv;
929 GtkRadioAction *zoom_radio_action;
930 GSList *group, *node;
932 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
933 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
934 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
936 group = gtk_radio_action_get_group (zoom_radio_action);
938 for (node = group; node != NULL; node = g_slist_next (node)) {
939 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
940 if (node->next != NULL) {
941 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
944 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
954 modest_msg_view_window_key_release_event (GtkWidget *window,
958 if (event->type == GDK_KEY_RELEASE) {
959 switch (event->keyval) {
961 modest_msg_view_window_scroll_up (MODEST_WINDOW (window));
965 modest_msg_view_window_scroll_down (MODEST_WINDOW (window));
978 modest_msg_view_window_scroll_up (ModestWindow *window)
980 ModestMsgViewWindowPrivate *priv;
981 gboolean return_value;
983 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
984 g_signal_emit_by_name (G_OBJECT (priv->main_scroll), "scroll-child", GTK_SCROLL_STEP_UP, FALSE, &return_value);
988 modest_msg_view_window_scroll_down (ModestWindow *window)
990 ModestMsgViewWindowPrivate *priv;
991 gboolean return_value;
993 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
994 g_signal_emit_by_name (G_OBJECT (priv->main_scroll), "scroll-child", GTK_SCROLL_STEP_DOWN, FALSE, &return_value);
998 modest_msg_view_window_last_message_selected (ModestMsgViewWindow *window)
1001 ModestMsgViewWindowPrivate *priv;
1002 GtkTreeIter tmp_iter;
1003 gboolean has_next = FALSE;
1005 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), TRUE);
1006 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1008 if (priv->header_model) {
1009 path = gtk_tree_row_reference_get_path (priv->row_reference);
1010 if (path == NULL) return FALSE;
1013 gtk_tree_path_next (path);
1014 if (!gtk_tree_model_get_iter (priv->header_model, &tmp_iter, path))
1016 gtk_tree_model_get (priv->header_model, &tmp_iter, TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
1018 if (!(tny_header_get_flags(header)&TNY_HEADER_FLAG_DELETED)) {
1023 gtk_tree_path_free (path);
1032 modest_msg_view_window_has_headers_model (ModestMsgViewWindow *window)
1034 ModestMsgViewWindowPrivate *priv;
1036 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), TRUE);
1037 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1039 return priv->header_model != NULL;
1043 modest_msg_view_window_first_message_selected (ModestMsgViewWindow *window)
1046 ModestMsgViewWindowPrivate *priv;
1048 GtkTreeIter tmp_iter;
1050 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), TRUE);
1051 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1053 if (priv->header_model) {
1054 gchar * path_string;
1055 path = gtk_tree_row_reference_get_path (priv->row_reference);
1059 path_string = gtk_tree_path_to_string (path);
1060 result = (strcmp (path_string, "0")==0);
1062 g_free (path_string);
1063 gtk_tree_path_free (path);
1070 gtk_tree_path_prev (path);
1072 if (!gtk_tree_model_get_iter (priv->header_model, &tmp_iter, path))
1074 gtk_tree_model_get (priv->header_model, &tmp_iter, TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
1076 if (!(tny_header_get_flags(header)&TNY_HEADER_FLAG_DELETED)) {
1081 path_string = gtk_tree_path_to_string (path);
1082 if (strcmp(path_string, "0")==0) {
1083 g_free (path_string);
1086 g_free (path_string);
1088 gtk_tree_path_free (path);
1097 * Reads the message whose summary item is @header. It takes care of
1098 * several things, among others:
1100 * If the message was not previously downloaded then ask the user
1101 * before downloading. If there is no connection launch the connection
1102 * dialog. Update toolbar dimming rules.
1104 * Returns: TRUE if the mail operation was started, otherwise if the
1105 * user do not want to download the message, or if the user do not
1106 * want to connect, then the operation is not issued
1109 message_reader (ModestMsgViewWindow *window,
1110 ModestMsgViewWindowPrivate *priv,
1114 ModestMailOperation *mail_op = NULL;
1115 ModestMailOperationTypeOperation op_type;
1116 gboolean already_showing = FALSE;
1117 ModestWindow *msg_window = NULL;
1118 ModestWindowMgr *mgr;
1120 g_return_val_if_fail (path != NULL, FALSE);
1122 mgr = modest_runtime_get_window_mgr ();
1123 already_showing = modest_window_mgr_find_registered_header (mgr, header, &msg_window);
1124 if (already_showing && (msg_window != MODEST_WINDOW (window))) {
1127 gtk_window_present (GTK_WINDOW (msg_window));
1128 g_signal_emit_by_name (G_OBJECT (window), "delete-event", NULL, &retval);
1132 /* Msg download completed */
1133 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED) {
1134 op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
1137 GtkResponseType response;
1139 op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1141 /* Ask the user if he wants to download the message */
1142 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
1143 _("mcen_nc_get_msg"));
1144 if (response == GTK_RESPONSE_CANCEL)
1147 /* Offer the connection dialog if necessary */
1148 /* FIXME: should this stuff go directly to the mail
1149 operation instead of spread it all over the
1151 folder = tny_header_get_folder (header);
1153 if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, TNY_FOLDER_STORE (folder))) {
1154 g_object_unref (folder);
1157 g_object_unref (folder);
1161 /* New mail operation */
1162 mail_op = modest_mail_operation_new_with_error_handling (op_type,
1164 modest_ui_actions_get_msgs_full_error_handler,
1167 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1168 modest_mail_operation_get_msg (mail_op, header, view_msg_cb, path);
1169 g_object_unref (mail_op);
1171 /* Update toolbar dimming rules */
1172 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
1178 modest_msg_view_window_select_next_message (ModestMsgViewWindow *window)
1180 ModestMsgViewWindowPrivate *priv;
1181 GtkTreePath *path= NULL;
1182 GtkTreeIter tmp_iter;
1184 gboolean retval = TRUE;
1186 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), FALSE);
1187 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1189 /* Update the next row reference if it's not valid. This could
1190 happen if for example the header which it was pointing to,
1191 was deleted. The best place to do it is in the row-deleted
1192 handler but the tinymail model do not work like the glib
1193 tree models and reports the deletion when the row is still
1195 if (!gtk_tree_row_reference_valid (priv->next_row_reference)) {
1196 if (gtk_tree_row_reference_valid (priv->row_reference)) {
1197 priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference);
1198 select_next_valid_row (priv->header_model, &(priv->next_row_reference), FALSE);
1201 if (priv->next_row_reference)
1202 path = gtk_tree_row_reference_get_path (priv->next_row_reference);
1206 gtk_tree_model_get_iter (priv->header_model,
1210 gtk_tree_model_get (priv->header_model, &tmp_iter,
1211 TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
1214 /* Read the message & show it */
1215 if (!message_reader (window, priv, header, path)) {
1217 gtk_tree_path_free (path);
1221 g_object_unref (header);
1227 modest_msg_view_window_select_first_message (ModestMsgViewWindow *self)
1229 ModestMsgViewWindowPrivate *priv = NULL;
1230 TnyHeader *header = NULL;
1234 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), FALSE);
1235 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
1237 /* Check that the model is not empty */
1238 if (!gtk_tree_model_get_iter_first (priv->header_model, &iter))
1241 /* Get the header */
1242 gtk_tree_model_get (priv->header_model,
1244 TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
1246 g_return_val_if_fail (TNY_IS_HEADER (header), FALSE);
1247 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_DELETED) {
1248 g_object_unref (header);
1249 return modest_msg_view_window_select_next_message (self);
1252 path = gtk_tree_model_get_path (priv->header_model, &iter);
1254 /* Read the message & show it */
1255 message_reader (self, priv, header, path);
1258 g_object_unref (header);
1264 modest_msg_view_window_select_previous_message (ModestMsgViewWindow *window)
1266 ModestMsgViewWindowPrivate *priv = NULL;
1269 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), FALSE);
1270 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1272 /* Return inmediatly if there is no header model */
1273 if (!priv->header_model)
1276 path = gtk_tree_row_reference_get_path (priv->row_reference);
1277 while (gtk_tree_path_prev (path)) {
1281 gtk_tree_model_get_iter (priv->header_model, &iter, path);
1282 gtk_tree_model_get (priv->header_model, &iter,
1283 TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
1287 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_DELETED) {
1288 g_object_unref (header);
1292 /* Read the message & show it */
1293 if (!message_reader (window, priv, header, path)) {
1294 g_object_unref (header);
1298 g_object_unref (header);
1303 gtk_tree_path_free (path);
1308 view_msg_cb (ModestMailOperation *mail_op,
1313 ModestMsgViewWindow *self = NULL;
1314 ModestMsgViewWindowPrivate *priv = NULL;
1317 /* If there was any error */
1318 path = (GtkTreePath *) user_data;
1319 if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
1320 gtk_tree_path_free (path);
1324 /* Get the window */
1325 self = (ModestMsgViewWindow *) modest_mail_operation_get_source (mail_op);
1326 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self));
1327 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
1329 /* Update the row reference */
1330 gtk_tree_row_reference_free (priv->row_reference);
1331 priv->row_reference = gtk_tree_row_reference_new (priv->header_model, path);
1332 priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference);
1333 select_next_valid_row (priv->header_model, &(priv->next_row_reference), TRUE);
1334 gtk_tree_path_free (path);
1336 /* Mark header as read */
1337 if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_SEEN))
1338 tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
1340 /* Set new message */
1341 modest_msg_view_set_message (MODEST_MSG_VIEW (priv->msg_view), msg);
1342 modest_msg_view_window_update_priority (self);
1343 update_window_title (MODEST_MSG_VIEW_WINDOW (self));
1344 modest_msg_view_grab_focus (MODEST_MSG_VIEW (priv->msg_view));
1346 /* Set the new message uid of the window */
1347 if (priv->msg_uid) {
1348 g_free (priv->msg_uid);
1349 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1352 /* Notify the observers */
1353 g_signal_emit (G_OBJECT (self), signals[MSG_CHANGED_SIGNAL],
1354 0, priv->header_model, priv->row_reference);
1356 /* Free new references */
1357 g_object_unref (self);
1361 modest_msg_view_window_get_folder_type (ModestMsgViewWindow *window)
1363 ModestMsgViewWindowPrivate *priv;
1365 TnyFolderType folder_type;
1367 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1369 folder_type = TNY_FOLDER_TYPE_UNKNOWN;
1371 msg = modest_msg_view_get_message (MODEST_MSG_VIEW (priv->msg_view));
1375 folder = tny_msg_get_folder (msg);
1378 folder_type = tny_folder_get_folder_type (folder);
1380 if (folder_type == TNY_FOLDER_TYPE_NORMAL || folder_type == TNY_FOLDER_TYPE_UNKNOWN) {
1381 const gchar *fname = tny_folder_get_name (folder);
1382 folder_type = modest_tny_folder_guess_folder_type_from_name (fname);
1385 g_object_unref (folder);
1387 g_object_unref (msg);
1395 modest_msg_view_window_update_priority (ModestMsgViewWindow *window)
1397 ModestMsgViewWindowPrivate *priv;
1398 TnyHeaderFlags flags = 0;
1400 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1402 if (priv->header_model) {
1405 GtkTreePath *path = NULL;
1407 path = gtk_tree_row_reference_get_path (priv->row_reference);
1408 g_return_if_fail (path != NULL);
1409 gtk_tree_model_get_iter (priv->header_model,
1411 gtk_tree_row_reference_get_path (priv->row_reference));
1413 gtk_tree_model_get (priv->header_model, &iter, TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
1415 flags = tny_header_get_flags (header);
1416 gtk_tree_path_free (path);
1419 modest_msg_view_set_priority (MODEST_MSG_VIEW(priv->msg_view), flags);
1424 modest_msg_view_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1426 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1427 ModestWindowPrivate *parent_priv;
1428 ModestWindowMgr *mgr;
1429 gboolean is_fullscreen;
1430 GtkAction *fs_toggle_action;
1433 mgr = modest_runtime_get_window_mgr ();
1434 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
1436 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1438 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1439 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1440 if (is_fullscreen != active) {
1441 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1450 modest_msg_view_window_toggle_fullscreen (ModestMsgViewWindow *window)
1452 ModestWindowPrivate *parent_priv;
1453 GtkAction *fs_toggle_action;
1454 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1456 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1457 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action),
1458 !gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)));
1462 set_homogeneous (GtkWidget *widget,
1465 if (GTK_IS_TOOL_ITEM (widget)) {
1466 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1467 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1472 modest_msg_view_window_show_toolbar (ModestWindow *self,
1473 gboolean show_toolbar)
1475 ModestMsgViewWindowPrivate *priv = NULL;
1476 ModestWindowPrivate *parent_priv;
1477 GtkWidget *reply_button = NULL, *menu = NULL;
1478 GtkWidget *placeholder = NULL;
1481 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1482 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
1484 /* Set optimized view status */
1485 priv->optimized_view = !show_toolbar;
1487 if (!parent_priv->toolbar) {
1488 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1491 /* Set homogeneous toolbar */
1492 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1493 set_homogeneous, NULL);
1495 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1496 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1497 priv->next_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNext");
1498 priv->prev_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageBack");
1499 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1500 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1501 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1502 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1504 /* Add ProgressBar (Transfer toolbar) */
1505 priv->progress_bar = modest_progress_bar_widget_new ();
1506 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1507 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressbarView");
1508 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1509 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1510 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1512 /* Connect cancel 'clicked' signal to abort progress mode */
1513 g_signal_connect(priv->cancel_toolitem, "clicked",
1514 G_CALLBACK(cancel_progressbar),
1517 /* Add it to the observers list */
1518 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1521 hildon_window_add_toolbar (HILDON_WINDOW (self),
1522 GTK_TOOLBAR (parent_priv->toolbar));
1525 /* Set reply button tap and hold menu */
1526 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1527 "/ToolBar/ToolbarMessageReply");
1528 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1529 "/ToolbarReplyCSM");
1530 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1534 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1535 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1536 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1538 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1539 set_toolbar_mode (MODEST_MSG_VIEW_WINDOW(self), TOOLBAR_MODE_NORMAL);
1542 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1543 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1548 modest_msg_view_window_clipboard_owner_change (GtkClipboard *clipboard,
1550 ModestMsgViewWindow *window)
1552 ModestWindowPrivate *parent_priv;
1553 /* GtkAction *action; */
1554 gboolean is_address;
1558 if (!GTK_WIDGET_VISIBLE (window))
1561 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1562 selection = gtk_clipboard_wait_for_text (clipboard);
1564 is_address = ((selection != NULL) && (modest_text_utils_validate_recipient (selection, NULL)));
1566 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/ToolsAddToContactsMenu"); */
1567 /* gtk_action_set_sensitive (action, is_address); */
1569 focused = gtk_window_get_focus (GTK_WINDOW (window));
1571 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/EditCopyMenu"); */
1572 /* gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused))); */
1574 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/EditCutMenu"); */
1575 /* gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused))); */
1578 /* modest_msg_view_window_update_dimmed (window); */
1583 modest_msg_view_window_transfer_mode_enabled (ModestMsgViewWindow *self)
1585 ModestMsgViewWindowPrivate *priv;
1587 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), FALSE);
1588 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
1590 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
1594 cancel_progressbar (GtkToolButton *toolbutton,
1595 ModestMsgViewWindow *self)
1598 ModestMsgViewWindowPrivate *priv;
1600 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
1602 /* Get operation observers and cancel its current operation */
1603 tmp = priv->progress_widgets;
1605 modest_progress_object_cancel_current_operation (MODEST_PROGRESS_OBJECT(tmp->data));
1606 tmp=g_slist_next(tmp);
1610 observers_empty (ModestMsgViewWindow *self)
1613 ModestMsgViewWindowPrivate *priv;
1614 gboolean is_empty = TRUE;
1615 guint pending_ops = 0;
1617 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
1618 tmp = priv->progress_widgets;
1620 /* Check all observers */
1621 while (tmp && is_empty) {
1622 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1623 is_empty = pending_ops == 0;
1625 tmp = g_slist_next(tmp);
1632 on_account_removed (TnyAccountStore *account_store,
1633 TnyAccount *account,
1636 /* Do nothing if it's a transport account, because we only
1637 show the messages of a store account */
1638 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_STORE) {
1639 const gchar *parent_acc = NULL;
1640 const gchar *our_acc = NULL;
1642 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
1643 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
1645 /* Close this window if I'm showing a message of the removed account */
1646 if (strcmp (parent_acc, our_acc) == 0)
1647 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
1652 on_queue_changed (ModestMailOperationQueue *queue,
1653 ModestMailOperation *mail_op,
1654 ModestMailOperationQueueNotification type,
1655 ModestMsgViewWindow *self)
1658 ModestMsgViewWindowPrivate *priv;
1659 ModestMailOperationTypeOperation op_type;
1660 ModestToolBarModes mode;
1662 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self));
1663 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
1665 /* If this operations was created by another window, do nothing */
1666 if (!modest_mail_operation_is_mine (mail_op, G_OBJECT(self)))
1669 /* Get toolbar mode from operation id*/
1670 op_type = modest_mail_operation_get_type_operation (mail_op);
1672 /* case MODEST_MAIL_OPERATION_TYPE_SEND: */
1673 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
1674 case MODEST_MAIL_OPERATION_TYPE_OPEN:
1675 mode = TOOLBAR_MODE_TRANSFER;
1678 mode = TOOLBAR_MODE_NORMAL;
1682 /* Add operation observers and change toolbar if neccessary*/
1683 tmp = priv->progress_widgets;
1685 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
1686 if (mode == TOOLBAR_MODE_TRANSFER) {
1687 /* Enable transfer toolbar mode */
1688 set_toolbar_transfer_mode(self);
1690 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1692 tmp = g_slist_next (tmp);
1697 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
1698 if (mode == TOOLBAR_MODE_TRANSFER) {
1700 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1702 tmp = g_slist_next (tmp);
1706 /* If no more operations are being observed, NORMAL mode is enabled again */
1707 if (observers_empty (self)) {
1708 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
1716 modest_msg_view_window_get_attachments (ModestMsgViewWindow *win)
1718 ModestMsgViewWindowPrivate *priv;
1719 GList *selected_attachments = NULL;
1721 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (win), NULL);
1722 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (win);
1724 selected_attachments = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
1726 return selected_attachments;
1730 modest_msg_view_window_view_attachment (ModestMsgViewWindow *window, TnyMimePart *mime_part)
1732 ModestMsgViewWindowPrivate *priv;
1733 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
1734 g_return_if_fail (TNY_IS_MIME_PART (mime_part) || (mime_part == NULL));
1736 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1738 if (mime_part == NULL) {
1739 gboolean error = FALSE;
1740 GList *selected_attachments = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
1741 if (selected_attachments == NULL) {
1743 } else if (g_list_length (selected_attachments) > 1) {
1744 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unable_to_display_more"));
1747 mime_part = (TnyMimePart *) selected_attachments->data;
1748 g_object_ref (mime_part);
1750 g_list_foreach (selected_attachments, (GFunc) g_object_unref, NULL);
1751 g_list_free (selected_attachments);
1756 g_object_ref (mime_part);
1759 if (tny_mime_part_is_purged (mime_part)) {
1760 g_object_unref (mime_part);
1761 hildon_banner_show_information (NULL, NULL, _("mail_ib_attach_not_local"));
1765 if (!TNY_IS_MSG (mime_part)) {
1766 gchar *filepath = NULL;
1767 const gchar *att_filename = tny_mime_part_get_filename (mime_part);
1768 gchar *extension = NULL;
1769 TnyFsStream *temp_stream = NULL;
1772 extension = g_strrstr (att_filename, ".");
1773 if (extension != NULL)
1777 temp_stream = modest_maemo_utils_create_temp_stream (extension, &filepath);
1780 const gchar *content_type;
1781 content_type = tny_mime_part_get_content_type (mime_part);
1782 tny_mime_part_decode_to_stream (mime_part, TNY_STREAM (temp_stream));
1784 modest_platform_activate_file (filepath, content_type);
1785 g_object_unref (temp_stream);
1787 /* TODO: delete temporary file */
1790 /* message attachment */
1791 TnyHeader *header = NULL;
1792 ModestWindowMgr *mgr;
1793 ModestWindow *msg_win = NULL;
1796 header = tny_msg_get_header (TNY_MSG (mime_part));
1797 mgr = modest_runtime_get_window_mgr ();
1798 found = modest_window_mgr_find_registered_header (mgr, header, &msg_win);
1801 if (msg_win) /* there is already a window for this uid; top it */
1802 gtk_window_present (GTK_WINDOW(msg_win));
1804 /* if it's found, but there is no msg_win, it's probably in the process of being created;
1805 * thus, we don't do anything */
1806 g_warning ("window for is already being created");
1808 /* it's not found, so create a new window for it */
1809 modest_window_mgr_register_header (mgr, header); /* register the uid before building the window */
1810 gchar *account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (window)));
1812 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr ());
1813 msg_win = modest_msg_view_window_new (TNY_MSG (mime_part), account, NULL);
1814 modest_window_set_zoom (MODEST_WINDOW (msg_win),
1815 modest_window_get_zoom (MODEST_WINDOW (window)));
1816 modest_window_mgr_register_window (mgr, msg_win);
1817 gtk_window_set_transient_for (GTK_WINDOW (msg_win), GTK_WINDOW (window));
1818 gtk_widget_show_all (GTK_WIDGET (msg_win));
1821 g_object_unref (mime_part);
1837 static void save_mime_part_info_free (SaveMimePartInfo *info, gboolean with_struct);
1838 static gboolean idle_save_mime_part_show_result (SaveMimePartInfo *info);
1839 static gpointer save_mime_part_to_file (SaveMimePartInfo *info);
1840 static void save_mime_parts_to_file_with_checks (SaveMimePartInfo *info);
1843 save_mime_part_info_free (SaveMimePartInfo *info, gboolean with_struct)
1847 for (node = info->pairs; node != NULL; node = g_list_next (node)) {
1848 SaveMimePartPair *pair = (SaveMimePartPair *) node->data;
1849 g_free (pair->filename);
1850 g_object_unref (pair->part);
1851 g_slice_free (SaveMimePartPair, pair);
1853 g_list_free (info->pairs);
1856 gtk_widget_destroy (info->banner);
1857 g_object_unref (info->banner);
1858 g_slice_free (SaveMimePartInfo, info);
1863 idle_save_mime_part_show_result (SaveMimePartInfo *info)
1865 if (info->pairs != NULL) {
1866 gdk_threads_enter ();
1867 save_mime_parts_to_file_with_checks (info);
1868 gdk_threads_leave ();
1871 result = info->result;
1873 gdk_threads_enter ();
1874 save_mime_part_info_free (info, TRUE);
1876 hildon_banner_show_information (NULL, NULL, _CS("sfil_ib_saved"));
1878 hildon_banner_show_information (NULL, NULL, _("mail_ib_file_operation_failed"));
1880 gdk_threads_leave ();
1887 save_mime_part_to_file (SaveMimePartInfo *info)
1889 GnomeVFSResult result;
1890 GnomeVFSHandle *handle;
1892 SaveMimePartPair *pair = (SaveMimePartPair *) info->pairs->data;
1894 result = gnome_vfs_create (&handle, pair->filename, GNOME_VFS_OPEN_WRITE, FALSE, 0777);
1895 if (result == GNOME_VFS_OK) {
1896 stream = tny_vfs_stream_new (handle);
1897 tny_mime_part_decode_to_stream (pair->part, stream);
1898 g_object_unref (G_OBJECT (stream));
1899 g_object_unref (pair->part);
1900 g_slice_free (SaveMimePartPair, pair);
1901 info->pairs = g_list_delete_link (info->pairs, info->pairs);
1902 info->result = TRUE;
1904 save_mime_part_info_free (info, FALSE);
1905 info->result = FALSE;
1908 g_idle_add ((GSourceFunc) idle_save_mime_part_show_result, info);
1913 save_mime_parts_to_file_with_checks (SaveMimePartInfo *info)
1915 SaveMimePartPair *pair;
1916 gboolean is_ok = TRUE;
1918 pair = info->pairs->data;
1919 if (modest_maemo_utils_file_exists (pair->filename)) {
1920 GtkWidget *confirm_overwrite_dialog;
1921 confirm_overwrite_dialog = hildon_note_new_confirmation (NULL,
1922 _("emev_nc_replace_files"));
1923 if (gtk_dialog_run (GTK_DIALOG (confirm_overwrite_dialog)) != GTK_RESPONSE_OK) {
1926 gtk_widget_destroy (confirm_overwrite_dialog);
1930 save_mime_part_info_free (info, TRUE);
1932 g_thread_create ((GThreadFunc)save_mime_part_to_file, info, FALSE, NULL);
1939 modest_msg_view_window_save_attachments (ModestMsgViewWindow *window, GList *mime_parts)
1941 gboolean clean_list = FALSE;
1942 ModestMsgViewWindowPrivate *priv;
1943 GList *files_to_save = NULL;
1944 GtkWidget *save_dialog = NULL;
1945 gchar *folder = NULL;
1946 gboolean canceled = FALSE;
1947 const gchar *filename = NULL;
1948 gchar *save_multiple_str = NULL;
1950 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
1951 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1953 if (mime_parts == NULL) {
1954 mime_parts = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
1955 if (mime_parts == NULL)
1960 /* prepare dialog */
1961 if (mime_parts->next == NULL) {
1962 /* only one attachment selected */
1963 TnyMimePart *mime_part = (TnyMimePart *) mime_parts->data;
1964 if (!TNY_IS_MSG (mime_part) && tny_mime_part_is_attachment (mime_part)) {
1965 filename = tny_mime_part_get_filename (mime_part);
1967 g_warning ("Tried to save a non-file attachment");
1971 save_multiple_str = g_strdup_printf (_("FIXME: %d attachments"),
1972 g_list_length (mime_parts));
1975 save_dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
1976 GTK_FILE_CHOOSER_ACTION_SAVE);
1979 folder = g_build_filename (g_get_home_dir (), DEFAULT_FOLDER, NULL);
1980 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (save_dialog), folder);
1984 if (filename != NULL)
1985 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (save_dialog),
1988 /* if multiple, set multiple string */
1989 if (save_multiple_str) {
1990 g_object_set (G_OBJECT (save_dialog), "save-multiple", save_multiple_str, NULL);
1994 if (gtk_dialog_run (GTK_DIALOG (save_dialog)) == GTK_RESPONSE_OK) {
1995 gchar *chooser_uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (save_dialog));
1997 if (!modest_maemo_utils_folder_writable (chooser_uri)) {
1998 hildon_banner_show_information
1999 (NULL, NULL, dgettext("hildon-fm", "sfil_ib_readonly_location"));
2003 for (node = mime_parts; node != NULL; node = g_list_next (node)) {
2004 TnyMimePart *mime_part = (TnyMimePart *) node->data;
2006 if (tny_mime_part_is_attachment (mime_part)) {
2007 SaveMimePartPair *pair;
2009 if ((mime_parts->next != NULL) &&
2010 (tny_mime_part_get_filename (mime_part) == NULL))
2013 pair = g_slice_new0 (SaveMimePartPair);
2014 if (mime_parts->next == NULL) {
2015 pair->filename = g_strdup (chooser_uri);
2018 g_build_filename (chooser_uri,
2019 tny_mime_part_get_filename (mime_part), NULL);
2021 pair->part = g_object_ref (mime_part);
2022 files_to_save = g_list_prepend (files_to_save, pair);
2026 g_free (chooser_uri);
2029 gtk_widget_destroy (save_dialog);
2032 g_list_foreach (mime_parts, (GFunc) g_object_unref, NULL);
2033 g_list_free (mime_parts);
2036 if (files_to_save != NULL) {
2037 SaveMimePartInfo *info = g_slice_new0 (SaveMimePartInfo);
2038 GtkWidget *banner = hildon_banner_show_animation (NULL, NULL,
2039 _CS("sfil_ib_saving"));
2040 info->pairs = files_to_save;
2041 info->banner = banner;
2042 info->result = TRUE;
2043 g_object_ref (banner);
2044 save_mime_parts_to_file_with_checks (info);
2049 modest_msg_view_window_remove_attachments (ModestMsgViewWindow *window, gboolean get_all)
2051 ModestMsgViewWindowPrivate *priv;
2052 GList *mime_parts = NULL, *node;
2053 gchar *confirmation_message;
2057 /* TnyFolder *folder; */
2059 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
2060 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
2063 mime_parts = modest_msg_view_get_attachments (MODEST_MSG_VIEW (priv->msg_view));
2065 mime_parts = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
2067 /* Remove already purged messages from mime parts list */
2069 while (node != NULL) {
2070 TnyMimePart *part = TNY_MIME_PART (node->data);
2071 if (tny_mime_part_is_purged (part)) {
2072 GList *deleted_node = node;
2073 node = g_list_next (node);
2074 g_object_unref (part);
2075 mime_parts = g_list_delete_link (mime_parts, deleted_node);
2077 node = g_list_next (node);
2081 if (mime_parts == NULL)
2084 n_attachments = g_list_length (mime_parts);
2085 if (n_attachments == 1) {
2086 const gchar *filename;
2088 if (TNY_IS_MSG (mime_parts->data)) {
2090 header = tny_msg_get_header (TNY_MSG (mime_parts->data));
2091 filename = tny_header_get_subject (header);
2092 g_object_unref (header);
2093 if (filename == NULL)
2094 filename = _("mail_va_no_subject");
2096 filename = tny_mime_part_get_filename (TNY_MIME_PART (mime_parts->data));
2098 confirmation_message = g_strdup_printf (_("mcen_nc_purge_file_text"), filename);
2100 confirmation_message = g_strdup_printf (ngettext("mcen_nc_purge_file_text",
2101 "mcen_nc_purge_files_text",
2102 n_attachments), n_attachments);
2104 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2105 confirmation_message);
2106 g_free (confirmation_message);
2108 if (response != GTK_RESPONSE_OK)
2111 /* folder = tny_msg_get_folder (msg); */
2112 /* tny_msg_uncache_attachments (msg); */
2113 /* tny_folder_refresh (folder, NULL); */
2114 /* g_object_unref (folder); */
2116 modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
2118 for (node = mime_parts; node != NULL; node = g_list_next (node)) {
2119 tny_mime_part_set_purged (TNY_MIME_PART (node->data));
2120 /* modest_msg_view_remove_attachment (MODEST_MSG_VIEW (priv->msg_view), node->data); */
2123 msg = modest_msg_view_get_message (MODEST_MSG_VIEW (priv->msg_view));
2124 modest_msg_view_set_message (MODEST_MSG_VIEW (priv->msg_view), NULL);
2125 tny_msg_rewrite_cache (msg);
2126 modest_msg_view_set_message (MODEST_MSG_VIEW (priv->msg_view), msg);
2128 g_list_foreach (mime_parts, (GFunc) g_object_unref, NULL);
2129 g_list_free (mime_parts);
2136 update_window_title (ModestMsgViewWindow *window)
2138 ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
2140 TnyHeader *header = NULL;
2141 const gchar *subject = NULL;
2143 msg = modest_msg_view_get_message (MODEST_MSG_VIEW (priv->msg_view));
2145 header = tny_msg_get_header (msg);
2146 subject = tny_header_get_subject (header);
2147 g_object_unref (msg);
2150 if ((subject == NULL)||(subject[0] == '\0'))
2151 subject = _("mail_va_no_subject");
2153 gtk_window_set_title (GTK_WINDOW (window), subject);