1 /* Copyright (c) 2006, Nokia Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of the Nokia Corporation nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include <glib/gi18n.h>
31 #include <tny-account-store.h>
32 #include <tny-simple-list.h>
34 #include <tny-mime-part.h>
35 #include <tny-vfs-stream.h>
36 #include "modest-marshal.h"
37 #include "modest-platform.h"
38 #include <modest-maemo-utils.h>
39 #include <modest-tny-msg.h>
40 #include <modest-msg-view-window.h>
41 #include <modest-attachments-view.h>
42 #include <modest-main-window-ui.h>
43 #include "modest-msg-view-window-ui-dimming.h"
44 #include <modest-widget-memory.h>
45 #include <modest-runtime.h>
46 #include <modest-window-priv.h>
47 #include <modest-tny-folder.h>
48 #include <modest-text-utils.h>
49 #include <modest-account-mgr-helpers.h>
50 #include "modest-progress-bar-widget.h"
51 #include "modest-defs.h"
52 #include "modest-hildon-includes.h"
53 #include <gtkhtml/gtkhtml-search.h>
54 #include "modest-ui-dimming-manager.h"
55 #include <gdk/gdkkeysyms.h>
56 #include <modest-tny-account.h>
58 #define DEFAULT_FOLDER "MyDocs/.documents"
60 static void modest_msg_view_window_class_init (ModestMsgViewWindowClass *klass);
61 static void modest_msg_view_window_init (ModestMsgViewWindow *obj);
62 static void modest_msg_view_window_finalize (GObject *obj);
63 static void modest_msg_view_window_toggle_find_toolbar (GtkToggleAction *obj,
65 static void modest_msg_view_window_find_toolbar_close (GtkWidget *widget,
66 ModestMsgViewWindow *obj);
67 static void modest_msg_view_window_find_toolbar_search (GtkWidget *widget,
68 ModestMsgViewWindow *obj);
70 static void modest_msg_view_window_disconnect_signals (ModestWindow *self);
71 static void modest_msg_view_window_set_zoom (ModestWindow *window,
73 static gdouble modest_msg_view_window_get_zoom (ModestWindow *window);
74 static gboolean modest_msg_view_window_zoom_minus (ModestWindow *window);
75 static gboolean modest_msg_view_window_zoom_plus (ModestWindow *window);
76 static gboolean modest_msg_view_window_key_release_event (GtkWidget *window,
79 static gboolean modest_msg_view_window_window_state_event (GtkWidget *widget,
80 GdkEventWindowState *event,
82 static void modest_msg_view_window_scroll_up (ModestWindow *window);
83 static void modest_msg_view_window_scroll_down (ModestWindow *window);
84 static void modest_msg_view_window_update_priority (ModestMsgViewWindow *window);
86 static void modest_msg_view_window_show_toolbar (ModestWindow *window,
87 gboolean show_toolbar);
89 static void modest_msg_view_window_clipboard_owner_change (GtkClipboard *clipboard,
91 ModestMsgViewWindow *window);
93 static void cancel_progressbar (GtkToolButton *toolbutton,
94 ModestMsgViewWindow *self);
96 static void on_queue_changed (ModestMailOperationQueue *queue,
97 ModestMailOperation *mail_op,
98 ModestMailOperationQueueNotification type,
99 ModestMsgViewWindow *self);
101 static void on_account_removed (TnyAccountStore *account_store,
105 static void view_msg_cb (ModestMailOperation *mail_op,
110 static void set_toolbar_mode (ModestMsgViewWindow *self,
111 ModestToolBarModes mode);
113 static void update_window_title (ModestMsgViewWindow *window);
115 static gboolean set_toolbar_transfer_mode (ModestMsgViewWindow *self);
118 /* list my signals */
124 static const GtkToggleActionEntry msg_view_toggle_action_entries [] = {
125 { "FindInMessage", MODEST_TOOLBAR_ICON_FIND, N_("qgn_toolb_gene_find"), NULL, NULL, G_CALLBACK (modest_msg_view_window_toggle_find_toolbar), FALSE },
126 { "ToolsFindInMessage", NULL, N_("mcen_me_viewer_find"), NULL, NULL, G_CALLBACK (modest_msg_view_window_toggle_find_toolbar), FALSE },
129 static const GtkRadioActionEntry msg_view_zoom_action_entries [] = {
130 { "Zoom50", NULL, N_("mcen_me_viewer_50"), NULL, NULL, 50 },
131 { "Zoom80", NULL, N_("mcen_me_viewer_80"), NULL, NULL, 80 },
132 { "Zoom100", NULL, N_("mcen_me_viewer_100"), NULL, NULL, 100 },
133 { "Zoom120", NULL, N_("mcen_me_viewer_120"), NULL, NULL, 120 },
134 { "Zoom150", NULL, N_("mcen_me_viewer_150"), NULL, NULL, 150 },
135 { "Zoom200", NULL, N_("mcen_me_viewer_200"), NULL, NULL, 200 }
138 typedef struct _ModestMsgViewWindowPrivate ModestMsgViewWindowPrivate;
139 struct _ModestMsgViewWindowPrivate {
142 GtkWidget *main_scroll;
143 GtkWidget *find_toolbar;
146 /* Progress observers */
147 GtkWidget *progress_bar;
148 GSList *progress_widgets;
151 GtkWidget *progress_toolitem;
152 GtkWidget *cancel_toolitem;
153 GtkWidget *prev_toolitem;
154 GtkWidget *next_toolitem;
155 ModestToolBarModes current_toolbar_mode;
157 /* Optimized view enabled */
158 gboolean optimized_view;
160 /* A reference to the @model of the header view
161 * to allow selecting previous/next messages,
162 * if the message is currently selected in the header view.
164 GtkTreeModel *header_model;
165 GtkTreeRowReference *row_reference;
166 GtkTreeRowReference *next_row_reference;
168 guint clipboard_change_handler;
169 guint queue_change_handler;
170 guint account_removed_handler;
172 guint progress_bar_timeout;
177 #define MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \
178 MODEST_TYPE_MSG_VIEW_WINDOW, \
179 ModestMsgViewWindowPrivate))
181 static GtkWindowClass *parent_class = NULL;
183 /* uncomment the following if you have defined any signals */
184 static guint signals[LAST_SIGNAL] = {0};
187 modest_msg_view_window_get_type (void)
189 static GType my_type = 0;
191 static const GTypeInfo my_info = {
192 sizeof(ModestMsgViewWindowClass),
193 NULL, /* base init */
194 NULL, /* base finalize */
195 (GClassInitFunc) modest_msg_view_window_class_init,
196 NULL, /* class finalize */
197 NULL, /* class data */
198 sizeof(ModestMsgViewWindow),
200 (GInstanceInitFunc) modest_msg_view_window_init,
203 my_type = g_type_register_static (MODEST_TYPE_WINDOW,
204 "ModestMsgViewWindow",
211 save_state (ModestWindow *self)
213 modest_widget_memory_save (modest_runtime_get_conf (),
215 MODEST_CONF_MSG_VIEW_WINDOW_KEY);
220 restore_settings (ModestMsgViewWindow *self)
222 modest_widget_memory_restore (modest_runtime_get_conf (),
224 MODEST_CONF_MSG_VIEW_WINDOW_KEY);
228 modest_msg_view_window_class_init (ModestMsgViewWindowClass *klass)
230 GObjectClass *gobject_class;
231 ModestWindowClass *modest_window_class;
232 gobject_class = (GObjectClass*) klass;
233 modest_window_class = (ModestWindowClass *) klass;
235 parent_class = g_type_class_peek_parent (klass);
236 gobject_class->finalize = modest_msg_view_window_finalize;
238 modest_window_class->set_zoom_func = modest_msg_view_window_set_zoom;
239 modest_window_class->get_zoom_func = modest_msg_view_window_get_zoom;
240 modest_window_class->zoom_minus_func = modest_msg_view_window_zoom_minus;
241 modest_window_class->zoom_plus_func = modest_msg_view_window_zoom_plus;
242 modest_window_class->show_toolbar_func = modest_msg_view_window_show_toolbar;
243 modest_window_class->disconnect_signals_func = modest_msg_view_window_disconnect_signals;
245 g_type_class_add_private (gobject_class, sizeof(ModestMsgViewWindowPrivate));
247 modest_window_class->save_state_func = save_state;
249 signals[MSG_CHANGED_SIGNAL] =
250 g_signal_new ("msg-changed",
251 G_TYPE_FROM_CLASS (gobject_class),
253 G_STRUCT_OFFSET (ModestMsgViewWindowClass, msg_changed),
255 modest_marshal_VOID__POINTER_POINTER,
256 G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER);
260 modest_msg_view_window_init (ModestMsgViewWindow *obj)
262 ModestMsgViewWindowPrivate *priv;
263 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(obj);
265 priv->msg_view = NULL;
266 priv->header_model = NULL;
267 priv->clipboard_change_handler = 0;
268 priv->queue_change_handler = 0;
269 priv->account_removed_handler = 0;
270 priv->current_toolbar_mode = TOOLBAR_MODE_NORMAL;
272 priv->optimized_view = FALSE;
273 priv->progress_bar_timeout = 0;
274 priv->msg_uid = NULL;
279 set_toolbar_transfer_mode (ModestMsgViewWindow *self)
281 ModestMsgViewWindowPrivate *priv = NULL;
283 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), FALSE);
285 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
287 set_toolbar_mode (self, TOOLBAR_MODE_TRANSFER);
289 if (priv->progress_bar_timeout > 0) {
290 g_source_remove (priv->progress_bar_timeout);
291 priv->progress_bar_timeout = 0;
298 set_toolbar_mode (ModestMsgViewWindow *self,
299 ModestToolBarModes mode)
301 ModestWindowPrivate *parent_priv;
302 ModestMsgViewWindowPrivate *priv;
303 /* GtkWidget *widget = NULL; */
305 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self));
307 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
308 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
310 /* Sets current toolbar mode */
311 priv->current_toolbar_mode = mode;
313 /* Update toolbar dimming state */
314 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (self));
317 case TOOLBAR_MODE_NORMAL:
318 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply"); */
319 /* gtk_action_set_sensitive (widget, TRUE); */
320 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage"); */
321 /* gtk_action_set_sensitive (widget, TRUE); */
322 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarMessageMoveTo"); */
323 /* gtk_action_set_sensitive (widget, TRUE); */
324 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/FindInMessage"); */
325 /* gtk_action_set_sensitive (widget, TRUE); */
327 if (priv->prev_toolitem)
328 gtk_widget_show (priv->prev_toolitem);
330 if (priv->next_toolitem)
331 gtk_widget_show (priv->next_toolitem);
333 if (priv->progress_toolitem)
334 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), FALSE);
335 if (priv->progress_bar)
336 gtk_widget_hide (priv->progress_bar);
338 if (priv->cancel_toolitem)
339 gtk_widget_hide (priv->cancel_toolitem);
341 /* Hide toolbar if optimized view is enabled */
342 if (priv->optimized_view) {
343 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
344 gtk_widget_hide (GTK_WIDGET(parent_priv->toolbar));
348 case TOOLBAR_MODE_TRANSFER:
349 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply"); */
350 /* gtk_action_set_sensitive (widget, FALSE); */
351 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage"); */
352 /* gtk_action_set_sensitive (widget, FALSE); */
353 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/ToolbarMessageMoveTo"); */
354 /* gtk_action_set_sensitive (widget, FALSE); */
355 /* widget = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/FindInMessage"); */
356 /* gtk_action_set_sensitive (widget, FALSE); */
358 if (priv->prev_toolitem)
359 gtk_widget_hide (priv->prev_toolitem);
361 if (priv->next_toolitem)
362 gtk_widget_hide (priv->next_toolitem);
364 if (priv->progress_toolitem)
365 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
366 if (priv->progress_bar)
367 gtk_widget_show (priv->progress_bar);
369 if (priv->cancel_toolitem)
370 gtk_widget_show (priv->cancel_toolitem);
372 /* Show toolbar if it's hiden (optimized view ) */
373 if (priv->optimized_view) {
374 gtk_widget_set_no_show_all (parent_priv->toolbar, FALSE);
375 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
380 g_return_if_reached ();
387 menubar_to_menu (GtkUIManager *ui_manager)
389 GtkWidget *main_menu;
393 /* Create new main menu */
394 main_menu = gtk_menu_new();
396 /* Get the menubar from the UI manager */
397 menubar = gtk_ui_manager_get_widget (ui_manager, "/MenuBar");
399 iter = gtk_container_get_children (GTK_CONTAINER (menubar));
403 menu = GTK_WIDGET (iter->data);
404 gtk_widget_reparent(menu, main_menu);
406 iter = g_list_next (iter);
412 init_window (ModestMsgViewWindow *obj, TnyMsg *msg)
414 GtkWidget *main_vbox;
415 ModestMsgViewWindowPrivate *priv;
416 ModestWindowPrivate *parent_priv;
418 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(obj);
419 parent_priv = MODEST_WINDOW_GET_PRIVATE(obj);
421 priv->msg_view = modest_msg_view_new (msg);
422 modest_msg_view_set_shadow_type (MODEST_MSG_VIEW (priv->msg_view), GTK_SHADOW_NONE);
423 main_vbox = gtk_vbox_new (FALSE, 6);
426 parent_priv->menubar = menubar_to_menu (parent_priv->ui_manager);
427 gtk_widget_show_all (GTK_WIDGET(parent_priv->menubar));
428 hildon_window_set_menu (HILDON_WINDOW(obj), GTK_MENU(parent_priv->menubar));
430 priv->main_scroll = gtk_scrolled_window_new (NULL, NULL);
431 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->main_scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
432 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->main_scroll), GTK_SHADOW_NONE);
433 modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->main_scroll), TRUE);
435 gtk_container_add (GTK_CONTAINER (priv->main_scroll), priv->msg_view);
436 gtk_box_pack_start (GTK_BOX(main_vbox), priv->main_scroll, TRUE, TRUE, 0);
437 gtk_container_add (GTK_CONTAINER(obj), main_vbox);
439 priv->find_toolbar = hildon_find_toolbar_new (NULL);
440 hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar));
441 gtk_widget_set_no_show_all (priv->find_toolbar, TRUE);
442 g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_view_window_find_toolbar_close), obj);
443 g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_view_window_find_toolbar_search), obj);
445 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);
446 gtk_widget_show_all (GTK_WIDGET(main_vbox));
450 modest_msg_view_window_disconnect_signals (ModestWindow *self)
452 ModestMsgViewWindowPrivate *priv;
454 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
456 if (g_signal_handler_is_connected (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
457 priv->clipboard_change_handler))
458 g_signal_handler_disconnect (gtk_clipboard_get (GDK_SELECTION_PRIMARY),
459 priv->clipboard_change_handler);
461 if (g_signal_handler_is_connected (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
462 priv->queue_change_handler))
463 g_signal_handler_disconnect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
464 priv->queue_change_handler);
466 if (g_signal_handler_is_connected (G_OBJECT (modest_runtime_get_account_store ()),
467 priv->account_removed_handler))
468 g_signal_handler_disconnect (G_OBJECT (modest_runtime_get_account_store ()),
469 priv->account_removed_handler);
473 modest_msg_view_window_finalize (GObject *obj)
475 ModestMsgViewWindowPrivate *priv;
477 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (obj);
479 /* Sanity check: shouldn't be needed, the window mgr should
480 call this function before */
481 modest_msg_view_window_disconnect_signals (MODEST_WINDOW (obj));
483 if (priv->header_model != NULL) {
484 g_object_unref (priv->header_model);
485 priv->header_model = NULL;
488 if (priv->progress_bar_timeout > 0) {
489 g_source_remove (priv->progress_bar_timeout);
490 priv->progress_bar_timeout = 0;
493 if (priv->row_reference) {
494 gtk_tree_row_reference_free (priv->row_reference);
495 priv->row_reference = NULL;
498 if (priv->next_row_reference) {
499 gtk_tree_row_reference_free (priv->next_row_reference);
500 priv->next_row_reference = NULL;
504 g_free (priv->msg_uid);
505 priv->msg_uid = NULL;
508 G_OBJECT_CLASS(parent_class)->finalize (obj);
512 select_next_valid_row (GtkTreeModel *model,
513 GtkTreeRowReference **row_reference,
516 GtkTreeIter tmp_iter;
517 GtkTreePath *path, *next;
518 gboolean retval = FALSE;
520 g_return_val_if_fail (gtk_tree_row_reference_valid (*row_reference), FALSE);
522 path = gtk_tree_row_reference_get_path (*row_reference);
523 gtk_tree_model_get_iter (model, &tmp_iter, path);
524 gtk_tree_row_reference_free (*row_reference);
525 *row_reference = NULL;
527 if (gtk_tree_model_iter_next (model, &tmp_iter)) {
528 next = gtk_tree_model_get_path (model, &tmp_iter);
529 *row_reference = gtk_tree_row_reference_new (model, next);
531 } else if (cycle && gtk_tree_model_get_iter_first (model, &tmp_iter)) {
532 next = gtk_tree_model_get_path (model, &tmp_iter);
534 /* Ensure that we are not selecting the same */
535 if (gtk_tree_path_compare (path, next) != 0) {
536 *row_reference = gtk_tree_row_reference_new (model, next);
542 gtk_tree_path_free (path);
548 modest_msg_view_window_new_with_header_model (TnyMsg *msg,
549 const gchar *modest_account_name,
550 const gchar *msg_uid,
552 GtkTreeRowReference *row_reference)
554 ModestMsgViewWindow *window = NULL;
555 ModestMsgViewWindowPrivate *priv = NULL;
557 window = MODEST_MSG_VIEW_WINDOW(modest_msg_view_window_new (msg, modest_account_name, msg_uid));
558 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), NULL);
560 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
562 g_object_ref (model);
563 priv->header_model = model;
564 priv->row_reference = gtk_tree_row_reference_copy (row_reference);
565 priv->next_row_reference = gtk_tree_row_reference_copy (row_reference);
566 select_next_valid_row (model, &(priv->next_row_reference), TRUE);
568 modest_msg_view_window_update_priority (window);
570 /* Check toolbar dimming rules */
571 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
573 return MODEST_WINDOW(window);
578 modest_msg_view_window_new (TnyMsg *msg,
579 const gchar *modest_account_name,
580 const gchar *msg_uid)
582 ModestMsgViewWindow *self = NULL;
584 ModestMsgViewWindowPrivate *priv = NULL;
585 ModestWindowPrivate *parent_priv = NULL;
586 ModestDimmingRulesGroup *menu_rules_group = NULL;
587 ModestDimmingRulesGroup *toolbar_rules_group = NULL;
588 GtkActionGroup *action_group = NULL;
589 GError *error = NULL;
590 GdkPixbuf *window_icon;
592 g_return_val_if_fail (msg, NULL);
594 obj = g_object_new(MODEST_TYPE_MSG_VIEW_WINDOW, NULL);
595 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(obj);
596 parent_priv = MODEST_WINDOW_GET_PRIVATE(obj);
597 self = MODEST_MSG_VIEW_WINDOW (obj);
599 priv->msg_uid = g_strdup (msg_uid);
601 parent_priv->ui_manager = gtk_ui_manager_new();
602 parent_priv->ui_dimming_manager = modest_ui_dimming_manager_new();
604 action_group = gtk_action_group_new ("ModestMsgViewWindowActions");
605 gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
607 menu_rules_group = modest_dimming_rules_group_new ("ModestMenuDimmingRules", FALSE);
608 toolbar_rules_group = modest_dimming_rules_group_new ("ModestToolbarDimmingRules", TRUE);
610 /* Add common actions */
611 gtk_action_group_add_actions (action_group,
612 modest_action_entries,
613 G_N_ELEMENTS (modest_action_entries),
615 gtk_action_group_add_toggle_actions (action_group,
616 modest_toggle_action_entries,
617 G_N_ELEMENTS (modest_toggle_action_entries),
619 gtk_action_group_add_toggle_actions (action_group,
620 msg_view_toggle_action_entries,
621 G_N_ELEMENTS (msg_view_toggle_action_entries),
623 gtk_action_group_add_radio_actions (action_group,
624 msg_view_zoom_action_entries,
625 G_N_ELEMENTS (msg_view_zoom_action_entries),
627 G_CALLBACK (modest_ui_actions_on_change_zoom),
630 gtk_ui_manager_insert_action_group (parent_priv->ui_manager, action_group, 0);
631 g_object_unref (action_group);
633 /* Load the UI definition */
634 gtk_ui_manager_add_ui_from_file (parent_priv->ui_manager, MODEST_UIDIR "modest-msg-view-window-ui.xml",
637 g_printerr ("modest: could not merge modest-msg-view-window-ui.xml: %s\n", error->message);
638 g_error_free (error);
643 /* Add common dimming rules */
644 modest_dimming_rules_group_add_rules (menu_rules_group,
645 modest_msg_view_menu_dimming_entries,
646 G_N_ELEMENTS (modest_msg_view_menu_dimming_entries),
648 modest_dimming_rules_group_add_rules (toolbar_rules_group,
649 modest_msg_view_toolbar_dimming_entries,
650 G_N_ELEMENTS (modest_msg_view_toolbar_dimming_entries),
653 /* Insert dimming rules group for this window */
654 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, menu_rules_group);
655 modest_ui_dimming_manager_insert_rules_group (parent_priv->ui_dimming_manager, toolbar_rules_group);
656 g_object_unref (menu_rules_group);
657 g_object_unref (toolbar_rules_group);
659 /* Add accelerators */
660 gtk_window_add_accel_group (GTK_WINDOW (obj),
661 gtk_ui_manager_get_accel_group (parent_priv->ui_manager));
664 init_window (MODEST_MSG_VIEW_WINDOW(obj), msg);
665 restore_settings (MODEST_MSG_VIEW_WINDOW(obj));
667 /* Set window icon */
668 window_icon = modest_platform_get_icon (MODEST_APP_MSG_VIEW_ICON);
670 gtk_window_set_icon (GTK_WINDOW (obj), window_icon);
671 g_object_unref (window_icon);
674 /* g_signal_connect (G_OBJECT(obj), "delete-event", G_CALLBACK(on_delete_event), obj); */
676 g_signal_connect (G_OBJECT(priv->msg_view), "link_clicked",
677 G_CALLBACK (modest_ui_actions_on_msg_link_clicked), obj);
678 g_signal_connect (G_OBJECT(priv->msg_view), "link_hover",
679 G_CALLBACK (modest_ui_actions_on_msg_link_hover), obj);
680 g_signal_connect (G_OBJECT(priv->msg_view), "attachment_clicked",
681 G_CALLBACK (modest_ui_actions_on_msg_attachment_clicked), obj);
682 g_signal_connect (G_OBJECT(priv->msg_view), "recpt_activated",
683 G_CALLBACK (modest_ui_actions_on_msg_recpt_activated), obj);
684 g_signal_connect (G_OBJECT(priv->msg_view), "link_contextual",
685 G_CALLBACK (modest_ui_actions_on_msg_link_contextual), obj);
687 g_signal_connect (G_OBJECT (obj), "key-release-event",
688 G_CALLBACK (modest_msg_view_window_key_release_event),
691 g_signal_connect (G_OBJECT (obj), "window-state-event",
692 G_CALLBACK (modest_msg_view_window_window_state_event),
695 /* Mail Operation Queue */
696 priv->queue_change_handler = g_signal_connect (G_OBJECT (modest_runtime_get_mail_operation_queue ()),
698 G_CALLBACK (on_queue_changed),
701 /* Account manager */
702 priv->account_removed_handler = g_signal_connect (G_OBJECT (modest_runtime_get_account_store ()),
704 G_CALLBACK(on_account_removed),
707 modest_window_set_active_account (MODEST_WINDOW(obj), modest_account_name);
709 priv->last_search = NULL;
711 /* Init the clipboard actions dim status */
712 modest_msg_view_grab_focus(MODEST_MSG_VIEW (priv->msg_view));
714 update_window_title (MODEST_MSG_VIEW_WINDOW (obj));
716 /* Check toolbar dimming rules */
717 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (obj));
719 return MODEST_WINDOW(obj);
724 modest_msg_view_window_toolbar_on_transfer_mode (ModestMsgViewWindow *self)
726 ModestMsgViewWindowPrivate *priv= NULL;
728 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), FALSE);
729 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
731 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
735 modest_msg_view_window_get_header (ModestMsgViewWindow *self)
737 ModestMsgViewWindowPrivate *priv= NULL;
739 TnyHeader *header = NULL;
740 GtkTreePath *path = NULL;
743 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), NULL);
744 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
746 /* If the message ws not obtained from a treemodel,
747 * for instance if it was opened directly by the search UI:
749 if (priv->header_model == NULL) {
750 msg = modest_msg_view_window_get_message (self);
751 header = tny_msg_get_header (msg);
752 g_object_unref (msg);
756 /* Get iter of the currently selected message in the header view: */
757 /* TODO: Why not just give this window a ref of the TnyHeader or TnyMessage,
758 * instead of sometimes retrieving it from the header view?
759 * Then we wouldn't be dependent on the message actually still being selected
760 * in the header view. murrayc. */
761 path = gtk_tree_row_reference_get_path (priv->row_reference);
762 g_return_val_if_fail (path != NULL, NULL);
763 gtk_tree_model_get_iter (priv->header_model,
767 /* Get current message header */
768 gtk_tree_model_get (priv->header_model, &iter,
769 TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
772 gtk_tree_path_free (path);
777 modest_msg_view_window_get_message (ModestMsgViewWindow *self)
779 ModestMsgView *msg_view;
780 ModestMsgViewWindowPrivate *priv;
782 g_return_val_if_fail (self, NULL);
784 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
786 msg_view = MODEST_MSG_VIEW (priv->msg_view);
788 return modest_msg_view_get_message (msg_view);
792 modest_msg_view_window_get_message_uid (ModestMsgViewWindow *self)
794 ModestMsgViewWindowPrivate *priv;
796 g_return_val_if_fail (self, NULL);
798 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
800 return (const gchar*) priv->msg_uid;
804 modest_msg_view_window_toggle_find_toolbar (GtkToggleAction *toggle,
807 ModestMsgViewWindow *window = MODEST_MSG_VIEW_WINDOW (data);
808 ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
809 ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
813 is_active = gtk_toggle_action_get_active (toggle);
816 gtk_widget_show (priv->find_toolbar);
817 hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE);
819 gtk_widget_hide (priv->find_toolbar);
822 /* update the toggle buttons status */
823 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/FindInMessage");
824 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), is_active);
825 action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/ToolsFindInMessageMenu");
826 modest_maemo_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), is_active);
831 modest_msg_view_window_find_toolbar_close (GtkWidget *widget,
832 ModestMsgViewWindow *obj)
834 GtkToggleAction *toggle;
835 ModestWindowPrivate *parent_priv;
836 parent_priv = MODEST_WINDOW_GET_PRIVATE (obj);
838 toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/FindInMessage"));
839 gtk_toggle_action_set_active (toggle, FALSE);
843 modest_msg_view_window_find_toolbar_search (GtkWidget *widget,
844 ModestMsgViewWindow *obj)
846 gchar *current_search;
847 ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (obj);
849 if (modest_msg_view_get_message_is_empty (MODEST_MSG_VIEW (priv->msg_view))) {
850 hildon_banner_show_information (NULL, NULL, _("mail_ib_nothing_to_find"));
854 g_object_get (G_OBJECT (widget), "prefix", ¤t_search, NULL);
856 if ((current_search == NULL) || (strcmp (current_search, "") == 0)) {
857 g_free (current_search);
858 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ecdg_ib_find_rep_enter_text"));
862 if ((priv->last_search == NULL) || (strcmp (priv->last_search, current_search) != 0)) {
864 g_free (priv->last_search);
865 priv->last_search = g_strdup (current_search);
866 result = modest_msg_view_search (MODEST_MSG_VIEW (priv->msg_view),
869 hildon_banner_show_information (NULL, NULL, dgettext("hildon-libs", "ckct_ib_find_no_matches"));
870 g_free (priv->last_search);
871 priv->last_search = NULL;
874 if (!modest_msg_view_search_next (MODEST_MSG_VIEW (priv->msg_view))) {
875 hildon_banner_show_information (NULL, NULL, dgettext("hildon-libs", "ckct_ib_find_search_complete"));
876 g_free (priv->last_search);
877 priv->last_search = NULL;
881 g_free (current_search);
886 modest_msg_view_window_set_zoom (ModestWindow *window,
889 ModestMsgViewWindowPrivate *priv;
891 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
893 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
894 modest_msg_view_set_zoom (MODEST_MSG_VIEW (priv->msg_view), zoom);
898 modest_msg_view_window_get_zoom (ModestWindow *window)
900 ModestMsgViewWindowPrivate *priv;
902 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), 1.0);
904 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
905 return modest_msg_view_get_zoom (MODEST_MSG_VIEW (priv->msg_view));
909 modest_msg_view_window_zoom_plus (ModestWindow *window)
911 ModestWindowPrivate *parent_priv;
912 GtkRadioAction *zoom_radio_action;
913 GSList *group, *node;
915 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
916 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
917 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
919 group = gtk_radio_action_get_group (zoom_radio_action);
921 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (group->data))) {
922 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_max_zoom_level_reached"));
926 for (node = group; node != NULL; node = g_slist_next (node)) {
927 if ((node->next != NULL) && gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->next->data))) {
928 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->data), TRUE);
936 modest_msg_view_window_zoom_minus (ModestWindow *window)
938 ModestWindowPrivate *parent_priv;
939 GtkRadioAction *zoom_radio_action;
940 GSList *group, *node;
942 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
943 zoom_radio_action = GTK_RADIO_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager,
944 "/MenuBar/ViewMenu/ZoomMenu/Zoom50Menu"));
946 group = gtk_radio_action_get_group (zoom_radio_action);
948 for (node = group; node != NULL; node = g_slist_next (node)) {
949 if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (node->data))) {
950 if (node->next != NULL) {
951 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (node->next->data), TRUE);
954 hildon_banner_show_information (NULL, NULL, dgettext("hildon-common-strings", "ckct_ib_min_zoom_level_reached"));
964 modest_msg_view_window_key_release_event (GtkWidget *window,
968 if (event->type == GDK_KEY_RELEASE) {
969 switch (event->keyval) {
971 modest_msg_view_window_scroll_up (MODEST_WINDOW (window));
975 modest_msg_view_window_scroll_down (MODEST_WINDOW (window));
988 modest_msg_view_window_scroll_up (ModestWindow *window)
990 ModestMsgViewWindowPrivate *priv;
991 gboolean return_value;
993 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
994 g_signal_emit_by_name (G_OBJECT (priv->main_scroll), "scroll-child", GTK_SCROLL_STEP_UP, FALSE, &return_value);
998 modest_msg_view_window_scroll_down (ModestWindow *window)
1000 ModestMsgViewWindowPrivate *priv;
1001 gboolean return_value;
1003 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1004 g_signal_emit_by_name (G_OBJECT (priv->main_scroll), "scroll-child", GTK_SCROLL_STEP_DOWN, FALSE, &return_value);
1008 modest_msg_view_window_last_message_selected (ModestMsgViewWindow *window)
1011 ModestMsgViewWindowPrivate *priv;
1012 GtkTreeIter tmp_iter;
1013 gboolean has_next = FALSE;
1015 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), TRUE);
1016 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1018 if (priv->header_model) {
1019 path = gtk_tree_row_reference_get_path (priv->row_reference);
1020 if (path == NULL) return FALSE;
1023 gtk_tree_path_next (path);
1024 if (!gtk_tree_model_get_iter (priv->header_model, &tmp_iter, path))
1026 gtk_tree_model_get (priv->header_model, &tmp_iter, TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
1028 if (!(tny_header_get_flags(header) & TNY_HEADER_FLAG_DELETED)) {
1033 gtk_tree_path_free (path);
1042 modest_msg_view_window_has_headers_model (ModestMsgViewWindow *window)
1044 ModestMsgViewWindowPrivate *priv;
1046 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), TRUE);
1047 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1049 return priv->header_model != NULL;
1053 modest_msg_view_window_first_message_selected (ModestMsgViewWindow *window)
1056 ModestMsgViewWindowPrivate *priv;
1058 GtkTreeIter tmp_iter;
1060 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), TRUE);
1061 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1063 if (priv->header_model) {
1064 gchar * path_string;
1065 path = gtk_tree_row_reference_get_path (priv->row_reference);
1069 path_string = gtk_tree_path_to_string (path);
1070 result = (strcmp (path_string, "0")==0);
1072 g_free (path_string);
1073 gtk_tree_path_free (path);
1080 gtk_tree_path_prev (path);
1082 if (!gtk_tree_model_get_iter (priv->header_model, &tmp_iter, path))
1084 gtk_tree_model_get (priv->header_model, &tmp_iter, TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
1086 if (!(tny_header_get_flags(header)&TNY_HEADER_FLAG_DELETED)) {
1091 path_string = gtk_tree_path_to_string (path);
1092 if (strcmp(path_string, "0")==0) {
1093 g_free (path_string);
1096 g_free (path_string);
1098 gtk_tree_path_free (path);
1107 * Reads the message whose summary item is @header. It takes care of
1108 * several things, among others:
1110 * If the message was not previously downloaded then ask the user
1111 * before downloading. If there is no connection launch the connection
1112 * dialog. Update toolbar dimming rules.
1114 * Returns: TRUE if the mail operation was started, otherwise if the
1115 * user do not want to download the message, or if the user do not
1116 * want to connect, then the operation is not issued
1119 message_reader (ModestMsgViewWindow *window,
1120 ModestMsgViewWindowPrivate *priv,
1124 ModestMailOperation *mail_op = NULL;
1125 ModestMailOperationTypeOperation op_type;
1126 gboolean already_showing = FALSE;
1127 ModestWindow *msg_window = NULL;
1128 ModestWindowMgr *mgr;
1130 g_return_val_if_fail (path != NULL, FALSE);
1132 mgr = modest_runtime_get_window_mgr ();
1133 already_showing = modest_window_mgr_find_registered_header (mgr, header, &msg_window);
1134 if (already_showing && (msg_window != MODEST_WINDOW (window))) {
1137 gtk_window_present (GTK_WINDOW (msg_window));
1138 g_signal_emit_by_name (G_OBJECT (window), "delete-event", NULL, &retval);
1142 /* Msg download completed */
1143 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED) {
1144 op_type = MODEST_MAIL_OPERATION_TYPE_OPEN;
1147 GtkResponseType response;
1149 op_type = MODEST_MAIL_OPERATION_TYPE_RECEIVE;
1151 /* Ask the user if he wants to download the message */
1152 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
1153 _("mcen_nc_get_msg"));
1154 if (response == GTK_RESPONSE_CANCEL)
1157 /* Offer the connection dialog if necessary */
1158 /* FIXME: should this stuff go directly to the mail
1159 operation instead of spread it all over the
1161 folder = tny_header_get_folder (header);
1163 if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, TNY_FOLDER_STORE (folder))) {
1164 g_object_unref (folder);
1167 g_object_unref (folder);
1171 /* New mail operation */
1172 mail_op = modest_mail_operation_new_with_error_handling (op_type,
1174 modest_ui_actions_get_msgs_full_error_handler,
1177 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1178 modest_mail_operation_get_msg (mail_op, header, view_msg_cb, path);
1179 g_object_unref (mail_op);
1181 /* Update toolbar dimming rules */
1182 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
1188 modest_msg_view_window_select_next_message (ModestMsgViewWindow *window)
1190 ModestMsgViewWindowPrivate *priv;
1191 GtkTreePath *path= NULL;
1192 GtkTreeIter tmp_iter;
1194 gboolean retval = TRUE;
1196 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), FALSE);
1197 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1199 /* Update the next row reference if it's not valid. This could
1200 happen if for example the header which it was pointing to,
1201 was deleted. The best place to do it is in the row-deleted
1202 handler but the tinymail model do not work like the glib
1203 tree models and reports the deletion when the row is still
1205 if (!gtk_tree_row_reference_valid (priv->next_row_reference)) {
1206 if (gtk_tree_row_reference_valid (priv->row_reference)) {
1207 priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference);
1208 select_next_valid_row (priv->header_model, &(priv->next_row_reference), FALSE);
1211 if (priv->next_row_reference)
1212 path = gtk_tree_row_reference_get_path (priv->next_row_reference);
1216 gtk_tree_model_get_iter (priv->header_model,
1220 gtk_tree_model_get (priv->header_model, &tmp_iter,
1221 TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
1224 /* Read the message & show it */
1225 if (!message_reader (window, priv, header, path)) {
1227 gtk_tree_path_free (path);
1231 g_object_unref (header);
1237 modest_msg_view_window_select_first_message (ModestMsgViewWindow *self)
1239 ModestMsgViewWindowPrivate *priv = NULL;
1240 TnyHeader *header = NULL;
1244 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), FALSE);
1245 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
1247 /* Check that the model is not empty */
1248 if (!gtk_tree_model_get_iter_first (priv->header_model, &iter))
1251 /* Get the header */
1252 gtk_tree_model_get (priv->header_model,
1254 TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
1256 g_return_val_if_fail (TNY_IS_HEADER (header), FALSE);
1257 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_DELETED) {
1258 g_object_unref (header);
1259 return modest_msg_view_window_select_next_message (self);
1262 path = gtk_tree_model_get_path (priv->header_model, &iter);
1264 /* Read the message & show it */
1265 message_reader (self, priv, header, path);
1268 g_object_unref (header);
1274 modest_msg_view_window_select_previous_message (ModestMsgViewWindow *window)
1276 ModestMsgViewWindowPrivate *priv = NULL;
1279 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), FALSE);
1280 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1282 /* Return inmediatly if there is no header model */
1283 if (!priv->header_model)
1286 path = gtk_tree_row_reference_get_path (priv->row_reference);
1287 while (gtk_tree_path_prev (path)) {
1291 gtk_tree_model_get_iter (priv->header_model, &iter, path);
1292 gtk_tree_model_get (priv->header_model, &iter,
1293 TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
1297 if (tny_header_get_flags (header) & TNY_HEADER_FLAG_DELETED) {
1298 g_object_unref (header);
1302 /* Read the message & show it */
1303 if (!message_reader (window, priv, header, path)) {
1304 g_object_unref (header);
1308 g_object_unref (header);
1313 gtk_tree_path_free (path);
1318 view_msg_cb (ModestMailOperation *mail_op,
1323 ModestMsgViewWindow *self = NULL;
1324 ModestMsgViewWindowPrivate *priv = NULL;
1327 /* If there was any error */
1328 path = (GtkTreePath *) user_data;
1329 if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
1330 gtk_tree_path_free (path);
1334 /* Get the window */
1335 self = (ModestMsgViewWindow *) modest_mail_operation_get_source (mail_op);
1336 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self));
1337 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self);
1339 /* Update the row reference */
1340 gtk_tree_row_reference_free (priv->row_reference);
1341 priv->row_reference = gtk_tree_row_reference_new (priv->header_model, path);
1342 priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference);
1343 select_next_valid_row (priv->header_model, &(priv->next_row_reference), TRUE);
1344 gtk_tree_path_free (path);
1346 /* Mark header as read */
1347 if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_SEEN))
1348 tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
1350 /* Set new message */
1351 modest_msg_view_set_message (MODEST_MSG_VIEW (priv->msg_view), msg);
1352 modest_msg_view_window_update_priority (self);
1353 update_window_title (MODEST_MSG_VIEW_WINDOW (self));
1354 modest_msg_view_grab_focus (MODEST_MSG_VIEW (priv->msg_view));
1356 /* Set the new message uid of the window */
1357 if (priv->msg_uid) {
1358 g_free (priv->msg_uid);
1359 priv->msg_uid = modest_tny_folder_get_header_unique_id (header);
1362 /* Notify the observers */
1363 g_signal_emit (G_OBJECT (self), signals[MSG_CHANGED_SIGNAL],
1364 0, priv->header_model, priv->row_reference);
1366 /* Free new references */
1367 g_object_unref (self);
1371 modest_msg_view_window_get_folder_type (ModestMsgViewWindow *window)
1373 ModestMsgViewWindowPrivate *priv;
1375 TnyFolderType folder_type;
1377 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1379 folder_type = TNY_FOLDER_TYPE_UNKNOWN;
1381 msg = modest_msg_view_get_message (MODEST_MSG_VIEW (priv->msg_view));
1385 folder = tny_msg_get_folder (msg);
1388 folder_type = tny_folder_get_folder_type (folder);
1390 if (folder_type == TNY_FOLDER_TYPE_NORMAL || folder_type == TNY_FOLDER_TYPE_UNKNOWN) {
1391 const gchar *fname = tny_folder_get_name (folder);
1392 folder_type = modest_tny_folder_guess_folder_type_from_name (fname);
1395 g_object_unref (folder);
1397 g_object_unref (msg);
1405 modest_msg_view_window_update_priority (ModestMsgViewWindow *window)
1407 ModestMsgViewWindowPrivate *priv;
1408 TnyHeaderFlags flags = 0;
1410 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1412 if (priv->header_model) {
1415 GtkTreePath *path = NULL;
1417 path = gtk_tree_row_reference_get_path (priv->row_reference);
1418 g_return_if_fail (path != NULL);
1419 gtk_tree_model_get_iter (priv->header_model,
1421 gtk_tree_row_reference_get_path (priv->row_reference));
1423 gtk_tree_model_get (priv->header_model, &iter, TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN,
1425 flags = tny_header_get_flags (header);
1426 gtk_tree_path_free (path);
1429 modest_msg_view_set_priority (MODEST_MSG_VIEW(priv->msg_view), flags);
1434 modest_msg_view_window_window_state_event (GtkWidget *widget, GdkEventWindowState *event, gpointer userdata)
1436 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
1437 ModestWindowPrivate *parent_priv;
1438 ModestWindowMgr *mgr;
1439 gboolean is_fullscreen;
1440 GtkAction *fs_toggle_action;
1443 mgr = modest_runtime_get_window_mgr ();
1444 is_fullscreen = (modest_window_mgr_get_fullscreen_mode (mgr))?1:0;
1446 parent_priv = MODEST_WINDOW_GET_PRIVATE (widget);
1448 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1449 active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)))?1:0;
1450 if (is_fullscreen != active) {
1451 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action), is_fullscreen);
1460 modest_msg_view_window_toggle_fullscreen (ModestMsgViewWindow *window)
1462 ModestWindowPrivate *parent_priv;
1463 GtkAction *fs_toggle_action;
1464 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1466 fs_toggle_action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ViewMenu/ViewToggleFullscreenMenu");
1467 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (fs_toggle_action),
1468 !gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (fs_toggle_action)));
1472 set_homogeneous (GtkWidget *widget,
1475 if (GTK_IS_TOOL_ITEM (widget)) {
1476 gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE);
1477 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE);
1482 modest_msg_view_window_show_toolbar (ModestWindow *self,
1483 gboolean show_toolbar)
1485 ModestMsgViewWindowPrivate *priv = NULL;
1486 ModestWindowPrivate *parent_priv;
1487 GtkWidget *reply_button = NULL, *menu = NULL;
1488 GtkWidget *placeholder = NULL;
1491 parent_priv = MODEST_WINDOW_GET_PRIVATE(self);
1492 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
1494 /* Set optimized view status */
1495 priv->optimized_view = !show_toolbar;
1497 if (!parent_priv->toolbar) {
1498 parent_priv->toolbar = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1501 /* Set homogeneous toolbar */
1502 gtk_container_foreach (GTK_CONTAINER (parent_priv->toolbar),
1503 set_homogeneous, NULL);
1505 priv->progress_toolitem = GTK_WIDGET (gtk_tool_item_new ());
1506 priv->cancel_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarCancel");
1507 priv->next_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageNext");
1508 priv->prev_toolitem = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageBack");
1509 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1510 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->progress_toolitem), TRUE);
1511 gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1512 gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->cancel_toolitem), FALSE);
1514 /* Add ProgressBar (Transfer toolbar) */
1515 priv->progress_bar = modest_progress_bar_widget_new ();
1516 gtk_widget_set_no_show_all (priv->progress_bar, TRUE);
1517 placeholder = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ProgressbarView");
1518 insert_index = gtk_toolbar_get_item_index(GTK_TOOLBAR (parent_priv->toolbar), GTK_TOOL_ITEM(placeholder));
1519 gtk_container_add (GTK_CONTAINER (priv->progress_toolitem), priv->progress_bar);
1520 gtk_toolbar_insert(GTK_TOOLBAR(parent_priv->toolbar), GTK_TOOL_ITEM (priv->progress_toolitem), insert_index);
1522 /* Connect cancel 'clicked' signal to abort progress mode */
1523 g_signal_connect(priv->cancel_toolitem, "clicked",
1524 G_CALLBACK(cancel_progressbar),
1527 /* Add it to the observers list */
1528 priv->progress_widgets = g_slist_prepend(priv->progress_widgets, priv->progress_bar);
1531 hildon_window_add_toolbar (HILDON_WINDOW (self),
1532 GTK_TOOLBAR (parent_priv->toolbar));
1535 /* Set reply button tap and hold menu */
1536 reply_button = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1537 "/ToolBar/ToolbarMessageReply");
1538 menu = gtk_ui_manager_get_widget (parent_priv->ui_manager,
1539 "/ToolbarReplyCSM");
1540 gtk_widget_tap_and_hold_setup (GTK_WIDGET (reply_button), menu, NULL, 0);
1544 /* Quick hack: this prevents toolbar icons "dance" when progress bar show status is changed */
1545 /* TODO: resize mode migth be GTK_RESIZE_QUEUE, in order to avoid unneccesary shows */
1546 gtk_container_set_resize_mode (GTK_CONTAINER(parent_priv->toolbar), GTK_RESIZE_IMMEDIATE);
1548 gtk_widget_show (GTK_WIDGET (parent_priv->toolbar));
1549 set_toolbar_mode (MODEST_MSG_VIEW_WINDOW(self), TOOLBAR_MODE_NORMAL);
1552 gtk_widget_set_no_show_all (parent_priv->toolbar, TRUE);
1553 gtk_widget_hide (GTK_WIDGET (parent_priv->toolbar));
1558 modest_msg_view_window_clipboard_owner_change (GtkClipboard *clipboard,
1560 ModestMsgViewWindow *window)
1562 ModestWindowPrivate *parent_priv;
1563 /* GtkAction *action; */
1564 gboolean is_address;
1568 if (!GTK_WIDGET_VISIBLE (window))
1571 parent_priv = MODEST_WINDOW_GET_PRIVATE (window);
1572 selection = gtk_clipboard_wait_for_text (clipboard);
1574 is_address = ((selection != NULL) && (modest_text_utils_validate_recipient (selection, NULL)));
1576 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/ToolsMenu/ToolsAddToContactsMenu"); */
1577 /* gtk_action_set_sensitive (action, is_address); */
1579 focused = gtk_window_get_focus (GTK_WINDOW (window));
1581 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/EditCopyMenu"); */
1582 /* gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused))); */
1584 /* action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/MenuBar/EditMenu/EditCutMenu"); */
1585 /* gtk_action_set_sensitive (action, (selection != NULL) && (!MODEST_IS_ATTACHMENTS_VIEW (focused))); */
1588 /* modest_msg_view_window_update_dimmed (window); */
1593 modest_msg_view_window_transfer_mode_enabled (ModestMsgViewWindow *self)
1595 ModestMsgViewWindowPrivate *priv;
1597 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), FALSE);
1598 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
1600 return priv->current_toolbar_mode == TOOLBAR_MODE_TRANSFER;
1604 cancel_progressbar (GtkToolButton *toolbutton,
1605 ModestMsgViewWindow *self)
1608 ModestMsgViewWindowPrivate *priv;
1610 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
1612 /* Get operation observers and cancel its current operation */
1613 tmp = priv->progress_widgets;
1615 modest_progress_object_cancel_current_operation (MODEST_PROGRESS_OBJECT(tmp->data));
1616 tmp=g_slist_next(tmp);
1620 observers_empty (ModestMsgViewWindow *self)
1623 ModestMsgViewWindowPrivate *priv;
1624 gboolean is_empty = TRUE;
1625 guint pending_ops = 0;
1627 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
1628 tmp = priv->progress_widgets;
1630 /* Check all observers */
1631 while (tmp && is_empty) {
1632 pending_ops = modest_progress_object_num_pending_operations (MODEST_PROGRESS_OBJECT(tmp->data));
1633 is_empty = pending_ops == 0;
1635 tmp = g_slist_next(tmp);
1642 on_account_removed (TnyAccountStore *account_store,
1643 TnyAccount *account,
1646 /* Do nothing if it's a transport account, because we only
1647 show the messages of a store account */
1648 if (tny_account_get_account_type(account) == TNY_ACCOUNT_TYPE_STORE) {
1649 const gchar *parent_acc = NULL;
1650 const gchar *our_acc = NULL;
1652 our_acc = modest_window_get_active_account (MODEST_WINDOW (user_data));
1653 parent_acc = modest_tny_account_get_parent_modest_account_name_for_server_account (account);
1655 /* Close this window if I'm showing a message of the removed account */
1656 if (strcmp (parent_acc, our_acc) == 0)
1657 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (user_data));
1662 on_queue_changed (ModestMailOperationQueue *queue,
1663 ModestMailOperation *mail_op,
1664 ModestMailOperationQueueNotification type,
1665 ModestMsgViewWindow *self)
1668 ModestMsgViewWindowPrivate *priv;
1669 ModestMailOperationTypeOperation op_type;
1670 ModestToolBarModes mode;
1672 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self));
1673 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self);
1675 /* If this operations was created by another window, do nothing */
1676 if (!modest_mail_operation_is_mine (mail_op, G_OBJECT(self)))
1679 /* Get toolbar mode from operation id*/
1680 op_type = modest_mail_operation_get_type_operation (mail_op);
1682 /* case MODEST_MAIL_OPERATION_TYPE_SEND: */
1683 case MODEST_MAIL_OPERATION_TYPE_RECEIVE:
1684 case MODEST_MAIL_OPERATION_TYPE_OPEN:
1685 mode = TOOLBAR_MODE_TRANSFER;
1688 mode = TOOLBAR_MODE_NORMAL;
1692 /* Add operation observers and change toolbar if neccessary*/
1693 tmp = priv->progress_widgets;
1695 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_ADDED:
1696 if (mode == TOOLBAR_MODE_TRANSFER) {
1697 /* Enable transfer toolbar mode */
1698 set_toolbar_transfer_mode(self);
1700 modest_progress_object_add_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1702 tmp = g_slist_next (tmp);
1707 case MODEST_MAIL_OPERATION_QUEUE_OPERATION_REMOVED:
1708 if (mode == TOOLBAR_MODE_TRANSFER) {
1710 modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data),
1712 tmp = g_slist_next (tmp);
1716 /* If no more operations are being observed, NORMAL mode is enabled again */
1717 if (observers_empty (self)) {
1718 set_toolbar_mode (self, TOOLBAR_MODE_NORMAL);
1726 modest_msg_view_window_get_attachments (ModestMsgViewWindow *win)
1728 ModestMsgViewWindowPrivate *priv;
1729 GList *selected_attachments = NULL;
1731 g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (win), NULL);
1732 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (win);
1734 selected_attachments = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
1736 return selected_attachments;
1740 modest_msg_view_window_view_attachment (ModestMsgViewWindow *window, TnyMimePart *mime_part)
1742 ModestMsgViewWindowPrivate *priv;
1743 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
1744 g_return_if_fail (TNY_IS_MIME_PART (mime_part) || (mime_part == NULL));
1746 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1748 if (mime_part == NULL) {
1749 gboolean error = FALSE;
1750 GList *selected_attachments = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
1751 if (selected_attachments == NULL) {
1753 } else if (g_list_length (selected_attachments) > 1) {
1754 hildon_banner_show_information (NULL, NULL, _("mcen_ib_unable_to_display_more"));
1757 mime_part = (TnyMimePart *) selected_attachments->data;
1758 g_object_ref (mime_part);
1760 g_list_foreach (selected_attachments, (GFunc) g_object_unref, NULL);
1761 g_list_free (selected_attachments);
1766 g_object_ref (mime_part);
1769 if (tny_mime_part_is_purged (mime_part)) {
1770 g_object_unref (mime_part);
1771 hildon_banner_show_information (NULL, NULL, _("mail_ib_attach_not_local"));
1775 if (!TNY_IS_MSG (mime_part)) {
1776 gchar *filepath = NULL;
1777 const gchar *att_filename = tny_mime_part_get_filename (mime_part);
1778 gchar *extension = NULL;
1779 TnyFsStream *temp_stream = NULL;
1782 extension = g_strrstr (att_filename, ".");
1783 if (extension != NULL)
1787 temp_stream = modest_maemo_utils_create_temp_stream (extension, &filepath);
1790 const gchar *content_type;
1791 content_type = tny_mime_part_get_content_type (mime_part);
1792 tny_mime_part_decode_to_stream (mime_part, TNY_STREAM (temp_stream));
1794 modest_platform_activate_file (filepath, content_type);
1795 g_object_unref (temp_stream);
1797 /* TODO: delete temporary file */
1800 /* message attachment */
1801 TnyHeader *header = NULL;
1802 ModestWindowMgr *mgr;
1803 ModestWindow *msg_win = NULL;
1806 header = tny_msg_get_header (TNY_MSG (mime_part));
1807 mgr = modest_runtime_get_window_mgr ();
1808 found = modest_window_mgr_find_registered_header (mgr, header, &msg_win);
1811 if (msg_win) /* there is already a window for this uid; top it */
1812 gtk_window_present (GTK_WINDOW(msg_win));
1814 /* if it's found, but there is no msg_win, it's probably in the process of being created;
1815 * thus, we don't do anything */
1816 g_warning ("window for is already being created");
1818 /* it's not found, so create a new window for it */
1819 modest_window_mgr_register_header (mgr, header); /* register the uid before building the window */
1820 gchar *account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (window)));
1822 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr ());
1823 msg_win = modest_msg_view_window_new (TNY_MSG (mime_part), account, NULL);
1824 modest_window_set_zoom (MODEST_WINDOW (msg_win),
1825 modest_window_get_zoom (MODEST_WINDOW (window)));
1826 modest_window_mgr_register_window (mgr, msg_win);
1827 gtk_window_set_transient_for (GTK_WINDOW (msg_win), GTK_WINDOW (window));
1828 gtk_widget_show_all (GTK_WIDGET (msg_win));
1831 g_object_unref (mime_part);
1847 static void save_mime_part_info_free (SaveMimePartInfo *info, gboolean with_struct);
1848 static gboolean idle_save_mime_part_show_result (SaveMimePartInfo *info);
1849 static gpointer save_mime_part_to_file (SaveMimePartInfo *info);
1850 static void save_mime_parts_to_file_with_checks (SaveMimePartInfo *info);
1853 save_mime_part_info_free (SaveMimePartInfo *info, gboolean with_struct)
1857 for (node = info->pairs; node != NULL; node = g_list_next (node)) {
1858 SaveMimePartPair *pair = (SaveMimePartPair *) node->data;
1859 g_free (pair->filename);
1860 g_object_unref (pair->part);
1861 g_slice_free (SaveMimePartPair, pair);
1863 g_list_free (info->pairs);
1866 gtk_widget_destroy (info->banner);
1867 g_object_unref (info->banner);
1868 g_slice_free (SaveMimePartInfo, info);
1873 idle_save_mime_part_show_result (SaveMimePartInfo *info)
1875 if (info->pairs != NULL) {
1876 gdk_threads_enter ();
1877 save_mime_parts_to_file_with_checks (info);
1878 gdk_threads_leave ();
1881 result = info->result;
1883 gdk_threads_enter ();
1884 save_mime_part_info_free (info, TRUE);
1886 hildon_banner_show_information (NULL, NULL, _CS("sfil_ib_saved"));
1888 hildon_banner_show_information (NULL, NULL, _("mail_ib_file_operation_failed"));
1890 gdk_threads_leave ();
1897 save_mime_part_to_file (SaveMimePartInfo *info)
1899 GnomeVFSResult result;
1900 GnomeVFSHandle *handle;
1902 SaveMimePartPair *pair = (SaveMimePartPair *) info->pairs->data;
1904 result = gnome_vfs_create (&handle, pair->filename, GNOME_VFS_OPEN_WRITE, FALSE, 0777);
1905 if (result == GNOME_VFS_OK) {
1906 stream = tny_vfs_stream_new (handle);
1907 tny_mime_part_decode_to_stream (pair->part, stream);
1908 g_object_unref (G_OBJECT (stream));
1909 g_object_unref (pair->part);
1910 g_slice_free (SaveMimePartPair, pair);
1911 info->pairs = g_list_delete_link (info->pairs, info->pairs);
1912 info->result = TRUE;
1914 save_mime_part_info_free (info, FALSE);
1915 info->result = FALSE;
1918 g_idle_add ((GSourceFunc) idle_save_mime_part_show_result, info);
1923 save_mime_parts_to_file_with_checks (SaveMimePartInfo *info)
1925 SaveMimePartPair *pair;
1926 gboolean is_ok = TRUE;
1928 pair = info->pairs->data;
1929 if (modest_maemo_utils_file_exists (pair->filename)) {
1930 GtkWidget *confirm_overwrite_dialog;
1931 confirm_overwrite_dialog = hildon_note_new_confirmation (NULL,
1932 _("emev_nc_replace_files"));
1933 if (gtk_dialog_run (GTK_DIALOG (confirm_overwrite_dialog)) != GTK_RESPONSE_OK) {
1936 gtk_widget_destroy (confirm_overwrite_dialog);
1940 save_mime_part_info_free (info, TRUE);
1942 g_thread_create ((GThreadFunc)save_mime_part_to_file, info, FALSE, NULL);
1949 modest_msg_view_window_save_attachments (ModestMsgViewWindow *window, GList *mime_parts)
1951 gboolean clean_list = FALSE;
1952 ModestMsgViewWindowPrivate *priv;
1953 GList *files_to_save = NULL;
1954 GtkWidget *save_dialog = NULL;
1955 gchar *folder = NULL;
1956 gboolean canceled = FALSE;
1957 const gchar *filename = NULL;
1958 gchar *save_multiple_str = NULL;
1960 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
1961 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
1963 if (mime_parts == NULL) {
1964 mime_parts = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
1965 if (mime_parts == NULL)
1970 /* prepare dialog */
1971 if (mime_parts->next == NULL) {
1972 /* only one attachment selected */
1973 TnyMimePart *mime_part = (TnyMimePart *) mime_parts->data;
1974 if (!TNY_IS_MSG (mime_part) && tny_mime_part_is_attachment (mime_part)) {
1975 filename = tny_mime_part_get_filename (mime_part);
1977 g_warning ("Tried to save a non-file attachment");
1981 save_multiple_str = g_strdup_printf (_FM("sfil_va_number_of_objects_attachments"),
1982 g_list_length (mime_parts));
1985 save_dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window),
1986 GTK_FILE_CHOOSER_ACTION_SAVE);
1989 folder = g_build_filename (g_get_home_dir (), DEFAULT_FOLDER, NULL);
1990 gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (save_dialog), folder);
1994 if (filename != NULL)
1995 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (save_dialog),
1998 /* if multiple, set multiple string */
1999 if (save_multiple_str) {
2000 g_object_set (G_OBJECT (save_dialog), "save-multiple", save_multiple_str, NULL);
2004 if (gtk_dialog_run (GTK_DIALOG (save_dialog)) == GTK_RESPONSE_OK) {
2005 gchar *chooser_uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (save_dialog));
2007 if (!modest_maemo_utils_folder_writable (chooser_uri)) {
2008 hildon_banner_show_information
2009 (NULL, NULL, dgettext("hildon-fm", "sfil_ib_readonly_location"));
2013 for (node = mime_parts; node != NULL; node = g_list_next (node)) {
2014 TnyMimePart *mime_part = (TnyMimePart *) node->data;
2016 if (tny_mime_part_is_attachment (mime_part)) {
2017 SaveMimePartPair *pair;
2019 if ((mime_parts->next != NULL) &&
2020 (tny_mime_part_get_filename (mime_part) == NULL))
2023 pair = g_slice_new0 (SaveMimePartPair);
2024 if (mime_parts->next == NULL) {
2025 pair->filename = g_strdup (chooser_uri);
2028 g_build_filename (chooser_uri,
2029 tny_mime_part_get_filename (mime_part), NULL);
2031 pair->part = g_object_ref (mime_part);
2032 files_to_save = g_list_prepend (files_to_save, pair);
2036 g_free (chooser_uri);
2039 gtk_widget_destroy (save_dialog);
2042 g_list_foreach (mime_parts, (GFunc) g_object_unref, NULL);
2043 g_list_free (mime_parts);
2046 if (files_to_save != NULL) {
2047 SaveMimePartInfo *info = g_slice_new0 (SaveMimePartInfo);
2048 GtkWidget *banner = hildon_banner_show_animation (NULL, NULL,
2049 _CS("sfil_ib_saving"));
2050 info->pairs = files_to_save;
2051 info->banner = banner;
2052 info->result = TRUE;
2053 g_object_ref (banner);
2054 save_mime_parts_to_file_with_checks (info);
2059 modest_msg_view_window_remove_attachments (ModestMsgViewWindow *window, gboolean get_all)
2061 ModestMsgViewWindowPrivate *priv;
2062 GList *mime_parts = NULL, *node;
2063 gchar *confirmation_message;
2067 /* TnyFolder *folder; */
2069 g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
2070 priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
2073 mime_parts = modest_msg_view_get_attachments (MODEST_MSG_VIEW (priv->msg_view));
2075 mime_parts = modest_msg_view_get_selected_attachments (MODEST_MSG_VIEW (priv->msg_view));
2077 /* Remove already purged messages from mime parts list */
2079 while (node != NULL) {
2080 TnyMimePart *part = TNY_MIME_PART (node->data);
2081 if (tny_mime_part_is_purged (part)) {
2082 GList *deleted_node = node;
2083 node = g_list_next (node);
2084 g_object_unref (part);
2085 mime_parts = g_list_delete_link (mime_parts, deleted_node);
2087 node = g_list_next (node);
2091 if (mime_parts == NULL)
2094 n_attachments = g_list_length (mime_parts);
2095 if (n_attachments == 1) {
2096 const gchar *filename;
2098 if (TNY_IS_MSG (mime_parts->data)) {
2100 header = tny_msg_get_header (TNY_MSG (mime_parts->data));
2101 filename = tny_header_get_subject (header);
2102 g_object_unref (header);
2103 if (filename == NULL)
2104 filename = _("mail_va_no_subject");
2106 filename = tny_mime_part_get_filename (TNY_MIME_PART (mime_parts->data));
2108 confirmation_message = g_strdup_printf (_("mcen_nc_purge_file_text"), filename);
2110 confirmation_message = g_strdup_printf (ngettext("mcen_nc_purge_file_text",
2111 "mcen_nc_purge_files_text",
2112 n_attachments), n_attachments);
2114 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
2115 confirmation_message);
2116 g_free (confirmation_message);
2118 if (response != GTK_RESPONSE_OK)
2121 /* folder = tny_msg_get_folder (msg); */
2122 /* tny_msg_uncache_attachments (msg); */
2123 /* tny_folder_refresh (folder, NULL); */
2124 /* g_object_unref (folder); */
2126 modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
2128 for (node = mime_parts; node != NULL; node = g_list_next (node)) {
2129 tny_mime_part_set_purged (TNY_MIME_PART (node->data));
2130 /* modest_msg_view_remove_attachment (MODEST_MSG_VIEW (priv->msg_view), node->data); */
2133 msg = modest_msg_view_get_message (MODEST_MSG_VIEW (priv->msg_view));
2134 modest_msg_view_set_message (MODEST_MSG_VIEW (priv->msg_view), NULL);
2135 tny_msg_rewrite_cache (msg);
2136 modest_msg_view_set_message (MODEST_MSG_VIEW (priv->msg_view), msg);
2138 g_list_foreach (mime_parts, (GFunc) g_object_unref, NULL);
2139 g_list_free (mime_parts);
2146 update_window_title (ModestMsgViewWindow *window)
2148 ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window);
2150 TnyHeader *header = NULL;
2151 const gchar *subject = NULL;
2153 msg = modest_msg_view_get_message (MODEST_MSG_VIEW (priv->msg_view));
2155 header = tny_msg_get_header (msg);
2156 subject = tny_header_get_subject (header);
2157 g_object_unref (msg);
2160 if ((subject == NULL)||(subject[0] == '\0'))
2161 subject = _("mail_va_no_subject");
2163 gtk_window_set_title (GTK_WINDOW (window), subject);