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_set_zoom (ModestWindow *window,
72 static gdouble modest_msg_view_window_get_zoom (ModestWindow *window);
73 static gboolean modest_msg_view_window_zoom_minus (ModestWindow *window);
74 static gboolean modest_msg_view_window_zoom_plus (ModestWindow *window);
75 static gboolean modest_msg_view_window_key_release_event (GtkWidget *window,
78 static gboolean modest_msg_view_window_window_state_event (GtkWidget *widget,
79 GdkEventWindowState *event,
81 static void modest_msg_view_window_scroll_up (ModestWindow *window);
82 static void modest_msg_view_window_scroll_down (ModestWindow *window);
83 static void modest_msg_view_window_update_priority (ModestMsgViewWindow *window);
85 static void modest_msg_view_window_show_toolbar (ModestWindow *window,
86 gboolean show_toolbar);
88 static void modest_msg_view_window_clipboard_owner_change (GtkClipboard *clipboard,
90 ModestMsgViewWindow *window);
92 static void cancel_progressbar (GtkToolButton *toolbutton,
93 ModestMsgViewWindow *self);
95 static void on_queue_changed (ModestMailOperationQueue *queue,
96 ModestMailOperation *mail_op,
97 ModestMailOperationQueueNotification type,
98 ModestMsgViewWindow *self);
100 static void on_account_removed (TnyAccountStore *account_store,
104 static void view_msg_cb (ModestMailOperation *mail_op,
109 static void set_toolbar_mode (ModestMsgViewWindow *self,
110 ModestToolBarModes mode);
112 static void update_window_title (ModestMsgViewWindow *window);
114 static gboolean set_toolbar_transfer_mode (ModestMsgViewWindow *self);
117 /* list my signals */
123 static const GtkToggleActionEntry msg_view_toggle_action_entries [] = {
124 { "FindInMessage", MODEST_TOOLBAR_ICON_FIND, N_("qgn_toolb_gene_find"), NULL, NULL, G_CALLBACK (modest_msg_view_window_toggle_find_toolbar), FALSE },
125 { "ToolsFindInMessage", NULL, N_("mcen_me_viewer_find"), NULL, NULL, G_CALLBACK (modest_msg_view_window_toggle_find_toolbar), FALSE },
128 static const GtkRadioActionEntry msg_view_zoom_action_entries [] = {
129 { "Zoom50", NULL, N_("mcen_me_viewer_50"), NULL, NULL, 50 },
130 { "Zoom80", NULL, N_("mcen_me_viewer_80"), NULL, NULL, 80 },
131 { "Zoom100", NULL, N_("mcen_me_viewer_100"), NULL, NULL, 100 },
132 { "Zoom120", NULL, N_("mcen_me_viewer_120"), NULL, NULL, 120 },
133 { "Zoom150", NULL, N_("mcen_me_viewer_150"), NULL, NULL, 150 },
134 { "Zoom200", NULL, N_("mcen_me_viewer_200"), NULL, NULL, 200 }
137 typedef struct _ModestMsgViewWindowPrivate ModestMsgViewWindowPrivate;
138 struct _ModestMsgViewWindowPrivate {
141 GtkWidget *main_scroll;
142 GtkWidget *find_toolbar;
145 /* Progress observers */
146 GtkWidget *progress_bar;
147 GSList *progress_widgets;
150 GtkWidget *progress_toolitem;
151 GtkWidget *cancel_toolitem;
152 GtkWidget *prev_toolitem;
153 GtkWidget *next_toolitem;
154 ModestToolBarModes current_toolbar_mode;
156 /* Optimized view enabled */
157 gboolean optimized_view;
159 GtkTreeModel *header_model;
160 GtkTreeRowReference *row_reference;
161 GtkTreeRowReference *next_row_reference;
163 guint clipboard_change_handler;
164 guint queue_change_handler;
165 guint account_removed_handler;
167 guint progress_bar_timeout;
172 #define MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
173 MODEST_TYPE_MSG_VIEW_WINDOW, \
174 ModestMsgViewWindowPrivate))
176 static GtkWindowClass *parent_class = NULL;
178 /* uncomment the following if you have defined any signals */
179 static guint signals[LAST_SIGNAL] = {0};
182 modest_msg_view_window_get_type (void)
184 static GType my_type = 0;
186 static const GTypeInfo my_info = {
187 sizeof(ModestMsgViewWindowClass),
188 NULL, /* base init */
189 NULL, /* base finalize */
190 (GClassInitFunc) modest_msg_view_window_class_init,
191 NULL, /* class finalize */
192 NULL, /* class data */
193 sizeof(ModestMsgViewWindow),
195 (GInstanceInitFunc) modest_msg_view_window_init,
198 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
199 "ModestMsgViewWindow",
206 save_state (ModestWindow *self)
208 modest_widget_memory_save (modest_runtime_get_conf (),
210 MODEST_CONF_MSG_VIEW_WINDOW_KEY);
215 restore_settings (ModestMsgViewWindow *self)
217 modest_widget_memory_restore (modest_runtime_get_conf (),
219 MODEST_CONF_MSG_VIEW_WINDOW_KEY);
223 modest_msg_view_window_class_init (ModestMsgViewWindowClass *klass)
225 GObjectClass *gobject_class;
226 ModestWindowClass *modest_window_class;
227 gobject_class = (GObjectClass*) klass;
228 modest_window_class = (ModestWindowClass *) klass;
230 parent_class = g_type_class_peek_parent (klass);
231 gobject_class->finalize = modest_msg_view_window_finalize;
233 modest_window_class->set_zoom_func = modest_msg_view_window_set_zoom;
234 modest_window_class->get_zoom_func = modest_msg_view_window_get_zoom;
235 modest_window_class->zoom_minus_func = modest_msg_view_window_zoom_minus;
236 modest_window_class->zoom_plus_func = modest_msg_view_window_zoom_plus;
237 modest_window_class->show_toolbar_func = modest_msg_view_window_show_toolbar;
239 g_type_class_add_private (gobject_class, sizeof(ModestMsgViewWindowPrivate));
241 modest_window_class->save_state_func = save_state;
243 signals[MSG_CHANGED_SIGNAL] =
244 g_signal_new ("msg-changed",
245 G_TYPE_FROM_CLASS (gobject_class),
247 G_STRUCT_OFFSET (ModestMsgViewWindowClass, msg_changed),
249 modest_marshal_VOID__POINTER_POINTER,
250 G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER);
254 modest_msg_view_window_init (ModestMsgViewWindow *obj)
256 ModestMsgViewWindowPrivate *priv;
257 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(obj);
259 priv->msg_view = NULL;
260 priv->header_model = NULL;
261 priv->clipboard_change_handler = 0;
262 priv->queue_change_handler = 0;
263 priv->account_removed_handler = 0;
264 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
266 priv->optimized_view = FALSE;
267 priv->progress_bar_timeout = 0;
268 priv->msg_uid = NULL;
273 set_toolbar_transfer_mode (ModestMsgViewWindow *self)
275 ModestMsgViewWindowPrivate *priv = NULL;
277 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), FALSE);
279 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
281 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
283 if (priv->progress_bar_timeout > 0) {
284 g_source_remove (priv->progress_bar_timeout);
285 priv->progress_bar_timeout = 0;
292 set_toolbar_mode (ModestMsgViewWindow *self,
293 ModestToolBarModes mode)
295 ModestWindowPrivate *parent_priv;
296 ModestMsgViewWindowPrivate *priv;
297 /* GtkWidget *widget = NULL; */
299 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self));
301 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
302 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
304 /* Sets current toolbar mode */
305 priv->current_toolbar_mode = mode;
307 /* Update toolbar dimming state */
308 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
311 case TOOLBAR_MODE_NORMAL:
312 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply"); */
313 /* gtk_action_set_sensitive (widget, TRUE); */
314 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage"); */
315 /* gtk_action_set_sensitive (widget, TRUE); */
316 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarMessageMoveTo"); */
317 /* gtk_action_set_sensitive (widget, TRUE); */
318 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/FindInMessage"); */
319 /* gtk_action_set_sensitive (widget, TRUE); */
321 if (priv->prev_toolitem)
322 gtk_widget_show (priv->prev_toolitem);
324 if (priv->next_toolitem)
325 gtk_widget_show (priv->next_toolitem);
327 if (priv->progress_toolitem)
328 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
329 if (priv->progress_bar)
330 gtk_widget_hide (priv->progress_bar);
332 if (priv->cancel_toolitem)
333 gtk_widget_hide (priv->cancel_toolitem);
335 /* Hide toolbar if optimized view is enabled */
336 if (priv->optimized_view) {
337 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
338 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
342 case TOOLBAR_MODE_TRANSFER:
343 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply"); */
344 /* gtk_action_set_sensitive (widget, FALSE); */
345 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage"); */
346 /* gtk_action_set_sensitive (widget, FALSE); */
347 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarMessageMoveTo"); */
348 /* gtk_action_set_sensitive (widget, FALSE); */
349 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/FindInMessage"); */
350 /* gtk_action_set_sensitive (widget, FALSE); */
352 if (priv->prev_toolitem)
353 gtk_widget_hide (priv->prev_toolitem);
355 if (priv->next_toolitem)
356 gtk_widget_hide (priv->next_toolitem);
358 if (priv->progress_toolitem)
359 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
360 if (priv->progress_bar)
361 gtk_widget_show (priv->progress_bar);
363 if (priv->cancel_toolitem)
364 gtk_widget_show (priv->cancel_toolitem);
366 /* Show toolbar if it's hiden (optimized view ) */
367 if (priv->optimized_view) {
368 gtk_widget_set_no_show_all (parent_priv->toolbar, FALSE);
369 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
374 g_return_if_reached ();
381 menubar_to_menu (GtkUIManager *ui_manager)
383 GtkWidget *main_menu;
387 /* Create new main menu */
388 main_menu = gtk_menu_new();
390 /* Get the menubar from the UI manager */
391 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
393 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
397 menu = GTK_WIDGET (iter->data);
398 gtk_widget_reparent(menu, main_menu);
400 iter = g_list_next (iter);
406 init_window (ModestMsgViewWindow *obj, TnyMsg *msg)
408 GtkWidget *main_vbox;
409 ModestMsgViewWindowPrivate *priv;
410 ModestWindowPrivate *parent_priv;
412 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(obj);
413 parent_priv = MODEST_WINDOW_GET_PRIVATE(obj);
415 priv->msg_view = modest_msg_view_new (msg);
416 modest_msg_view_set_shadow_type (MODEST_MSG_VIEW (priv->msg_view), GTK_SHADOW_NONE);
417 main_vbox = gtk_vbox_new (FALSE, 6);
420 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
421 gtk_widget_show_all (GTK_WIDGET(parent_priv->menubar));
422 hildon_window_set_menu (HILDON_WINDOW(obj), GTK_MENU(parent_priv->menubar));
424 priv->main_scroll = gtk_scrolled_window_new (NULL, NULL);
425 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->main_scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
426 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->main_scroll), GTK_SHADOW_NONE);
427 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->main_scroll), TRUE);
429 gtk_container_add (GTK_CONTAINER (priv->main_scroll), priv->msg_view);
430 gtk_box_pack_start (GTK_BOX(main_vbox), priv->main_scroll, TRUE, TRUE, 0);
431 gtk_container_add (GTK_CONTAINER(obj), main_vbox);
433 priv->find_toolbar = hildon_find_toolbar_new (NULL);
434 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
435 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
436 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_view_window_find_toolbar_close), obj);
437 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_view_window_find_toolbar_search), obj);
439 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);
440 gtk_widget_show_all (GTK_WIDGET(main_vbox));
446 modest_msg_view_window_finalize (GObject *obj)
448 ModestMsgViewWindowPrivate *priv;
450 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (obj);
451 if (priv->clipboard_change_handler > 0) {
452 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
453 priv->clipboard_change_handler);
454 priv->clipboard_change_handler = 0;
456 if (priv->queue_change_handler > 0) {
457 g_signal_handler_disconnect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
458 priv->queue_change_handler);
459 priv->queue_change_handler = 0;
461 if (priv->account_removed_handler > 0) {
462 g_signal_handler_disconnect (G_OBJECT (modest_runtime_get_account_store ()),
463 priv->account_removed_handler);
464 priv->account_removed_handler = 0;
466 if (priv->header_model != NULL) {
467 g_object_unref (priv->header_model);
468 priv->header_model = NULL;
471 if (priv->progress_bar_timeout > 0) {
472 g_source_remove (priv->progress_bar_timeout);
473 priv->progress_bar_timeout = 0;
476 if (priv->row_reference) {
477 gtk_tree_row_reference_free (priv->row_reference);
478 priv->row_reference = NULL;
481 if (priv->next_row_reference) {
482 gtk_tree_row_reference_free (priv->next_row_reference);
483 priv->next_row_reference = NULL;
487 g_free (priv->msg_uid);
488 priv->msg_uid = NULL;
491 G_OBJECT_CLASS(parent_class)->finalize (obj);
495 select_next_valid_row (GtkTreeModel *model,
496 GtkTreeRowReference **row_reference,
499 GtkTreeIter tmp_iter;
500 GtkTreePath *path, *next;
501 gboolean retval = FALSE;
503 g_return_val_if_fail (gtk_tree_row_reference_valid (*row_reference), FALSE);
505 path = gtk_tree_row_reference_get_path (*row_reference);
506 gtk_tree_model_get_iter (model, &tmp_iter, path);
507 gtk_tree_row_reference_free (*row_reference);
508 *row_reference = NULL;
510 if (gtk_tree_model_iter_next (model, &tmp_iter)) {
511 next = gtk_tree_model_get_path (model, &tmp_iter);
512 *row_reference = gtk_tree_row_reference_new (model, next);
514 } else if (cycle && gtk_tree_model_get_iter_first (model, &tmp_iter)) {
515 next = gtk_tree_model_get_path (model, &tmp_iter);
517 /* Ensure that we are not selecting the same */
518 if (gtk_tree_path_compare (path, next) != 0) {
519 *row_reference = gtk_tree_row_reference_new (model, next);
525 gtk_tree_path_free (path);
531 modest_msg_view_window_new_with_header_model (TnyMsg *msg,
532 const gchar *modest_account_name,
533 const gchar *msg_uid,
535 GtkTreeRowReference *row_reference)
537 ModestMsgViewWindow *window = NULL;
538 ModestMsgViewWindowPrivate *priv = NULL;
540 window = MODEST_MSG_VIEW_WINDOW(modest_msg_view_window_new (msg, modest_account_name, msg_uid));
541 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), NULL);
543 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
545 g_object_ref (model);
546 priv->header_model = model;
547 priv->row_reference = gtk_tree_row_reference_copy (row_reference);
548 priv->next_row_reference = gtk_tree_row_reference_copy (row_reference);
549 select_next_valid_row (model, &(priv->next_row_reference), TRUE);
551 modest_msg_view_window_update_priority (window);
553 /* Check toolbar dimming rules */
554 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
556 return MODEST_WINDOW(window);
561 modest_msg_view_window_new (TnyMsg *msg,
562 const gchar *modest_account_name,
563 const gchar *msg_uid)
565 ModestMsgViewWindow *self = NULL;
567 ModestMsgViewWindowPrivate *priv = NULL;
568 ModestWindowPrivate *parent_priv = NULL;
569 ModestDimmingRulesGroup *menu_rules_group = NULL;
570 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
571 GtkActionGroup *action_group = NULL;
572 GError *error = NULL;
573 GdkPixbuf *window_icon;
575 g_return_val_if_fail (msg, NULL);
577 obj = g_object_new(MODEST_TYPE_MSG_VIEW_WINDOW, NULL);
578 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(obj);
579 parent_priv = MODEST_WINDOW_GET_PRIVATE(obj);
580 self = MODEST_MSG_VIEW_WINDOW (obj);
582 priv->msg_uid = g_strdup (msg_uid);
584 parent_priv->ui_manager = gtk_ui_manager_new();
585 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
587 action_group = gtk_action_group_new ("ModestMsgViewWindowActions");
588 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
590 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
591 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
593 /* Add common actions */
594 gtk_action_group_add_actions (action_group,
595 modest_action_entries,
596 G_N_ELEMENTS (modest_action_entries),
598 gtk_action_group_add_toggle_actions (action_group,
599 modest_toggle_action_entries,
600 G_N_ELEMENTS (modest_toggle_action_entries),
602 gtk_action_group_add_toggle_actions (action_group,
603 msg_view_toggle_action_entries,
604 G_N_ELEMENTS (msg_view_toggle_action_entries),
606 gtk_action_group_add_radio_actions (action_group,
607 msg_view_zoom_action_entries,
608 G_N_ELEMENTS (msg_view_zoom_action_entries),
610 G_CALLBACK (modest_ui_actions_on_change_zoom),
613 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
614 g_object_unref (action_group);
616 /* Load the UI definition */
617 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-view-window-ui.xml",
620 g_printerr ("modest: could not merge modest-msg-view-window-ui.xml: %s\n", error->message);
621 g_error_free (error);
626 /* Add common dimming rules */
627 modest_dimming_rules_group_add_rules (menu_rules_group,
628 modest_msg_view_menu_dimming_entries,
629 G_N_ELEMENTS (modest_msg_view_menu_dimming_entries),
631 modest_dimming_rules_group_add_rules (toolbar_rules_group,
632 modest_msg_view_toolbar_dimming_entries,
633 G_N_ELEMENTS (modest_msg_view_toolbar_dimming_entries),
636 /* Insert dimming rules group for this window */
637 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
638 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
639 g_object_unref (menu_rules_group);
640 g_object_unref (toolbar_rules_group);
642 /* Add accelerators */
643 gtk_window_add_accel_group (GTK_WINDOW (obj),
644 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
647 init_window (MODEST_MSG_VIEW_WINDOW(obj), msg);
648 restore_settings (MODEST_MSG_VIEW_WINDOW(obj));
650 /* Set window icon */
651 window_icon = modest_platform_get_icon (MODEST_APP_MSG_VIEW_ICON);
653 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
654 g_object_unref (window_icon);
657 /* g_signal_connect (G_OBJECT(obj), "delete-event", G_CALLBACK(on_delete_event), obj); */
659 g_signal_connect (G_OBJECT(priv->msg_view), "link_clicked",
660 G_CALLBACK (modest_ui_actions_on_msg_link_clicked), obj);
661 g_signal_connect (G_OBJECT(priv->msg_view), "link_hover",
662 G_CALLBACK (modest_ui_actions_on_msg_link_hover), obj);
663 g_signal_connect (G_OBJECT(priv->msg_view), "attachment_clicked",
664 G_CALLBACK (modest_ui_actions_on_msg_attachment_clicked), obj);
665 g_signal_connect (G_OBJECT(priv->msg_view), "recpt_activated",
666 G_CALLBACK (modest_ui_actions_on_msg_recpt_activated), obj);
667 g_signal_connect (G_OBJECT(priv->msg_view), "link_contextual",
668 G_CALLBACK (modest_ui_actions_on_msg_link_contextual), obj);
670 g_signal_connect (G_OBJECT (obj), "key-release-event",
671 G_CALLBACK (modest_msg_view_window_key_release_event),
674 g_signal_connect (G_OBJECT (obj), "window-state-event",
675 G_CALLBACK (modest_msg_view_window_window_state_event),
678 /* Mail Operation Queue */
679 priv->queue_change_handler = g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
681 G_CALLBACK (on_queue_changed),
684 /* Account manager */
685 priv->account_removed_handler = g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
687 G_CALLBACK(on_account_removed),
690 modest_window_set_active_account (MODEST_WINDOW(obj), modest_account_name);
692 priv->last_search = NULL;
694 /* Init the clipboard actions dim status */
695 modest_msg_view_grab_focus(MODEST_MSG_VIEW (priv->msg_view));
697 update_window_title (MODEST_MSG_VIEW_WINDOW (obj));
699 /* Check toolbar dimming rules */
700 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
702 return MODEST_WINDOW(obj);
707 modest_msg_view_window_toolbar_on_transfer_mode (ModestMsgViewWindow *self)
709 ModestMsgViewWindowPrivate *priv= NULL;
711 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), FALSE);
712 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
714 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
718 modest_msg_view_window_get_header (ModestMsgViewWindow *self)
720 ModestMsgViewWindowPrivate *priv= NULL;
722 TnyHeader *header = NULL;
723 GtkTreePath *path = NULL;
726 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), NULL);
727 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
729 /* Message is not obtained from a treemodel (Attachment ?) */
730 if (priv->header_model == NULL) {
731 msg = modest_msg_view_window_get_message (self);
732 header = tny_msg_get_header (msg);
733 g_object_unref (msg);
737 /* Get current message iter */
738 path = gtk_tree_row_reference_get_path (priv->row_reference);
739 g_return_val_if_fail (path != NULL, NULL);
740 gtk_tree_model_get_iter (priv->header_model,
744 /* Get current message header */
745 gtk_tree_model_get (priv->header_model, &iter,
746 TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
749 gtk_tree_path_free (path);
754 modest_msg_view_window_get_message (ModestMsgViewWindow *self)
756 ModestMsgView *msg_view;
757 ModestMsgViewWindowPrivate *priv;
759 g_return_val_if_fail (self, NULL);
761 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
763 msg_view = MODEST_MSG_VIEW (priv->msg_view);
765 return modest_msg_view_get_message (msg_view);
769 modest_msg_view_window_get_message_uid (ModestMsgViewWindow *self)
771 ModestMsgViewWindowPrivate *priv;
773 g_return_val_if_fail (self, NULL);
775 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
777 return (const gchar*) priv->msg_uid;
781 modest_msg_view_window_toggle_find_toolbar (GtkToggleAction *toggle,
784 ModestMsgViewWindow *window = MODEST_MSG_VIEW_WINDOW (data);
785 ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
786 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
790 is_active = gtk_toggle_action_get_active (toggle);
793 gtk_widget_show (priv->find_toolbar);
794 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
796 gtk_widget_hide (priv->find_toolbar);
799 /* update the toggle buttons status */
800 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/FindInMessage");
801 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), is_active);
802 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/ToolsFindInMessageMenu");
803 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), is_active);
808 modest_msg_view_window_find_toolbar_close (GtkWidget *widget,
809 ModestMsgViewWindow *obj)
811 GtkToggleAction *toggle;
812 ModestWindowPrivate *parent_priv;
813 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
815 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/FindInMessage"));
816 gtk_toggle_action_set_active (toggle, FALSE);
820 modest_msg_view_window_find_toolbar_search (GtkWidget *widget,
821 ModestMsgViewWindow *obj)
823 gchar *current_search;
824 ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (obj);
826 if (modest_msg_view_get_message_is_empty (MODEST_MSG_VIEW (priv->msg_view))) {
827 hildon_banner_show_information (NULL, NULL, _("mail_ib_nothing_to_find"));
831 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
833 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
834 g_free (current_search);
835 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
839 if ((priv->last_search == NULL) || (strcmp (priv->last_search, current_search) != 0)) {
841 g_free (priv->last_search);
842 priv->last_search = g_strdup (current_search);
843 result = modest_msg_view_search (MODEST_MSG_VIEW (priv->msg_view),
846 hildon_banner_show_information (NULL, NULL, dgettext("hildon-libs", "ckct_ib_find_no_matches"));
847 g_free (priv->last_search);
848 priv->last_search = NULL;
851 if (!modest_msg_view_search_next (MODEST_MSG_VIEW (priv->msg_view))) {
852 hildon_banner_show_information (NULL, NULL, dgettext("hildon-libs", "ckct_ib_find_search_complete"));
853 g_free (priv->last_search);
854 priv->last_search = NULL;
858 g_free (current_search);
863 modest_msg_view_window_set_zoom (ModestWindow *window,
866 ModestMsgViewWindowPrivate *priv;
868 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
870 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
871 modest_msg_view_set_zoom (MODEST_MSG_VIEW (priv->msg_view), zoom);
875 modest_msg_view_window_get_zoom (ModestWindow *window)
877 ModestMsgViewWindowPrivate *priv;
879 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), 1.0);
881 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
882 return modest_msg_view_get_zoom (MODEST_MSG_VIEW (priv->msg_view));
886 modest_msg_view_window_zoom_plus (ModestWindow *window)
888 ModestWindowPrivate *parent_priv;
889 GtkRadioAction *zoom_radio_action;
890 GSList *group, *node;
892 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
893 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
894 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
896 group = gtk_radio_action_get_group (zoom_radio_action);
898 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
899 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
903 for (node = group; node != NULL; node = g_slist_next (node)) {
904 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
905 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
913 modest_msg_view_window_zoom_minus (ModestWindow *window)
915 ModestWindowPrivate *parent_priv;
916 GtkRadioAction *zoom_radio_action;
917 GSList *group, *node;
919 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
920 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
921 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
923 group = gtk_radio_action_get_group (zoom_radio_action);
925 for (node = group; node != NULL; node = g_slist_next (node)) {
926 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
927 if (node->next != NULL) {
928 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
931 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
941 modest_msg_view_window_key_release_event (GtkWidget *window,
945 if (event->type == GDK_KEY_RELEASE) {
946 switch (event->keyval) {
948 modest_msg_view_window_scroll_up (MODEST_WINDOW (window));
952 modest_msg_view_window_scroll_down (MODEST_WINDOW (window));
965 modest_msg_view_window_scroll_up (ModestWindow *window)
967 ModestMsgViewWindowPrivate *priv;
968 gboolean return_value;
970 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
971 g_signal_emit_by_name (G_OBJECT (priv->main_scroll), "scroll-child", GTK_SCROLL_STEP_UP, FALSE, &return_value);
975 modest_msg_view_window_scroll_down (ModestWindow *window)
977 ModestMsgViewWindowPrivate *priv;
978 gboolean return_value;
980 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
981 g_signal_emit_by_name (G_OBJECT (priv->main_scroll), "scroll-child", GTK_SCROLL_STEP_DOWN, FALSE, &return_value);
985 modest_msg_view_window_last_message_selected (ModestMsgViewWindow *window)
988 ModestMsgViewWindowPrivate *priv;
989 GtkTreeIter tmp_iter;
990 gboolean has_next = FALSE;
992 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), TRUE);
993 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
995 if (priv->header_model) {
996 path = gtk_tree_row_reference_get_path (priv->row_reference);
997 if (path == NULL) return FALSE;
1000 gtk_tree_path_next (path);
1001 if (!gtk_tree_model_get_iter (priv->header_model, &tmp_iter, path))
1003 gtk_tree_model_get (priv->header_model, &tmp_iter, TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
1005 if (!(tny_header_get_flags(header)&TNY_HEADER_FLAG_DELETED)) {
1010 gtk_tree_path_free (path);
1019 modest_msg_view_window_has_headers_model (ModestMsgViewWindow *window)
1021 ModestMsgViewWindowPrivate *priv;
1023 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), TRUE);
1024 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1026 return priv->header_model != NULL;
1030 modest_msg_view_window_first_message_selected (ModestMsgViewWindow *window)
1033 ModestMsgViewWindowPrivate *priv;
1035 GtkTreeIter tmp_iter;
1037 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), TRUE);
1038 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1040 if (priv->header_model) {
1041 gchar * path_string;
1042 path = gtk_tree_row_reference_get_path (priv->row_reference);
1046 path_string = gtk_tree_path_to_string (path);
1047 result = (strcmp (path_string, "0")==0);
1049 g_free (path_string);
1050 gtk_tree_path_free (path);
1057 gtk_tree_path_prev (path);
1059 if (!gtk_tree_model_get_iter (priv->header_model, &tmp_iter, path))
1061 gtk_tree_model_get (priv->header_model, &tmp_iter, TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
1063 if (!(tny_header_get_flags(header)&TNY_HEADER_FLAG_DELETED)) {
1068 path_string = gtk_tree_path_to_string (path);
1069 if (strcmp(path_string, "0")==0) {
1070 g_free (path_string);
1073 g_free (path_string);
1075 gtk_tree_path_free (path);
1084 * Reads the message whose summary item is @header. It takes care of
1085 * several things, among others:
1087 * If the message was not previously downloaded then ask the user
1088 * before downloading. If there is no connection launch the connection
1089 * dialog. Update toolbar dimming rules.
1091 * Returns: TRUE if the mail operation was started, otherwise if the
1092 * user do not want to download the message, or if the user do not
1093 * want to connect, then the operation is not issued
1096 message_reader (ModestMsgViewWindow *window,
1097 ModestMsgViewWindowPrivate *priv,
1101 ModestMailOperation *mail_op = NULL;
1102 ModestMailOperationTypeOperation op_type;
1104 g_return_val_if_fail (path != NULL, FALSE);
1106 /* Msg download completed */
1107 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED) {
1108 op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
1111 GtkResponseType response;
1113 op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1115 /* Ask the user if he wants to download the message */
1116 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
1117 _("mcen_nc_get_msg"));
1118 if (response == GTK_RESPONSE_CANCEL)
1121 /* Offer the connection dialog if necessary */
1122 /* FIXME: should this stuff go directly to the mail
1123 operation instead of spread it all over the
1125 folder = tny_header_get_folder (header);
1127 if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, TNY_FOLDER_STORE (folder))) {
1128 g_object_unref (folder);
1131 g_object_unref (folder);
1135 /* New mail operation */
1136 mail_op = modest_mail_operation_new_with_error_handling (op_type,
1138 modest_ui_actions_get_msgs_full_error_handler,
1141 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1142 modest_mail_operation_get_msg (mail_op, header, view_msg_cb, path);
1143 g_object_unref (mail_op);
1145 /* Update toolbar dimming rules */
1146 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
1152 modest_msg_view_window_select_next_message (ModestMsgViewWindow *window)
1154 ModestMsgViewWindowPrivate *priv;
1155 GtkTreePath *path= NULL;
1156 GtkTreeIter tmp_iter;
1158 gboolean retval = TRUE;
1160 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), FALSE);
1161 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1163 /* Update the next row reference if it's not valid. This could
1164 happen if for example the header which it was pointing to,
1165 was deleted. The best place to do it is in the row-deleted
1166 handler but the tinymail model do not work like the glib
1167 tree models and reports the deletion when the row is still
1169 if (!gtk_tree_row_reference_valid (priv->next_row_reference)) {
1170 if (gtk_tree_row_reference_valid (priv->row_reference)) {
1171 priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference);
1172 select_next_valid_row (priv->header_model, &(priv->next_row_reference), FALSE);
1175 if (priv->next_row_reference)
1176 path = gtk_tree_row_reference_get_path (priv->next_row_reference);
1180 gtk_tree_model_get_iter (priv->header_model,
1184 gtk_tree_model_get (priv->header_model, &tmp_iter,
1185 TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
1188 /* Read the message & show it */
1189 if (!message_reader (window, priv, header, path)) {
1191 gtk_tree_path_free (path);
1195 g_object_unref (header);
1201 modest_msg_view_window_select_first_message (ModestMsgViewWindow *self)
1203 ModestMsgViewWindowPrivate *priv = NULL;
1204 TnyHeader *header = NULL;
1208 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), FALSE);
1209 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
1211 /* Check that the model is not empty */
1212 if (!gtk_tree_model_get_iter_first (priv->header_model, &iter))
1215 /* Get the header */
1216 gtk_tree_model_get (priv->header_model,
1218 TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
1220 g_return_val_if_fail (TNY_IS_HEADER (header), FALSE);
1221 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_DELETED) {
1222 g_object_unref (header);
1223 return modest_msg_view_window_select_next_message (self);
1226 path = gtk_tree_model_get_path (priv->header_model, &iter);
1228 /* Read the message & show it */
1229 message_reader (self, priv, header, path);
1232 g_object_unref (header);
1238 modest_msg_view_window_select_previous_message (ModestMsgViewWindow *window)
1240 ModestMsgViewWindowPrivate *priv = NULL;
1243 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), FALSE);
1244 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1246 /* Return inmediatly if there is no header model */
1247 if (!priv->header_model)
1250 path = gtk_tree_row_reference_get_path (priv->row_reference);
1251 while (gtk_tree_path_prev (path)) {
1255 gtk_tree_model_get_iter (priv->header_model, &iter, path);
1256 gtk_tree_model_get (priv->header_model, &iter,
1257 TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
1261 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_DELETED) {
1262 g_object_unref (header);
1266 /* Read the message & show it */
1267 if (!message_reader (window, priv, header, path)) {
1268 g_object_unref (header);
1272 g_object_unref (header);
1277 gtk_tree_path_free (path);
1282 view_msg_cb (ModestMailOperation *mail_op,
1287 ModestMsgViewWindow *self = NULL;
1288 ModestMsgViewWindowPrivate *priv = NULL;
1291 /* If there was any error */
1292 path = (GtkTreePath *) user_data;
1293 if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
1294 gtk_tree_path_free (path);
1298 /* Get the window */
1299 self = (ModestMsgViewWindow *) modest_mail_operation_get_source (mail_op);
1300 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self));
1301 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
1303 /* Update the row reference */
1304 gtk_tree_row_reference_free (priv->row_reference);
1305 priv->row_reference = gtk_tree_row_reference_new (priv->header_model, path);
1306 priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference);
1307 select_next_valid_row (priv->header_model, &(priv->next_row_reference), TRUE);
1308 gtk_tree_path_free (path);
1310 /* Mark header as read */
1311 if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_SEEN))
1312 tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
1314 /* Set new message */
1315 modest_msg_view_set_message (MODEST_MSG_VIEW (priv->msg_view), msg);
1316 modest_msg_view_window_update_priority (self);
1317 update_window_title (MODEST_MSG_VIEW_WINDOW (self));
1318 modest_msg_view_grab_focus (MODEST_MSG_VIEW (priv->msg_view));
1320 /* Set the new message uid of the window */
1321 if (priv->msg_uid) {
1322 g_free (priv->msg_uid);
1323 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1326 /* Notify the observers */
1327 g_signal_emit (G_OBJECT (self), signals[MSG_CHANGED_SIGNAL],
1328 0, priv->header_model, priv->row_reference);
1330 /* Free new references */
1331 g_object_unref (self);
1335 modest_msg_view_window_get_folder_type (ModestMsgViewWindow *window)
1337 ModestMsgViewWindowPrivate *priv;
1339 TnyFolderType folder_type;
1341 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1343 folder_type = TNY_FOLDER_TYPE_UNKNOWN;
1345 msg = modest_msg_view_get_message (MODEST_MSG_VIEW (priv->msg_view));
1349 folder = tny_msg_get_folder (msg);
1352 folder_type = tny_folder_get_folder_type (folder);
1354 if (folder_type == TNY_FOLDER_TYPE_NORMAL || folder_type == TNY_FOLDER_TYPE_UNKNOWN) {
1355 const gchar *fname = tny_folder_get_name (folder);
1356 folder_type = modest_tny_folder_guess_folder_type_from_name (fname);
1359 g_object_unref (folder);
1361 g_object_unref (msg);
1369 modest_msg_view_window_update_priority (ModestMsgViewWindow *window)
1371 ModestMsgViewWindowPrivate *priv;
1372 TnyHeaderFlags flags = 0;
1374 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1376 if (priv->header_model) {
1379 GtkTreePath *path = NULL;
1381 path = gtk_tree_row_reference_get_path (priv->row_reference);
1382 g_return_if_fail (path != NULL);
1383 gtk_tree_model_get_iter (priv->header_model,
1385 gtk_tree_row_reference_get_path (priv->row_reference));
1387 gtk_tree_model_get (priv->header_model, &iter, TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
1389 flags = tny_header_get_flags (header);
1390 gtk_tree_path_free (path);
1393 modest_msg_view_set_priority (MODEST_MSG_VIEW(priv->msg_view), flags);
1398 modest_msg_view_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1400 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1401 ModestWindowPrivate *parent_priv;
1402 ModestWindowMgr *mgr;
1403 gboolean is_fullscreen;
1404 GtkAction *fs_toggle_action;
1407 mgr = modest_runtime_get_window_mgr ();
1408 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
1410 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1412 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1413 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1414 if (is_fullscreen != active) {
1415 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1424 modest_msg_view_window_toggle_fullscreen (ModestMsgViewWindow *window)
1426 ModestWindowPrivate *parent_priv;
1427 GtkAction *fs_toggle_action;
1428 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1430 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1431 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action),
1432 !gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)));
1436 set_homogeneous (GtkWidget *widget,
1439 if (GTK_IS_TOOL_ITEM (widget)) {
1440 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1441 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1446 modest_msg_view_window_show_toolbar (ModestWindow *self,
1447 gboolean show_toolbar)
1449 ModestMsgViewWindowPrivate *priv = NULL;
1450 ModestWindowPrivate *parent_priv;
1451 GtkWidget *reply_button = NULL, *menu = NULL;
1452 GtkWidget *placeholder = NULL;
1455 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1456 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
1458 /* Set optimized view status */
1459 priv->optimized_view = !show_toolbar;
1461 if (!parent_priv->toolbar) {
1462 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1465 /* Set homogeneous toolbar */
1466 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1467 set_homogeneous, NULL);
1469 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1470 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1471 priv->next_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNext");
1472 priv->prev_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageBack");
1473 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1474 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1475 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1476 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1478 /* Add ProgressBar (Transfer toolbar) */
1479 priv->progress_bar = modest_progress_bar_widget_new ();
1480 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1481 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressbarView");
1482 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1483 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1484 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1486 /* Connect cancel 'clicked' signal to abort progress mode */
1487 g_signal_connect(priv->cancel_toolitem, "clicked",
1488 G_CALLBACK(cancel_progressbar),
1491 /* Add it to the observers list */
1492 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1495 hildon_window_add_toolbar (HILDON_WINDOW (self),
1496 GTK_TOOLBAR (parent_priv->toolbar));
1499 /* Set reply button tap and hold menu */
1500 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1501 "/ToolBar/ToolbarMessageReply");
1502 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1503 "/ToolbarReplyCSM");
1504 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1508 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1509 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1510 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1512 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1513 set_toolbar_mode (MODEST_MSG_VIEW_WINDOW(self), TOOLBAR_MODE_NORMAL);
1516 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1517 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1522 modest_msg_view_window_clipboard_owner_change (GtkClipboard *clipboard,
1524 ModestMsgViewWindow *window)
1526 ModestWindowPrivate *parent_priv;
1527 /* GtkAction *action; */
1528 gboolean is_address;
1532 if (!GTK_WIDGET_VISIBLE (window))
1535 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1536 selection = gtk_clipboard_wait_for_text (clipboard);
1538 is_address = ((selection != NULL) && (modest_text_utils_validate_recipient (selection, NULL)));
1540 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/ToolsAddToContactsMenu"); */
1541 /* gtk_action_set_sensitive (action, is_address); */
1543 focused = gtk_window_get_focus (GTK_WINDOW (window));
1545 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/EditCopyMenu"); */
1546 /* gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused))); */
1548 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/EditCutMenu"); */
1549 /* gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused))); */
1552 /* modest_msg_view_window_update_dimmed (window); */
1557 modest_msg_view_window_transfer_mode_enabled (ModestMsgViewWindow *self)
1559 ModestMsgViewWindowPrivate *priv;
1561 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), FALSE);
1562 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
1564 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
1568 cancel_progressbar (GtkToolButton *toolbutton,
1569 ModestMsgViewWindow *self)
1572 ModestMsgViewWindowPrivate *priv;
1574 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
1576 /* Get operation observers and cancel its current operation */
1577 tmp = priv->progress_widgets;
1579 modest_progress_object_cancel_current_operation (MODEST_PROGRESS_OBJECT(tmp->data));
1580 tmp=g_slist_next(tmp);
1584 observers_empty (ModestMsgViewWindow *self)
1587 ModestMsgViewWindowPrivate *priv;
1588 gboolean is_empty = TRUE;
1589 guint pending_ops = 0;
1591 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
1592 tmp = priv->progress_widgets;
1594 /* Check all observers */
1595 while (tmp && is_empty) {
1596 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1597 is_empty = pending_ops == 0;
1599 tmp = g_slist_next(tmp);
1606 on_account_removed (TnyAccountStore *account_store,
1607 TnyAccount *account,
1610 /* Do nothing if it's a transport account, because we only
1611 show the messages of a store account */
1612 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_STORE) {
1613 const gchar *parent_acc = NULL;
1614 const gchar *our_acc = NULL;
1616 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
1617 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
1619 /* Close this window if I'm showing a message of the removed account */
1620 if (strcmp (parent_acc, our_acc) == 0)
1621 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
1626 on_queue_changed (ModestMailOperationQueue *queue,
1627 ModestMailOperation *mail_op,
1628 ModestMailOperationQueueNotification type,
1629 ModestMsgViewWindow *self)
1632 ModestMsgViewWindowPrivate *priv;
1633 ModestMailOperationTypeOperation op_type;
1634 ModestToolBarModes mode;
1636 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self));
1637 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
1639 /* If this operations was created by another window, do nothing */
1640 if (!modest_mail_operation_is_mine (mail_op, G_OBJECT(self)))
1643 /* Get toolbar mode from operation id*/
1644 op_type = modest_mail_operation_get_type_operation (mail_op);
1646 /* case MODEST_MAIL_OPERATION_TYPE_SEND: */
1647 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
1648 case MODEST_MAIL_OPERATION_TYPE_OPEN:
1649 mode = TOOLBAR_MODE_TRANSFER;
1652 mode = TOOLBAR_MODE_NORMAL;
1656 /* Add operation observers and change toolbar if neccessary*/
1657 tmp = priv->progress_widgets;
1659 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
1660 if (mode == TOOLBAR_MODE_TRANSFER) {
1661 /* Enable transfer toolbar mode */
1662 set_toolbar_transfer_mode(self);
1664 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1666 tmp = g_slist_next (tmp);
1671 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
1672 if (mode == TOOLBAR_MODE_TRANSFER) {
1674 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1676 tmp = g_slist_next (tmp);
1680 /* If no more operations are being observed, NORMAL mode is enabled again */
1681 if (observers_empty (self)) {
1682 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
1690 modest_msg_view_window_get_attachments (ModestMsgViewWindow *win)
1692 ModestMsgViewWindowPrivate *priv;
1693 GList *selected_attachments = NULL;
1695 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (win), NULL);
1696 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (win);
1698 selected_attachments = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
1700 return selected_attachments;
1704 modest_msg_view_window_view_attachment (ModestMsgViewWindow *window, TnyMimePart *mime_part)
1706 ModestMsgViewWindowPrivate *priv;
1707 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
1708 g_return_if_fail (TNY_IS_MIME_PART (mime_part) || (mime_part == NULL));
1710 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1712 if (mime_part == NULL) {
1713 gboolean error = FALSE;
1714 GList *selected_attachments = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
1715 if (selected_attachments == NULL) {
1717 } else if (g_list_length (selected_attachments) > 1) {
1718 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unable_to_display_more"));
1721 mime_part = (TnyMimePart *) selected_attachments->data;
1722 g_object_ref (mime_part);
1724 g_list_foreach (selected_attachments, (GFunc) g_object_unref, NULL);
1725 g_list_free (selected_attachments);
1730 g_object_ref (mime_part);
1733 if (tny_mime_part_is_purged (mime_part)) {
1734 g_object_unref (mime_part);
1735 hildon_banner_show_information (NULL, NULL, _("mail_ib_attach_not_local"));
1739 if (!TNY_IS_MSG (mime_part)) {
1740 gchar *filepath = NULL;
1741 const gchar *att_filename = tny_mime_part_get_filename (mime_part);
1742 gchar *extension = NULL;
1743 TnyFsStream *temp_stream = NULL;
1746 extension = g_strrstr (att_filename, ".");
1747 if (extension != NULL)
1751 temp_stream = modest_maemo_utils_create_temp_stream (extension, &filepath);
1754 const gchar *content_type;
1755 content_type = tny_mime_part_get_content_type (mime_part);
1756 tny_mime_part_decode_to_stream (mime_part, TNY_STREAM (temp_stream));
1758 modest_platform_activate_file (filepath, content_type);
1759 g_object_unref (temp_stream);
1761 /* TODO: delete temporary file */
1764 /* message attachment */
1765 TnyHeader *header = NULL;
1766 ModestWindowMgr *mgr;
1767 ModestWindow *msg_win = NULL;
1770 header = tny_msg_get_header (TNY_MSG (mime_part));
1771 mgr = modest_runtime_get_window_mgr ();
1772 found = modest_window_mgr_find_registered_header (mgr, header, &msg_win);
1775 if (msg_win) /* there is already a window for this uid; top it */
1776 gtk_window_present (GTK_WINDOW(msg_win));
1778 /* if it's found, but there is no msg_win, it's probably in the process of being created;
1779 * thus, we don't do anything */
1780 g_warning ("window for is already being created");
1782 /* it's not found, so create a new window for it */
1783 modest_window_mgr_register_header (mgr, header); /* register the uid before building the window */
1784 gchar *account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (window)));
1786 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr ());
1787 msg_win = modest_msg_view_window_new (TNY_MSG (mime_part), account, NULL);
1788 modest_window_mgr_register_window (mgr, msg_win);
1789 gtk_window_set_transient_for (GTK_WINDOW (msg_win), GTK_WINDOW (window));
1790 gtk_widget_show_all (GTK_WIDGET (msg_win));
1793 g_object_unref (mime_part);
1809 static void save_mime_part_info_free (SaveMimePartInfo *info, gboolean with_struct);
1810 static gboolean idle_save_mime_part_show_result (SaveMimePartInfo *info);
1811 static gpointer save_mime_part_to_file (SaveMimePartInfo *info);
1812 static void save_mime_parts_to_file_with_checks (SaveMimePartInfo *info);
1815 save_mime_part_info_free (SaveMimePartInfo *info, gboolean with_struct)
1819 for (node = info->pairs; node != NULL; node = g_list_next (node)) {
1820 SaveMimePartPair *pair = (SaveMimePartPair *) node->data;
1821 g_free (pair->filename);
1822 g_object_unref (pair->part);
1823 g_slice_free (SaveMimePartPair, pair);
1825 g_list_free (info->pairs);
1828 gtk_widget_destroy (info->banner);
1829 g_object_unref (info->banner);
1830 g_slice_free (SaveMimePartInfo, info);
1835 idle_save_mime_part_show_result (SaveMimePartInfo *info)
1837 if (info->pairs != NULL) {
1838 gdk_threads_enter ();
1839 save_mime_parts_to_file_with_checks (info);
1840 gdk_threads_leave ();
1843 result = info->result;
1845 gdk_threads_enter ();
1846 save_mime_part_info_free (info, TRUE);
1848 hildon_banner_show_information (NULL, NULL, _CS("sfil_ib_saved"));
1850 hildon_banner_show_information (NULL, NULL, _("mail_ib_file_operation_failed"));
1852 gdk_threads_leave ();
1859 save_mime_part_to_file (SaveMimePartInfo *info)
1861 GnomeVFSResult result;
1862 GnomeVFSHandle *handle;
1864 SaveMimePartPair *pair = (SaveMimePartPair *) info->pairs->data;
1866 result = gnome_vfs_create (&handle, pair->filename, GNOME_VFS_OPEN_WRITE, FALSE, 0777);
1867 if (result == GNOME_VFS_OK) {
1868 stream = tny_vfs_stream_new (handle);
1869 tny_mime_part_decode_to_stream (pair->part, stream);
1870 g_object_unref (G_OBJECT (stream));
1871 g_object_unref (pair->part);
1872 g_slice_free (SaveMimePartPair, pair);
1873 info->pairs = g_list_delete_link (info->pairs, info->pairs);
1874 info->result = TRUE;
1876 save_mime_part_info_free (info, FALSE);
1877 info->result = FALSE;
1880 g_idle_add ((GSourceFunc) idle_save_mime_part_show_result, info);
1885 save_mime_parts_to_file_with_checks (SaveMimePartInfo *info)
1887 SaveMimePartPair *pair;
1888 gboolean is_ok = TRUE;
1890 pair = info->pairs->data;
1891 if (modest_maemo_utils_file_exists (pair->filename)) {
1892 GtkWidget *confirm_overwrite_dialog;
1893 confirm_overwrite_dialog = hildon_note_new_confirmation (NULL,
1894 _("emev_nc_replace_files"));
1895 if (gtk_dialog_run (GTK_DIALOG (confirm_overwrite_dialog)) != GTK_RESPONSE_OK) {
1898 gtk_widget_destroy (confirm_overwrite_dialog);
1902 save_mime_part_info_free (info, TRUE);
1904 g_thread_create ((GThreadFunc)save_mime_part_to_file, info, FALSE, NULL);
1911 modest_msg_view_window_save_attachments (ModestMsgViewWindow *window, GList *mime_parts)
1913 gboolean clean_list = FALSE;
1914 ModestMsgViewWindowPrivate *priv;
1915 GList *files_to_save = NULL;
1916 GtkWidget *save_dialog = NULL;
1917 gchar *folder = NULL;
1918 gboolean canceled = FALSE;
1919 const gchar *filename = NULL;
1920 gchar *save_multiple_str = NULL;
1922 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
1923 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1925 if (mime_parts == NULL) {
1926 mime_parts = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
1927 if (mime_parts == NULL)
1932 /* prepare dialog */
1933 if (mime_parts->next == NULL) {
1934 /* only one attachment selected */
1935 TnyMimePart *mime_part = (TnyMimePart *) mime_parts->data;
1936 if (!TNY_IS_MSG (mime_part) && tny_mime_part_is_attachment (mime_part)) {
1937 filename = tny_mime_part_get_filename (mime_part);
1939 g_warning ("Tried to save a non-file attachment");
1943 save_multiple_str = g_strdup_printf (_("FIXME: %d attachments"),
1944 g_list_length (mime_parts));
1947 save_dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
1948 GTK_FILE_CHOOSER_ACTION_SAVE);
1951 folder = g_build_filename (g_get_home_dir (), DEFAULT_FOLDER, NULL);
1952 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (save_dialog), folder);
1956 if (filename != NULL)
1957 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (save_dialog),
1960 /* if multiple, set multiple string */
1961 if (save_multiple_str) {
1962 g_object_set (G_OBJECT (save_dialog), "save-multiple", save_multiple_str, NULL);
1966 if (gtk_dialog_run (GTK_DIALOG (save_dialog)) == GTK_RESPONSE_OK) {
1967 gchar *chooser_uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (save_dialog));
1969 if (!modest_maemo_utils_folder_writable (chooser_uri)) {
1970 hildon_banner_show_information
1971 (NULL, NULL, dgettext("hildon-fm", "sfil_ib_readonly_location"));
1975 for (node = mime_parts; node != NULL; node = g_list_next (node)) {
1976 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1978 if (tny_mime_part_is_attachment (mime_part)) {
1979 SaveMimePartPair *pair;
1981 if ((mime_parts->next != NULL) &&
1982 (tny_mime_part_get_filename (mime_part) == NULL))
1985 pair = g_slice_new0 (SaveMimePartPair);
1986 if (mime_parts->next == NULL) {
1987 pair->filename = g_strdup (chooser_uri);
1990 g_build_filename (chooser_uri,
1991 tny_mime_part_get_filename (mime_part), NULL);
1993 pair->part = g_object_ref (mime_part);
1994 files_to_save = g_list_prepend (files_to_save, pair);
1998 g_free (chooser_uri);
2001 gtk_widget_destroy (save_dialog);
2004 g_list_foreach (mime_parts, (GFunc) g_object_unref, NULL);
2005 g_list_free (mime_parts);
2008 if (files_to_save != NULL) {
2009 SaveMimePartInfo *info = g_slice_new0 (SaveMimePartInfo);
2010 GtkWidget *banner = hildon_banner_show_animation (NULL, NULL,
2011 _CS("sfil_ib_saving"));
2012 info->pairs = files_to_save;
2013 info->banner = banner;
2014 info->result = TRUE;
2015 g_object_ref (banner);
2016 save_mime_parts_to_file_with_checks (info);
2021 modest_msg_view_window_remove_attachments (ModestMsgViewWindow *window, gboolean get_all)
2023 ModestMsgViewWindowPrivate *priv;
2024 GList *mime_parts = NULL, *node;
2025 gchar *confirmation_message;
2029 /* TnyFolder *folder; */
2031 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
2032 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
2035 mime_parts = modest_msg_view_get_attachments (MODEST_MSG_VIEW (priv->msg_view));
2037 mime_parts = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
2039 /* Remove already purged messages from mime parts list */
2041 while (node != NULL) {
2042 TnyMimePart *part = TNY_MIME_PART (node->data);
2043 if (tny_mime_part_is_purged (part)) {
2044 GList *deleted_node = node;
2045 node = g_list_next (node);
2046 g_object_unref (part);
2047 mime_parts = g_list_delete_link (mime_parts, deleted_node);
2049 node = g_list_next (node);
2053 if (mime_parts == NULL)
2056 n_attachments = g_list_length (mime_parts);
2057 if (n_attachments == 1) {
2058 const gchar *filename;
2060 if (TNY_IS_MSG (mime_parts->data)) {
2062 header = tny_msg_get_header (TNY_MSG (mime_parts->data));
2063 filename = tny_header_get_subject (header);
2064 g_object_unref (header);
2065 if (filename == NULL)
2066 filename = _("mail_va_no_subject");
2068 filename = tny_mime_part_get_filename (TNY_MIME_PART (mime_parts->data));
2070 confirmation_message = g_strdup_printf (_("mcen_nc_purge_file_text"), filename);
2072 confirmation_message = g_strdup_printf (ngettext("mcen_nc_purge_file_text",
2073 "mcen_nc_purge_files_text",
2074 n_attachments), n_attachments);
2076 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2077 confirmation_message);
2078 g_free (confirmation_message);
2080 if (response != GTK_RESPONSE_OK)
2083 /* folder = tny_msg_get_folder (msg); */
2084 /* tny_msg_uncache_attachments (msg); */
2085 /* tny_folder_refresh (folder, NULL); */
2086 /* g_object_unref (folder); */
2088 modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
2090 for (node = mime_parts; node != NULL; node = g_list_next (node)) {
2091 tny_mime_part_set_purged (TNY_MIME_PART (node->data));
2092 /* modest_msg_view_remove_attachment (MODEST_MSG_VIEW (priv->msg_view), node->data); */
2095 msg = modest_msg_view_get_message (MODEST_MSG_VIEW (priv->msg_view));
2096 modest_msg_view_set_message (MODEST_MSG_VIEW (priv->msg_view), NULL);
2097 tny_msg_rewrite_cache (msg);
2098 modest_msg_view_set_message (MODEST_MSG_VIEW (priv->msg_view), msg);
2100 g_list_foreach (mime_parts, (GFunc) g_object_unref, NULL);
2101 g_list_free (mime_parts);
2108 update_window_title (ModestMsgViewWindow *window)
2110 ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
2112 TnyHeader *header = NULL;
2113 const gchar *subject = NULL;
2115 msg = modest_msg_view_get_message (MODEST_MSG_VIEW (priv->msg_view));
2117 header = tny_msg_get_header (msg);
2118 subject = tny_header_get_subject (header);
2119 g_object_unref (msg);
2122 if ((subject == NULL)||(subject[0] == '\0'))
2123 subject = _("mail_va_no_subject");
2125 gtk_window_set_title (GTK_WINDOW (window), subject);