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;
1103 gboolean already_showing = FALSE;
1104 ModestWindow *msg_window = NULL;
1105 ModestWindowMgr *mgr;
1107 g_return_val_if_fail (path != NULL, FALSE);
1109 mgr = modest_runtime_get_window_mgr ();
1110 already_showing = modest_window_mgr_find_registered_header (mgr, header, &msg_window);
1111 if (already_showing && (msg_window != MODEST_WINDOW (window))) {
1114 gtk_window_present (GTK_WINDOW (msg_window));
1115 g_signal_emit_by_name (G_OBJECT (window), "delete-event", NULL, &retval);
1119 /* Msg download completed */
1120 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED) {
1121 op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
1124 GtkResponseType response;
1126 op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1128 /* Ask the user if he wants to download the message */
1129 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
1130 _("mcen_nc_get_msg"));
1131 if (response == GTK_RESPONSE_CANCEL)
1134 /* Offer the connection dialog if necessary */
1135 /* FIXME: should this stuff go directly to the mail
1136 operation instead of spread it all over the
1138 folder = tny_header_get_folder (header);
1140 if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, TNY_FOLDER_STORE (folder))) {
1141 g_object_unref (folder);
1144 g_object_unref (folder);
1148 /* New mail operation */
1149 mail_op = modest_mail_operation_new_with_error_handling (op_type,
1151 modest_ui_actions_get_msgs_full_error_handler,
1154 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1155 modest_mail_operation_get_msg (mail_op, header, view_msg_cb, path);
1156 g_object_unref (mail_op);
1158 /* Update toolbar dimming rules */
1159 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
1165 modest_msg_view_window_select_next_message (ModestMsgViewWindow *window)
1167 ModestMsgViewWindowPrivate *priv;
1168 GtkTreePath *path= NULL;
1169 GtkTreeIter tmp_iter;
1171 gboolean retval = TRUE;
1173 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), FALSE);
1174 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1176 /* Update the next row reference if it's not valid. This could
1177 happen if for example the header which it was pointing to,
1178 was deleted. The best place to do it is in the row-deleted
1179 handler but the tinymail model do not work like the glib
1180 tree models and reports the deletion when the row is still
1182 if (!gtk_tree_row_reference_valid (priv->next_row_reference)) {
1183 if (gtk_tree_row_reference_valid (priv->row_reference)) {
1184 priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference);
1185 select_next_valid_row (priv->header_model, &(priv->next_row_reference), FALSE);
1188 if (priv->next_row_reference)
1189 path = gtk_tree_row_reference_get_path (priv->next_row_reference);
1193 gtk_tree_model_get_iter (priv->header_model,
1197 gtk_tree_model_get (priv->header_model, &tmp_iter,
1198 TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
1201 /* Read the message & show it */
1202 if (!message_reader (window, priv, header, path)) {
1204 gtk_tree_path_free (path);
1208 g_object_unref (header);
1214 modest_msg_view_window_select_first_message (ModestMsgViewWindow *self)
1216 ModestMsgViewWindowPrivate *priv = NULL;
1217 TnyHeader *header = NULL;
1221 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), FALSE);
1222 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
1224 /* Check that the model is not empty */
1225 if (!gtk_tree_model_get_iter_first (priv->header_model, &iter))
1228 /* Get the header */
1229 gtk_tree_model_get (priv->header_model,
1231 TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
1233 g_return_val_if_fail (TNY_IS_HEADER (header), FALSE);
1234 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_DELETED) {
1235 g_object_unref (header);
1236 return modest_msg_view_window_select_next_message (self);
1239 path = gtk_tree_model_get_path (priv->header_model, &iter);
1241 /* Read the message & show it */
1242 message_reader (self, priv, header, path);
1245 g_object_unref (header);
1251 modest_msg_view_window_select_previous_message (ModestMsgViewWindow *window)
1253 ModestMsgViewWindowPrivate *priv = NULL;
1256 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), FALSE);
1257 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1259 /* Return inmediatly if there is no header model */
1260 if (!priv->header_model)
1263 path = gtk_tree_row_reference_get_path (priv->row_reference);
1264 while (gtk_tree_path_prev (path)) {
1268 gtk_tree_model_get_iter (priv->header_model, &iter, path);
1269 gtk_tree_model_get (priv->header_model, &iter,
1270 TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
1274 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_DELETED) {
1275 g_object_unref (header);
1279 /* Read the message & show it */
1280 if (!message_reader (window, priv, header, path)) {
1281 g_object_unref (header);
1285 g_object_unref (header);
1290 gtk_tree_path_free (path);
1295 view_msg_cb (ModestMailOperation *mail_op,
1300 ModestMsgViewWindow *self = NULL;
1301 ModestMsgViewWindowPrivate *priv = NULL;
1304 /* If there was any error */
1305 path = (GtkTreePath *) user_data;
1306 if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
1307 gtk_tree_path_free (path);
1311 /* Get the window */
1312 self = (ModestMsgViewWindow *) modest_mail_operation_get_source (mail_op);
1313 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self));
1314 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
1316 /* Update the row reference */
1317 gtk_tree_row_reference_free (priv->row_reference);
1318 priv->row_reference = gtk_tree_row_reference_new (priv->header_model, path);
1319 priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference);
1320 select_next_valid_row (priv->header_model, &(priv->next_row_reference), TRUE);
1321 gtk_tree_path_free (path);
1323 /* Mark header as read */
1324 if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_SEEN))
1325 tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
1327 /* Set new message */
1328 modest_msg_view_set_message (MODEST_MSG_VIEW (priv->msg_view), msg);
1329 modest_msg_view_window_update_priority (self);
1330 update_window_title (MODEST_MSG_VIEW_WINDOW (self));
1331 modest_msg_view_grab_focus (MODEST_MSG_VIEW (priv->msg_view));
1333 /* Set the new message uid of the window */
1334 if (priv->msg_uid) {
1335 g_free (priv->msg_uid);
1336 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1339 /* Notify the observers */
1340 g_signal_emit (G_OBJECT (self), signals[MSG_CHANGED_SIGNAL],
1341 0, priv->header_model, priv->row_reference);
1343 /* Free new references */
1344 g_object_unref (self);
1348 modest_msg_view_window_get_folder_type (ModestMsgViewWindow *window)
1350 ModestMsgViewWindowPrivate *priv;
1352 TnyFolderType folder_type;
1354 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1356 folder_type = TNY_FOLDER_TYPE_UNKNOWN;
1358 msg = modest_msg_view_get_message (MODEST_MSG_VIEW (priv->msg_view));
1362 folder = tny_msg_get_folder (msg);
1365 folder_type = tny_folder_get_folder_type (folder);
1367 if (folder_type == TNY_FOLDER_TYPE_NORMAL || folder_type == TNY_FOLDER_TYPE_UNKNOWN) {
1368 const gchar *fname = tny_folder_get_name (folder);
1369 folder_type = modest_tny_folder_guess_folder_type_from_name (fname);
1372 g_object_unref (folder);
1374 g_object_unref (msg);
1382 modest_msg_view_window_update_priority (ModestMsgViewWindow *window)
1384 ModestMsgViewWindowPrivate *priv;
1385 TnyHeaderFlags flags = 0;
1387 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1389 if (priv->header_model) {
1392 GtkTreePath *path = NULL;
1394 path = gtk_tree_row_reference_get_path (priv->row_reference);
1395 g_return_if_fail (path != NULL);
1396 gtk_tree_model_get_iter (priv->header_model,
1398 gtk_tree_row_reference_get_path (priv->row_reference));
1400 gtk_tree_model_get (priv->header_model, &iter, TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
1402 flags = tny_header_get_flags (header);
1403 gtk_tree_path_free (path);
1406 modest_msg_view_set_priority (MODEST_MSG_VIEW(priv->msg_view), flags);
1411 modest_msg_view_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1413 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1414 ModestWindowPrivate *parent_priv;
1415 ModestWindowMgr *mgr;
1416 gboolean is_fullscreen;
1417 GtkAction *fs_toggle_action;
1420 mgr = modest_runtime_get_window_mgr ();
1421 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
1423 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1425 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1426 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1427 if (is_fullscreen != active) {
1428 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1437 modest_msg_view_window_toggle_fullscreen (ModestMsgViewWindow *window)
1439 ModestWindowPrivate *parent_priv;
1440 GtkAction *fs_toggle_action;
1441 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1443 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1444 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action),
1445 !gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)));
1449 set_homogeneous (GtkWidget *widget,
1452 if (GTK_IS_TOOL_ITEM (widget)) {
1453 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1454 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1459 modest_msg_view_window_show_toolbar (ModestWindow *self,
1460 gboolean show_toolbar)
1462 ModestMsgViewWindowPrivate *priv = NULL;
1463 ModestWindowPrivate *parent_priv;
1464 GtkWidget *reply_button = NULL, *menu = NULL;
1465 GtkWidget *placeholder = NULL;
1468 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1469 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
1471 /* Set optimized view status */
1472 priv->optimized_view = !show_toolbar;
1474 if (!parent_priv->toolbar) {
1475 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1478 /* Set homogeneous toolbar */
1479 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1480 set_homogeneous, NULL);
1482 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1483 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1484 priv->next_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNext");
1485 priv->prev_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageBack");
1486 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1487 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1488 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1489 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1491 /* Add ProgressBar (Transfer toolbar) */
1492 priv->progress_bar = modest_progress_bar_widget_new ();
1493 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1494 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressbarView");
1495 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1496 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1497 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1499 /* Connect cancel 'clicked' signal to abort progress mode */
1500 g_signal_connect(priv->cancel_toolitem, "clicked",
1501 G_CALLBACK(cancel_progressbar),
1504 /* Add it to the observers list */
1505 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1508 hildon_window_add_toolbar (HILDON_WINDOW (self),
1509 GTK_TOOLBAR (parent_priv->toolbar));
1512 /* Set reply button tap and hold menu */
1513 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1514 "/ToolBar/ToolbarMessageReply");
1515 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1516 "/ToolbarReplyCSM");
1517 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1521 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1522 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1523 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1525 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1526 set_toolbar_mode (MODEST_MSG_VIEW_WINDOW(self), TOOLBAR_MODE_NORMAL);
1529 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1530 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1535 modest_msg_view_window_clipboard_owner_change (GtkClipboard *clipboard,
1537 ModestMsgViewWindow *window)
1539 ModestWindowPrivate *parent_priv;
1540 /* GtkAction *action; */
1541 gboolean is_address;
1545 if (!GTK_WIDGET_VISIBLE (window))
1548 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1549 selection = gtk_clipboard_wait_for_text (clipboard);
1551 is_address = ((selection != NULL) && (modest_text_utils_validate_recipient (selection, NULL)));
1553 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/ToolsAddToContactsMenu"); */
1554 /* gtk_action_set_sensitive (action, is_address); */
1556 focused = gtk_window_get_focus (GTK_WINDOW (window));
1558 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/EditCopyMenu"); */
1559 /* gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused))); */
1561 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/EditCutMenu"); */
1562 /* gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused))); */
1565 /* modest_msg_view_window_update_dimmed (window); */
1570 modest_msg_view_window_transfer_mode_enabled (ModestMsgViewWindow *self)
1572 ModestMsgViewWindowPrivate *priv;
1574 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), FALSE);
1575 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
1577 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
1581 cancel_progressbar (GtkToolButton *toolbutton,
1582 ModestMsgViewWindow *self)
1585 ModestMsgViewWindowPrivate *priv;
1587 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
1589 /* Get operation observers and cancel its current operation */
1590 tmp = priv->progress_widgets;
1592 modest_progress_object_cancel_current_operation (MODEST_PROGRESS_OBJECT(tmp->data));
1593 tmp=g_slist_next(tmp);
1597 observers_empty (ModestMsgViewWindow *self)
1600 ModestMsgViewWindowPrivate *priv;
1601 gboolean is_empty = TRUE;
1602 guint pending_ops = 0;
1604 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
1605 tmp = priv->progress_widgets;
1607 /* Check all observers */
1608 while (tmp && is_empty) {
1609 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1610 is_empty = pending_ops == 0;
1612 tmp = g_slist_next(tmp);
1619 on_account_removed (TnyAccountStore *account_store,
1620 TnyAccount *account,
1623 /* Do nothing if it's a transport account, because we only
1624 show the messages of a store account */
1625 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_STORE) {
1626 const gchar *parent_acc = NULL;
1627 const gchar *our_acc = NULL;
1629 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
1630 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
1632 /* Close this window if I'm showing a message of the removed account */
1633 if (strcmp (parent_acc, our_acc) == 0)
1634 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
1639 on_queue_changed (ModestMailOperationQueue *queue,
1640 ModestMailOperation *mail_op,
1641 ModestMailOperationQueueNotification type,
1642 ModestMsgViewWindow *self)
1645 ModestMsgViewWindowPrivate *priv;
1646 ModestMailOperationTypeOperation op_type;
1647 ModestToolBarModes mode;
1649 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self));
1650 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
1652 /* If this operations was created by another window, do nothing */
1653 if (!modest_mail_operation_is_mine (mail_op, G_OBJECT(self)))
1656 /* Get toolbar mode from operation id*/
1657 op_type = modest_mail_operation_get_type_operation (mail_op);
1659 /* case MODEST_MAIL_OPERATION_TYPE_SEND: */
1660 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
1661 case MODEST_MAIL_OPERATION_TYPE_OPEN:
1662 mode = TOOLBAR_MODE_TRANSFER;
1665 mode = TOOLBAR_MODE_NORMAL;
1669 /* Add operation observers and change toolbar if neccessary*/
1670 tmp = priv->progress_widgets;
1672 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
1673 if (mode == TOOLBAR_MODE_TRANSFER) {
1674 /* Enable transfer toolbar mode */
1675 set_toolbar_transfer_mode(self);
1677 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1679 tmp = g_slist_next (tmp);
1684 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
1685 if (mode == TOOLBAR_MODE_TRANSFER) {
1687 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1689 tmp = g_slist_next (tmp);
1693 /* If no more operations are being observed, NORMAL mode is enabled again */
1694 if (observers_empty (self)) {
1695 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
1703 modest_msg_view_window_get_attachments (ModestMsgViewWindow *win)
1705 ModestMsgViewWindowPrivate *priv;
1706 GList *selected_attachments = NULL;
1708 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (win), NULL);
1709 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (win);
1711 selected_attachments = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
1713 return selected_attachments;
1717 modest_msg_view_window_view_attachment (ModestMsgViewWindow *window, TnyMimePart *mime_part)
1719 ModestMsgViewWindowPrivate *priv;
1720 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
1721 g_return_if_fail (TNY_IS_MIME_PART (mime_part) || (mime_part == NULL));
1723 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1725 if (mime_part == NULL) {
1726 gboolean error = FALSE;
1727 GList *selected_attachments = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
1728 if (selected_attachments == NULL) {
1730 } else if (g_list_length (selected_attachments) > 1) {
1731 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unable_to_display_more"));
1734 mime_part = (TnyMimePart *) selected_attachments->data;
1735 g_object_ref (mime_part);
1737 g_list_foreach (selected_attachments, (GFunc) g_object_unref, NULL);
1738 g_list_free (selected_attachments);
1743 g_object_ref (mime_part);
1746 if (tny_mime_part_is_purged (mime_part)) {
1747 g_object_unref (mime_part);
1748 hildon_banner_show_information (NULL, NULL, _("mail_ib_attach_not_local"));
1752 if (!TNY_IS_MSG (mime_part)) {
1753 gchar *filepath = NULL;
1754 const gchar *att_filename = tny_mime_part_get_filename (mime_part);
1755 gchar *extension = NULL;
1756 TnyFsStream *temp_stream = NULL;
1759 extension = g_strrstr (att_filename, ".");
1760 if (extension != NULL)
1764 temp_stream = modest_maemo_utils_create_temp_stream (extension, &filepath);
1767 const gchar *content_type;
1768 content_type = tny_mime_part_get_content_type (mime_part);
1769 tny_mime_part_decode_to_stream (mime_part, TNY_STREAM (temp_stream));
1771 modest_platform_activate_file (filepath, content_type);
1772 g_object_unref (temp_stream);
1774 /* TODO: delete temporary file */
1777 /* message attachment */
1778 TnyHeader *header = NULL;
1779 ModestWindowMgr *mgr;
1780 ModestWindow *msg_win = NULL;
1783 header = tny_msg_get_header (TNY_MSG (mime_part));
1784 mgr = modest_runtime_get_window_mgr ();
1785 found = modest_window_mgr_find_registered_header (mgr, header, &msg_win);
1788 if (msg_win) /* there is already a window for this uid; top it */
1789 gtk_window_present (GTK_WINDOW(msg_win));
1791 /* if it's found, but there is no msg_win, it's probably in the process of being created;
1792 * thus, we don't do anything */
1793 g_warning ("window for is already being created");
1795 /* it's not found, so create a new window for it */
1796 modest_window_mgr_register_header (mgr, header); /* register the uid before building the window */
1797 gchar *account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (window)));
1799 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr ());
1800 msg_win = modest_msg_view_window_new (TNY_MSG (mime_part), account, NULL);
1801 modest_window_set_zoom (MODEST_WINDOW (msg_win),
1802 modest_window_get_zoom (MODEST_WINDOW (window)));
1803 modest_window_mgr_register_window (mgr, msg_win);
1804 gtk_window_set_transient_for (GTK_WINDOW (msg_win), GTK_WINDOW (window));
1805 gtk_widget_show_all (GTK_WIDGET (msg_win));
1808 g_object_unref (mime_part);
1824 static void save_mime_part_info_free (SaveMimePartInfo *info, gboolean with_struct);
1825 static gboolean idle_save_mime_part_show_result (SaveMimePartInfo *info);
1826 static gpointer save_mime_part_to_file (SaveMimePartInfo *info);
1827 static void save_mime_parts_to_file_with_checks (SaveMimePartInfo *info);
1830 save_mime_part_info_free (SaveMimePartInfo *info, gboolean with_struct)
1834 for (node = info->pairs; node != NULL; node = g_list_next (node)) {
1835 SaveMimePartPair *pair = (SaveMimePartPair *) node->data;
1836 g_free (pair->filename);
1837 g_object_unref (pair->part);
1838 g_slice_free (SaveMimePartPair, pair);
1840 g_list_free (info->pairs);
1843 gtk_widget_destroy (info->banner);
1844 g_object_unref (info->banner);
1845 g_slice_free (SaveMimePartInfo, info);
1850 idle_save_mime_part_show_result (SaveMimePartInfo *info)
1852 if (info->pairs != NULL) {
1853 gdk_threads_enter ();
1854 save_mime_parts_to_file_with_checks (info);
1855 gdk_threads_leave ();
1858 result = info->result;
1860 gdk_threads_enter ();
1861 save_mime_part_info_free (info, TRUE);
1863 hildon_banner_show_information (NULL, NULL, _CS("sfil_ib_saved"));
1865 hildon_banner_show_information (NULL, NULL, _("mail_ib_file_operation_failed"));
1867 gdk_threads_leave ();
1874 save_mime_part_to_file (SaveMimePartInfo *info)
1876 GnomeVFSResult result;
1877 GnomeVFSHandle *handle;
1879 SaveMimePartPair *pair = (SaveMimePartPair *) info->pairs->data;
1881 result = gnome_vfs_create (&handle, pair->filename, GNOME_VFS_OPEN_WRITE, FALSE, 0777);
1882 if (result == GNOME_VFS_OK) {
1883 stream = tny_vfs_stream_new (handle);
1884 tny_mime_part_decode_to_stream (pair->part, stream);
1885 g_object_unref (G_OBJECT (stream));
1886 g_object_unref (pair->part);
1887 g_slice_free (SaveMimePartPair, pair);
1888 info->pairs = g_list_delete_link (info->pairs, info->pairs);
1889 info->result = TRUE;
1891 save_mime_part_info_free (info, FALSE);
1892 info->result = FALSE;
1895 g_idle_add ((GSourceFunc) idle_save_mime_part_show_result, info);
1900 save_mime_parts_to_file_with_checks (SaveMimePartInfo *info)
1902 SaveMimePartPair *pair;
1903 gboolean is_ok = TRUE;
1905 pair = info->pairs->data;
1906 if (modest_maemo_utils_file_exists (pair->filename)) {
1907 GtkWidget *confirm_overwrite_dialog;
1908 confirm_overwrite_dialog = hildon_note_new_confirmation (NULL,
1909 _("emev_nc_replace_files"));
1910 if (gtk_dialog_run (GTK_DIALOG (confirm_overwrite_dialog)) != GTK_RESPONSE_OK) {
1913 gtk_widget_destroy (confirm_overwrite_dialog);
1917 save_mime_part_info_free (info, TRUE);
1919 g_thread_create ((GThreadFunc)save_mime_part_to_file, info, FALSE, NULL);
1926 modest_msg_view_window_save_attachments (ModestMsgViewWindow *window, GList *mime_parts)
1928 gboolean clean_list = FALSE;
1929 ModestMsgViewWindowPrivate *priv;
1930 GList *files_to_save = NULL;
1931 GtkWidget *save_dialog = NULL;
1932 gchar *folder = NULL;
1933 gboolean canceled = FALSE;
1934 const gchar *filename = NULL;
1935 gchar *save_multiple_str = NULL;
1937 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
1938 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1940 if (mime_parts == NULL) {
1941 mime_parts = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
1942 if (mime_parts == NULL)
1947 /* prepare dialog */
1948 if (mime_parts->next == NULL) {
1949 /* only one attachment selected */
1950 TnyMimePart *mime_part = (TnyMimePart *) mime_parts->data;
1951 if (!TNY_IS_MSG (mime_part) && tny_mime_part_is_attachment (mime_part)) {
1952 filename = tny_mime_part_get_filename (mime_part);
1954 g_warning ("Tried to save a non-file attachment");
1958 save_multiple_str = g_strdup_printf (_("FIXME: %d attachments"),
1959 g_list_length (mime_parts));
1962 save_dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
1963 GTK_FILE_CHOOSER_ACTION_SAVE);
1966 folder = g_build_filename (g_get_home_dir (), DEFAULT_FOLDER, NULL);
1967 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (save_dialog), folder);
1971 if (filename != NULL)
1972 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (save_dialog),
1975 /* if multiple, set multiple string */
1976 if (save_multiple_str) {
1977 g_object_set (G_OBJECT (save_dialog), "save-multiple", save_multiple_str, NULL);
1981 if (gtk_dialog_run (GTK_DIALOG (save_dialog)) == GTK_RESPONSE_OK) {
1982 gchar *chooser_uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (save_dialog));
1984 if (!modest_maemo_utils_folder_writable (chooser_uri)) {
1985 hildon_banner_show_information
1986 (NULL, NULL, dgettext("hildon-fm", "sfil_ib_readonly_location"));
1990 for (node = mime_parts; node != NULL; node = g_list_next (node)) {
1991 TnyMimePart *mime_part = (TnyMimePart *) node->data;
1993 if (tny_mime_part_is_attachment (mime_part)) {
1994 SaveMimePartPair *pair;
1996 if ((mime_parts->next != NULL) &&
1997 (tny_mime_part_get_filename (mime_part) == NULL))
2000 pair = g_slice_new0 (SaveMimePartPair);
2001 if (mime_parts->next == NULL) {
2002 pair->filename = g_strdup (chooser_uri);
2005 g_build_filename (chooser_uri,
2006 tny_mime_part_get_filename (mime_part), NULL);
2008 pair->part = g_object_ref (mime_part);
2009 files_to_save = g_list_prepend (files_to_save, pair);
2013 g_free (chooser_uri);
2016 gtk_widget_destroy (save_dialog);
2019 g_list_foreach (mime_parts, (GFunc) g_object_unref, NULL);
2020 g_list_free (mime_parts);
2023 if (files_to_save != NULL) {
2024 SaveMimePartInfo *info = g_slice_new0 (SaveMimePartInfo);
2025 GtkWidget *banner = hildon_banner_show_animation (NULL, NULL,
2026 _CS("sfil_ib_saving"));
2027 info->pairs = files_to_save;
2028 info->banner = banner;
2029 info->result = TRUE;
2030 g_object_ref (banner);
2031 save_mime_parts_to_file_with_checks (info);
2036 modest_msg_view_window_remove_attachments (ModestMsgViewWindow *window, gboolean get_all)
2038 ModestMsgViewWindowPrivate *priv;
2039 GList *mime_parts = NULL, *node;
2040 gchar *confirmation_message;
2044 /* TnyFolder *folder; */
2046 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
2047 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
2050 mime_parts = modest_msg_view_get_attachments (MODEST_MSG_VIEW (priv->msg_view));
2052 mime_parts = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
2054 /* Remove already purged messages from mime parts list */
2056 while (node != NULL) {
2057 TnyMimePart *part = TNY_MIME_PART (node->data);
2058 if (tny_mime_part_is_purged (part)) {
2059 GList *deleted_node = node;
2060 node = g_list_next (node);
2061 g_object_unref (part);
2062 mime_parts = g_list_delete_link (mime_parts, deleted_node);
2064 node = g_list_next (node);
2068 if (mime_parts == NULL)
2071 n_attachments = g_list_length (mime_parts);
2072 if (n_attachments == 1) {
2073 const gchar *filename;
2075 if (TNY_IS_MSG (mime_parts->data)) {
2077 header = tny_msg_get_header (TNY_MSG (mime_parts->data));
2078 filename = tny_header_get_subject (header);
2079 g_object_unref (header);
2080 if (filename == NULL)
2081 filename = _("mail_va_no_subject");
2083 filename = tny_mime_part_get_filename (TNY_MIME_PART (mime_parts->data));
2085 confirmation_message = g_strdup_printf (_("mcen_nc_purge_file_text"), filename);
2087 confirmation_message = g_strdup_printf (ngettext("mcen_nc_purge_file_text",
2088 "mcen_nc_purge_files_text",
2089 n_attachments), n_attachments);
2091 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2092 confirmation_message);
2093 g_free (confirmation_message);
2095 if (response != GTK_RESPONSE_OK)
2098 /* folder = tny_msg_get_folder (msg); */
2099 /* tny_msg_uncache_attachments (msg); */
2100 /* tny_folder_refresh (folder, NULL); */
2101 /* g_object_unref (folder); */
2103 modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
2105 for (node = mime_parts; node != NULL; node = g_list_next (node)) {
2106 tny_mime_part_set_purged (TNY_MIME_PART (node->data));
2107 /* modest_msg_view_remove_attachment (MODEST_MSG_VIEW (priv->msg_view), node->data); */
2110 msg = modest_msg_view_get_message (MODEST_MSG_VIEW (priv->msg_view));
2111 modest_msg_view_set_message (MODEST_MSG_VIEW (priv->msg_view), NULL);
2112 tny_msg_rewrite_cache (msg);
2113 modest_msg_view_set_message (MODEST_MSG_VIEW (priv->msg_view), msg);
2115 g_list_foreach (mime_parts, (GFunc) g_object_unref, NULL);
2116 g_list_free (mime_parts);
2123 update_window_title (ModestMsgViewWindow *window)
2125 ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
2127 TnyHeader *header = NULL;
2128 const gchar *subject = NULL;
2130 msg = modest_msg_view_get_message (MODEST_MSG_VIEW (priv->msg_view));
2132 header = tny_msg_get_header (msg);
2133 subject = tny_header_get_subject (header);
2134 g_object_unref (msg);
2137 if ((subject == NULL)||(subject[0] == '\0'))
2138 subject = _("mail_va_no_subject");
2140 gtk_window_set_title (GTK_WINDOW (window), subject);