X-Git-Url: http://git.maemo.org/git/?p=modest;a=blobdiff_plain;f=src%2Fhildon2%2Fmodest-msg-view-window.c;h=cf2f3f38166b42f53231c4b55cab0faca2135d21;hp=14f6212b8ccf698bf54b1b04c7fea7bc13db40ef;hb=f7b838795d57791e623ea279d8971d07864bcbf9;hpb=1f49ac9df5635e0427ef1c2e1b2cc0c30c7c0cd2 diff --git a/src/hildon2/modest-msg-view-window.c b/src/hildon2/modest-msg-view-window.c index 14f6212..cf2f3f3 100644 --- a/src/hildon2/modest-msg-view-window.c +++ b/src/hildon2/modest-msg-view-window.c @@ -66,6 +66,15 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #define MYDOCS_ENV "MYDOCSDIR" #define DOCS_FOLDER ".documents" @@ -85,6 +94,7 @@ struct _ModestMsgViewWindowPrivate { GtkWidget *prev_toolitem; GtkWidget *next_toolitem; gboolean progress_hint; + gint fetching_images; /* Optimized view enabled */ gboolean optimized_view; @@ -111,37 +121,39 @@ struct _ModestMsgViewWindowPrivate { gulong row_deleted_handler; gulong row_inserted_handler; gulong rows_reordered_handler; + gulong fetch_image_redraw_handler; guint purge_timeout; GtkWidget *remove_attachment_banner; gchar *msg_uid; + TnyMimePart *other_body; + TnyMsg * top_msg; GSList *sighandlers; }; static void modest_msg_view_window_class_init (ModestMsgViewWindowClass *klass); static void modest_msg_view_window_init (ModestMsgViewWindow *obj); -static void modest_header_view_observer_init( - ModestHeaderViewObserverIface *iface_class); +static void modest_header_view_observer_init (ModestHeaderViewObserverIface *iface_class); static void modest_msg_view_window_finalize (GObject *obj); -static void modest_msg_view_window_toggle_find_toolbar (GtkToggleAction *obj, - gpointer data); -static void modest_msg_view_window_find_toolbar_close (GtkWidget *widget, - ModestMsgViewWindow *obj); +static void modest_msg_view_window_show_find_toolbar (GtkWidget *obj, gpointer data); +static void modest_msg_view_window_find_toolbar_close (GtkWidget *widget, + ModestMsgViewWindow *obj); static void modest_msg_view_window_find_toolbar_search (GtkWidget *widget, - ModestMsgViewWindow *obj); - + ModestMsgViewWindow *obj); +static void modest_msg_view_window_toggle_find_toolbar (GtkWidget *obj, + gpointer data); static void modest_msg_view_window_disconnect_signals (ModestWindow *self); -static gdouble modest_msg_view_window_get_zoom (ModestWindow *window); -static void modest_msg_view_window_set_zoom (ModestWindow *window, - gdouble zoom); +static gdouble modest_msg_view_window_get_zoom (ModestWindow *window); +static void modest_msg_view_window_set_zoom (ModestWindow *window, + gdouble zoom); static gboolean modest_msg_view_window_zoom_minus (ModestWindow *window); -static gboolean modest_msg_view_window_zoom_plus (ModestWindow *window); -static gboolean modest_msg_view_window_key_event (GtkWidget *window, - GdkEventKey *event, - gpointer userdata); +static gboolean modest_msg_view_window_zoom_plus (ModestWindow *window); +static gboolean modest_msg_view_window_key_event (GtkWidget *window, + GdkEventKey *event, + gpointer userdata); static void modest_msg_view_window_update_priority (ModestMsgViewWindow *window); static void modest_msg_view_window_show_toolbar (ModestWindow *window, @@ -200,7 +212,6 @@ static void set_progress_hint (ModestMsgViewWindow *self, static void update_window_title (ModestMsgViewWindow *window); -static gboolean set_toolbar_transfer_mode (ModestMsgViewWindow *self); static void init_window (ModestMsgViewWindow *obj); static gboolean msg_is_visible (TnyHeader *header, gboolean check_outbox); @@ -219,12 +230,21 @@ static gboolean modest_msg_view_window_scroll_child (ModestMsgViewWindow *self, static gboolean message_reader (ModestMsgViewWindow *window, ModestMsgViewWindowPrivate *priv, TnyHeader *header, + const gchar *msg_uid, + TnyFolder *folder, GtkTreeRowReference *row_reference); static void setup_menu (ModestMsgViewWindow *self); static gboolean _modest_msg_view_window_map_event (GtkWidget *widget, GdkEvent *event, gpointer userdata); +static void update_branding (ModestMsgViewWindow *self); +static void sync_flags (ModestMsgViewWindow *self); +static gboolean on_handle_calendar (ModestMsgView *msgview, TnyMimePart *calendar_part, + GtkContainer *container, ModestMsgViewWindow *self); + +static gboolean on_realize (GtkWidget *widget, + gpointer userdata); /* list my signals */ enum { @@ -234,10 +254,9 @@ enum { }; static const GtkToggleActionEntry msg_view_toggle_action_entries [] = { - { "FindInMessage", MODEST_TOOLBAR_ICON_FIND, N_("qgn_toolb_gene_find"), NULL, NULL, G_CALLBACK (modest_msg_view_window_toggle_find_toolbar), FALSE }, + { "FindInMessage", MODEST_TOOLBAR_ICON_FIND, N_("qgn_toolb_gene_find"), "F", NULL, G_CALLBACK (modest_msg_view_window_toggle_find_toolbar), FALSE }, }; - #define MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), \ MODEST_TYPE_MSG_VIEW_WINDOW, \ ModestMsgViewWindowPrivate)) @@ -286,22 +305,48 @@ static void save_state (ModestWindow *self) { modest_widget_memory_save (modest_runtime_get_conf (), - G_OBJECT(self), + G_OBJECT(self), MODEST_CONF_MSG_VIEW_WINDOW_KEY); } -static -gboolean modest_msg_view_window_scroll_child (ModestMsgViewWindow *self, - GtkScrollType scroll_type, - gboolean horizontal, - gpointer userdata) +static gboolean +modest_msg_view_window_scroll_child (ModestMsgViewWindow *self, + GtkScrollType scroll_type, + gboolean horizontal, + gpointer userdata) { ModestMsgViewWindowPrivate *priv; - gboolean return_value; + gint step = 0; priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self); - g_signal_emit_by_name (priv->main_scroll, "scroll-child", scroll_type, horizontal, &return_value); - return return_value; + + switch (scroll_type) { + case GTK_SCROLL_STEP_UP: + step = -1; + break; + case GTK_SCROLL_STEP_DOWN: + step = +1; + break; + case GTK_SCROLL_PAGE_UP: + step = -6; + break; + case GTK_SCROLL_PAGE_DOWN: + step = +6; + break; + case GTK_SCROLL_START: + step = -100; + break; + case GTK_SCROLL_END: + step = +100; + break; + default: + step = 0; + } + + if (step) + modest_maemo_utils_scroll_pannable((HildonPannableArea *) priv->main_scroll, 0, step); + + return (gboolean) step; } static void @@ -310,7 +355,7 @@ add_scroll_binding (GtkBindingSet *binding_set, GtkScrollType scroll) { guint keypad_keyval = keyval - GDK_Left + GDK_KP_Left; - + gtk_binding_entry_add_signal (binding_set, keyval, 0, "scroll_child", 2, GTK_TYPE_SCROLL_TYPE, scroll, @@ -390,7 +435,6 @@ modest_msg_view_window_init (ModestMsgViewWindow *obj) ModestWindowPrivate *parent_priv = NULL; GtkActionGroup *action_group = NULL; GError *error = NULL; - GdkPixbuf *window_icon; priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(obj); parent_priv = MODEST_WINDOW_GET_PRIVATE(obj); @@ -439,43 +483,41 @@ modest_msg_view_window_init (ModestMsgViewWindow *obj) priv->row_deleted_handler = 0; priv->row_inserted_handler = 0; priv->rows_reordered_handler = 0; + priv->fetch_image_redraw_handler = 0; priv->progress_hint = FALSE; + priv->fetching_images = 0; priv->optimized_view = FALSE; priv->purge_timeout = 0; priv->remove_attachment_banner = NULL; priv->msg_uid = NULL; - + priv->other_body = NULL; + priv->sighandlers = NULL; - + /* Init window */ init_window (MODEST_MSG_VIEW_WINDOW(obj)); - - /* Set window icon */ - window_icon = modest_platform_get_icon (MODEST_APP_MSG_VIEW_ICON, MODEST_ICON_SIZE_BIG); - if (window_icon) { - gtk_window_set_icon (GTK_WINDOW (obj), window_icon); - g_object_unref (window_icon); - } - + hildon_program_add_window (hildon_program_get_instance(), HILDON_WINDOW(obj)); + /* Grab the zoom keys, it will be used for Zoom and not for + changing volume */ + g_signal_connect (G_OBJECT (obj), "realize", + G_CALLBACK (on_realize), + NULL); } - -static gboolean -set_toolbar_transfer_mode (ModestMsgViewWindow *self) +static void +update_progress_hint (ModestMsgViewWindow *self) { - ModestMsgViewWindowPrivate *priv = NULL; - - g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), FALSE); - + ModestMsgViewWindowPrivate *priv; priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self); - set_progress_hint (self, TRUE); - - return FALSE; + if (GTK_WIDGET_VISIBLE (self)) { + hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), + (priv->progress_hint || (priv->fetching_images > 0))?1:0); + } } static void @@ -493,9 +535,7 @@ set_progress_hint (ModestMsgViewWindow *self, /* Sets current progress hint */ priv->progress_hint = enabled; - if (GTK_WIDGET_VISIBLE (self)) { - hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), enabled?1:0); - } + update_progress_hint (self); } @@ -511,29 +551,15 @@ init_window (ModestMsgViewWindow *obj) priv->msg_view = GTK_WIDGET (tny_platform_factory_new_msg_view (modest_tny_platform_factory_get_instance ())); modest_msg_view_set_shadow_type (MODEST_MSG_VIEW (priv->msg_view), GTK_SHADOW_NONE); main_vbox = gtk_vbox_new (FALSE, 6); -#ifdef MODEST_TOOLKIT_HILDON2 priv->main_scroll = hildon_pannable_area_new (); + g_object_set (G_OBJECT (priv->main_scroll), + "mov-mode", HILDON_MOVEMENT_MODE_BOTH, + "hovershoot-max", 0, + NULL); gtk_container_add (GTK_CONTAINER (priv->main_scroll), priv->msg_view); -#else -#ifdef MODEST_USE_MOZEMBED - priv->main_scroll = priv->msg_view; - gtk_widget_set_size_request (priv->msg_view, -1, 1600); -#else - priv->main_scroll = gtk_scrolled_window_new (NULL, NULL); - gtk_container_add (GTK_CONTAINER (priv->main_scroll), priv->msg_view); -#endif - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->main_scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (priv->main_scroll), GTK_SHADOW_NONE); - modest_maemo_set_thumbable_scrollbar (GTK_SCROLLED_WINDOW(priv->main_scroll), TRUE); - -#endif gtk_box_pack_start (GTK_BOX(main_vbox), priv->main_scroll, TRUE, TRUE, 0); gtk_container_add (GTK_CONTAINER(obj), main_vbox); - priv->find_toolbar = hildon_find_toolbar_new (NULL); - hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar)); - gtk_widget_set_no_show_all (priv->find_toolbar, TRUE); - /* NULL-ize fields if the window is destroyed */ g_signal_connect (priv->msg_view, "destroy", G_CALLBACK (gtk_widget_destroyed), &(priv->msg_view)); @@ -598,7 +624,7 @@ modest_msg_view_window_disconnect_signals (ModestWindow *self) MODEST_HEADER_VIEW_OBSERVER(self)); } } -} +} static void modest_msg_view_window_finalize (GObject *obj) @@ -611,6 +637,21 @@ modest_msg_view_window_finalize (GObject *obj) call this function before */ modest_msg_view_window_disconnect_signals (MODEST_WINDOW (obj)); + if (priv->fetch_image_redraw_handler > 0) { + g_source_remove (priv->fetch_image_redraw_handler); + priv->fetch_image_redraw_handler = 0; + } + + if (priv->other_body != NULL) { + g_object_unref (priv->other_body); + priv->other_body = NULL; + } + + if (priv->top_msg != NULL) { + g_object_unref (priv->top_msg); + priv->top_msg = NULL; + } + if (priv->header_model != NULL) { g_object_unref (priv->header_model); priv->header_model = NULL; @@ -778,6 +819,10 @@ modest_msg_view_window_construct (ModestMsgViewWindow *self, G_CALLBACK (modest_ui_actions_on_details), obj); g_signal_connect (G_OBJECT(priv->msg_view), "link_contextual", G_CALLBACK (modest_ui_actions_on_msg_link_contextual), obj); + g_signal_connect (G_OBJECT(priv->msg_view), "limit_error", + G_CALLBACK (modest_ui_actions_on_limit_error), obj); + g_signal_connect (G_OBJECT(priv->msg_view), "handle_calendar", + G_CALLBACK (on_handle_calendar), obj); g_signal_connect (G_OBJECT (priv->msg_view), "fetch_image", G_CALLBACK (on_fetch_image), obj); @@ -811,12 +856,20 @@ modest_msg_view_window_construct (ModestMsgViewWindow *self, modest_window_set_active_account (MODEST_WINDOW(obj), modest_account_name); modest_window_set_active_mailbox (MODEST_WINDOW(obj), mailbox); - g_signal_connect (G_OBJECT (priv->find_toolbar), "close", G_CALLBACK (modest_msg_view_window_find_toolbar_close), obj); - g_signal_connect (G_OBJECT (priv->find_toolbar), "search", G_CALLBACK (modest_msg_view_window_find_toolbar_search), obj); - priv->last_search = NULL; - + /* First add out toolbar ... */ modest_msg_view_window_show_toolbar (MODEST_WINDOW (obj), TRUE); + /* ... and later the find toolbar. This way find toolbar will + be shown over the other */ + priv->find_toolbar = hildon_find_toolbar_new (NULL); + hildon_window_add_toolbar (HILDON_WINDOW (obj), GTK_TOOLBAR (priv->find_toolbar)); + gtk_widget_set_no_show_all (priv->find_toolbar, TRUE); + g_signal_connect (G_OBJECT (priv->find_toolbar), "close", + G_CALLBACK (modest_msg_view_window_find_toolbar_close), obj); + g_signal_connect (G_OBJECT (priv->find_toolbar), "search", + G_CALLBACK (modest_msg_view_window_find_toolbar_search), obj); + priv->last_search = NULL; + /* Init the clipboard actions dim status */ modest_msg_view_grab_focus(MODEST_MSG_VIEW (priv->msg_view)); @@ -838,7 +891,6 @@ modest_msg_view_window_new_with_header_model (TnyMsg *msg, ModestMsgViewWindowPrivate *priv = NULL; TnyFolder *header_folder = NULL; ModestHeaderView *header_view = NULL; - ModestWindow *main_window = NULL; ModestWindowMgr *mgr = NULL; MODEST_DEBUG_BLOCK ( @@ -852,35 +904,22 @@ modest_msg_view_window_new_with_header_model (TnyMsg *msg, modest_msg_view_window_construct (window, modest_account_name, mailbox, msg_uid); priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window); + priv->top_msg = NULL; - /* Remember the message list's TreeModel so we can detect changes + /* Remember the message list's TreeModel so we can detect changes * and change the list selection when necessary: */ - - main_window = modest_window_mgr_get_main_window(mgr, FALSE); /* don't create */ - if (main_window) { - header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget( - MODEST_MAIN_WINDOW(main_window), - MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW)); - } - - if (header_view != NULL){ - header_folder = modest_header_view_get_folder(header_view); - /* This could happen if the header folder was - unseleted before opening this msg window (for - example if the user selects an account in the - folder view of the main window */ - if (header_folder) { - priv->is_outbox = (modest_tny_folder_guess_folder_type (header_folder) == TNY_FOLDER_TYPE_OUTBOX); - priv->header_folder_id = tny_folder_get_id(header_folder); - g_assert(priv->header_folder_id != NULL); - g_object_unref(header_folder); - } + header_folder = modest_header_view_get_folder (header_view); + if (header_folder) { + priv->is_outbox = (modest_tny_folder_guess_folder_type (header_folder) == + TNY_FOLDER_TYPE_OUTBOX); + priv->header_folder_id = tny_folder_get_id (header_folder); + g_object_unref(header_folder); } /* Setup row references and connect signals */ priv->header_model = g_object_ref (model); - if (row_reference) { + if (row_reference && gtk_tree_row_reference_valid (row_reference)) { priv->row_reference = gtk_tree_row_reference_copy (row_reference); priv->next_row_reference = gtk_tree_row_reference_copy (row_reference); select_next_valid_row (model, &(priv->next_row_reference), TRUE, priv->is_outbox); @@ -914,6 +953,7 @@ modest_msg_view_window_new_with_header_model (TnyMsg *msg, tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), msg); update_window_title (MODEST_MSG_VIEW_WINDOW (window)); + update_branding (MODEST_MSG_VIEW_WINDOW (window)); /* gtk_widget_show_all (GTK_WIDGET (window)); */ modest_msg_view_window_update_priority (window); @@ -926,11 +966,89 @@ modest_msg_view_window_new_with_header_model (TnyMsg *msg, } ModestWindow * -modest_msg_view_window_new_from_header_view (ModestHeaderView *header_view, - const gchar *modest_account_name, +modest_msg_view_window_new_from_uid (const gchar *modest_account_name, + const gchar *mailbox, + const gchar *msg_uid) +{ + ModestMsgViewWindow *window = NULL; + ModestMsgViewWindowPrivate *priv = NULL; + ModestWindowMgr *mgr = NULL; + gboolean is_merge; + TnyAccount *account = NULL; + + mgr = modest_runtime_get_window_mgr (); + window = MODEST_MSG_VIEW_WINDOW (modest_window_mgr_get_msg_view_window (mgr)); + g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), NULL); + + modest_msg_view_window_construct (window, modest_account_name, mailbox, msg_uid); + + priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window); + priv->top_msg = NULL; + + is_merge = g_str_has_prefix (msg_uid, "merge:"); + + /* Get the account */ + if (!is_merge) + account = tny_account_store_find_account (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()), + msg_uid); + + if (is_merge || account) { + TnyFolder *folder = NULL; + + /* Try to get the message, if it's already downloaded + we don't need to connect */ + if (account) { + folder = modest_tny_folder_store_find_folder_from_uri (TNY_FOLDER_STORE (account), msg_uid); + } else { + ModestTnyAccountStore *account_store; + ModestTnyLocalFoldersAccount *local_folders_account; + + account_store = modest_runtime_get_account_store (); + local_folders_account = MODEST_TNY_LOCAL_FOLDERS_ACCOUNT ( + modest_tny_account_store_get_local_folders_account (account_store)); + folder = modest_tny_local_folders_account_get_merged_outbox (local_folders_account); + g_object_unref (local_folders_account); + } + if (folder) { + TnyDevice *device; + gboolean device_online; + + device = modest_runtime_get_device(); + device_online = tny_device_is_online (device); + if (device_online) { + message_reader (window, priv, NULL, msg_uid, folder, NULL); + } else { + TnyMsg *msg = tny_folder_find_msg (folder, msg_uid, NULL); + if (msg) { + tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), msg); + update_window_title (MODEST_MSG_VIEW_WINDOW (window)); + update_branding (MODEST_MSG_VIEW_WINDOW (window)); + g_object_unref (msg); + /* Sync flags to server */ + sync_flags (MODEST_MSG_VIEW_WINDOW (window)); + } else { + message_reader (window, priv, NULL, msg_uid, folder, NULL); + } + } + g_object_unref (folder); + } + + } + + /* Check dimming rules */ + modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window)); + modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window)); + modest_window_check_dimming_rules_group (MODEST_WINDOW (window), MODEST_DIMMING_RULES_CLIPBOARD); + + return MODEST_WINDOW(window); +} + +ModestWindow * +modest_msg_view_window_new_from_header_view (ModestHeaderView *header_view, + const gchar *modest_account_name, const gchar *mailbox, - const gchar *msg_uid, - GtkTreeRowReference *row_reference) + const gchar *msg_uid, + GtkTreeRowReference *row_reference) { ModestMsgViewWindow *window = NULL; ModestMsgViewWindowPrivate *priv = NULL; @@ -946,6 +1064,7 @@ modest_msg_view_window_new_from_header_view (ModestHeaderView *header_view, modest_msg_view_window_construct (window, modest_account_name, mailbox, msg_uid); priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window); + priv->top_msg = NULL; /* Remember the message list's TreeModel so we can detect changes * and change the list selection when necessary: */ @@ -957,9 +1076,9 @@ modest_msg_view_window_new_from_header_view (ModestHeaderView *header_view, example if the user selects an account in the folder view of the main window */ if (header_folder) { - priv->is_outbox = (modest_tny_folder_guess_folder_type (header_folder) == TNY_FOLDER_TYPE_OUTBOX); + priv->is_outbox = (modest_tny_folder_guess_folder_type (header_folder) == + TNY_FOLDER_TYPE_OUTBOX); priv->header_folder_id = tny_folder_get_id(header_folder); - g_assert(priv->header_folder_id != NULL); g_object_unref(header_folder); } } @@ -968,7 +1087,7 @@ modest_msg_view_window_new_from_header_view (ModestHeaderView *header_view, priv->header_model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)); g_object_ref (priv->header_model); - if (row_reference) { + if (row_reference && gtk_tree_row_reference_valid (row_reference)) { priv->row_reference = gtk_tree_row_reference_copy (row_reference); priv->next_row_reference = gtk_tree_row_reference_copy (row_reference); select_next_valid_row (priv->header_model, &(priv->next_row_reference), TRUE, priv->is_outbox); @@ -997,21 +1116,24 @@ modest_msg_view_window_new_from_header_view (ModestHeaderView *header_view, if (header_view != NULL){ modest_header_view_add_observer(header_view, - MODEST_HEADER_VIEW_OBSERVER(window)); + MODEST_HEADER_VIEW_OBSERVER(window)); } tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), NULL); + update_branding (MODEST_MSG_VIEW_WINDOW (window)); - path = gtk_tree_row_reference_get_path (row_reference); - if (gtk_tree_model_get_iter (priv->header_model, &iter, path)) { - TnyHeader *header; - gtk_tree_model_get (priv->header_model, &iter, - TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN, - &header, -1); - message_reader (window, priv, header, row_reference); + if (priv->row_reference) { + path = gtk_tree_row_reference_get_path (priv->row_reference); + if (gtk_tree_model_get_iter (priv->header_model, &iter, path)) { + TnyHeader *header; + gtk_tree_model_get (priv->header_model, &iter, + TNY_GTK_HEADER_LIST_MODEL_INSTANCE_COLUMN, + &header, -1); + message_reader (window, priv, header, NULL, NULL, priv->row_reference); + g_object_unref (header); + } + gtk_tree_path_free (path); } - gtk_tree_path_free (path); - /* Check dimming rules */ modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window)); modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window)); @@ -1021,7 +1143,7 @@ modest_msg_view_window_new_from_header_view (ModestHeaderView *header_view, } ModestWindow * -modest_msg_view_window_new_for_search_result (TnyMsg *msg, +modest_msg_view_window_new_for_search_result (TnyMsg *msg, const gchar *modest_account_name, const gchar *mailbox, const gchar *msg_uid) @@ -1036,12 +1158,14 @@ modest_msg_view_window_new_for_search_result (TnyMsg *msg, modest_msg_view_window_construct (window, modest_account_name, mailbox, msg_uid); priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window); + priv->top_msg = NULL; /* Remember that this is a search result, * so we can disable some UI appropriately: */ priv->is_search_result = TRUE; tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), msg); + update_branding (MODEST_MSG_VIEW_WINDOW (window)); update_window_title (window); /* gtk_widget_show_all (GTK_WIDGET (window));*/ @@ -1055,11 +1179,24 @@ modest_msg_view_window_new_for_search_result (TnyMsg *msg, return MODEST_WINDOW(window); } +gboolean +modest_msg_view_window_is_other_body (ModestMsgViewWindow *self) +{ + ModestMsgViewWindowPrivate *priv = NULL; + + g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), FALSE); + priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self); + + return (priv->other_body != NULL); +} + ModestWindow * -modest_msg_view_window_new_for_attachment (TnyMsg *msg, - const gchar *modest_account_name, - const gchar *mailbox, - const gchar *msg_uid) +modest_msg_view_window_new_with_other_body (TnyMsg *msg, + TnyMimePart *other_body, + TnyMsg *top_msg, + const gchar *modest_account_name, + const gchar *mailbox, + const gchar *msg_uid) { GObject *obj = NULL; ModestMsgViewWindowPrivate *priv; @@ -1072,8 +1209,19 @@ modest_msg_view_window_new_for_attachment (TnyMsg *msg, modest_msg_view_window_construct (MODEST_MSG_VIEW_WINDOW (obj), modest_account_name, mailbox, msg_uid); - tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), msg); + if (other_body) { + priv->other_body = g_object_ref (other_body); + modest_msg_view_set_msg_with_other_body (MODEST_MSG_VIEW (priv->msg_view), msg, other_body); + } else { + tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), msg); + } + if (top_msg) { + priv->top_msg = g_object_ref (top_msg); + } else { + priv->top_msg = NULL; + } update_window_title (MODEST_MSG_VIEW_WINDOW (obj)); + update_branding (MODEST_MSG_VIEW_WINDOW (obj)); /* gtk_widget_show_all (GTK_WIDGET (obj)); */ @@ -1085,6 +1233,16 @@ modest_msg_view_window_new_for_attachment (TnyMsg *msg, return MODEST_WINDOW(obj); } +ModestWindow * +modest_msg_view_window_new_for_attachment (TnyMsg *msg, + TnyMsg *top_msg, + const gchar *modest_account_name, + const gchar *mailbox, + const gchar *msg_uid) +{ + return modest_msg_view_window_new_with_other_body (msg, NULL, top_msg, modest_account_name, mailbox, msg_uid); +} + static void modest_msg_view_window_on_row_changed (GtkTreeModel *header_model, GtkTreePath *arg1, @@ -1164,7 +1322,7 @@ modest_msg_view_window_on_row_inserted (GtkTreeModel *model, /* Setup row_reference for the actual msg. */ priv->row_reference = gtk_tree_row_reference_new (priv->header_model, tree_path); if (priv->row_reference == NULL) { - g_warning("No reference for msg header item."); + g_warning("%s: No reference for msg header item.", __FUNCTION__); return; } @@ -1202,41 +1360,41 @@ modest_msg_view_window_on_row_reordered (GtkTreeModel *header_model, gpointer arg3, ModestMsgViewWindow *window) { - ModestMsgViewWindowPrivate *priv = NULL; + ModestMsgViewWindowPrivate *priv = NULL; gboolean already_changed = FALSE; priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(window); /* If the current row was reordered select the proper next valid row. The same if the next row reference changes */ - if (priv->row_reference && - gtk_tree_row_reference_valid (priv->row_reference)) { - GtkTreePath *path; - path = gtk_tree_row_reference_get_path (priv->row_reference); - if (gtk_tree_path_compare (path, arg1) == 0) { - if (priv->next_row_reference) { - gtk_tree_row_reference_free (priv->next_row_reference); - } - priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference); - select_next_valid_row (header_model, &(priv->next_row_reference), FALSE, priv->is_outbox); - already_changed = TRUE; - } - gtk_tree_path_free (path); - } - if (!already_changed && - priv->next_row_reference && + if (!priv->row_reference || + !gtk_tree_row_reference_valid (priv->row_reference)) + return; + + if (priv->next_row_reference && gtk_tree_row_reference_valid (priv->next_row_reference)) { - GtkTreePath *path; - path = gtk_tree_row_reference_get_path (priv->next_row_reference); - if (gtk_tree_path_compare (path, arg1) == 0) { - if (priv->next_row_reference) { - gtk_tree_row_reference_free (priv->next_row_reference); - } + GtkTreePath *cur, *next; + /* Check that the order is still the correct one */ + cur = gtk_tree_row_reference_get_path (priv->row_reference); + next = gtk_tree_row_reference_get_path (priv->next_row_reference); + gtk_tree_path_next (cur); + if (gtk_tree_path_compare (cur, next) != 0) { + gtk_tree_row_reference_free (priv->next_row_reference); priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference); select_next_valid_row (header_model, &(priv->next_row_reference), FALSE, priv->is_outbox); + already_changed = TRUE; } - gtk_tree_path_free (path); + gtk_tree_path_free (cur); + gtk_tree_path_free (next); + } else { + if (priv->next_row_reference) + gtk_tree_row_reference_free (priv->next_row_reference); + /* Update next row reference */ + priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference); + select_next_valid_row (header_model, &(priv->next_row_reference), FALSE, priv->is_outbox); + already_changed = TRUE; } + check_dimming_rules_after_change (window); } @@ -1389,6 +1547,21 @@ modest_msg_view_window_get_message (ModestMsgViewWindow *self) return tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view)); } +TnyMsg* +modest_msg_view_window_get_top_message (ModestMsgViewWindow *self) +{ + ModestMsgViewWindowPrivate *priv; + + g_return_val_if_fail (self, NULL); + + priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE(self); + + if (priv->top_msg) + return g_object_ref (priv->top_msg); + else + return NULL; +} + const gchar* modest_msg_view_window_get_message_uid (ModestMsgViewWindow *self) { @@ -1401,46 +1574,44 @@ modest_msg_view_window_get_message_uid (ModestMsgViewWindow *self) return (const gchar*) priv->msg_uid; } -static void -modest_msg_view_window_toggle_find_toolbar (GtkToggleAction *toggle, +/* Used for the Ctrl+F accelerator */ +static void +modest_msg_view_window_toggle_find_toolbar (GtkWidget *obj, gpointer data) { ModestMsgViewWindow *window = MODEST_MSG_VIEW_WINDOW (data); ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window); - ModestWindowPrivate *parent_priv = MODEST_WINDOW_GET_PRIVATE (window); - gboolean is_active; - GtkAction *action; - is_active = gtk_toggle_action_get_active (toggle); - - if (is_active) { - gtk_widget_show (priv->find_toolbar); - hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE); - } else { - gtk_widget_hide (priv->find_toolbar); - modest_msg_view_grab_focus (MODEST_MSG_VIEW (priv->msg_view)); - } + if (GTK_WIDGET_VISIBLE (priv->find_toolbar)) { + modest_msg_view_window_find_toolbar_close (obj, data); + } else { + modest_msg_view_window_show_find_toolbar (obj, data); + } +} - /* update the toggle buttons status */ - action = gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/FindInMessage"); - if (action) - modest_utils_toggle_action_set_active_block_notify (GTK_TOGGLE_ACTION (action), is_active); +/* Handler for menu option */ +static void +modest_msg_view_window_show_find_toolbar (GtkWidget *obj, + gpointer data) +{ + ModestMsgViewWindow *window = MODEST_MSG_VIEW_WINDOW (data); + ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window); + gtk_widget_show (priv->find_toolbar); + hildon_find_toolbar_highlight_entry (HILDON_FIND_TOOLBAR (priv->find_toolbar), TRUE); } +/* Handler for click on the "X" close button in find toolbar */ static void modest_msg_view_window_find_toolbar_close (GtkWidget *widget, ModestMsgViewWindow *obj) { - GtkToggleAction *toggle; - ModestWindowPrivate *parent_priv; ModestMsgViewWindowPrivate *priv; priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (obj); - parent_priv = MODEST_WINDOW_GET_PRIVATE (obj); - toggle = GTK_TOGGLE_ACTION (gtk_ui_manager_get_action (parent_priv->ui_manager, "/ToolBar/FindInMessage")); - gtk_toggle_action_set_active (toggle, FALSE); + /* Hide toolbar */ + gtk_widget_hide (priv->find_toolbar); modest_msg_view_grab_focus (MODEST_MSG_VIEW (priv->msg_view)); } @@ -1599,7 +1770,6 @@ modest_msg_view_window_zoom_minus (ModestWindow *window) modest_zoomable_set_zoom (MODEST_ZOOMABLE (priv->msg_view), zoom_level); return TRUE; - } static gboolean @@ -1619,52 +1789,11 @@ modest_msg_view_window_key_event (GtkWidget *window, gtk_widget_event (focus, copy); gdk_event_free (copy); return TRUE; - } else - return FALSE; - } - if (event->keyval == GDK_Up || event->keyval == GDK_KP_Up || - event->keyval == GDK_Down || event->keyval == GDK_KP_Down || - event->keyval == GDK_Page_Up || event->keyval == GDK_KP_Page_Up || - event->keyval == GDK_Page_Down || event->keyval == GDK_KP_Page_Down || - event->keyval == GDK_Home || event->keyval == GDK_KP_Home || - event->keyval == GDK_End || event->keyval == GDK_KP_End) { - /* ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window); */ - /* gboolean return_value; */ - - if (event->type == GDK_KEY_PRESS) { - GtkScrollType scroll_type; - - switch (event->keyval) { - case GDK_Up: - case GDK_KP_Up: - scroll_type = GTK_SCROLL_STEP_UP; break; - case GDK_Down: - case GDK_KP_Down: - scroll_type = GTK_SCROLL_STEP_DOWN; break; - case GDK_Page_Up: - case GDK_KP_Page_Up: - scroll_type = GTK_SCROLL_PAGE_UP; break; - case GDK_Page_Down: - case GDK_KP_Page_Down: - scroll_type = GTK_SCROLL_PAGE_DOWN; break; - case GDK_Home: - case GDK_KP_Home: - scroll_type = GTK_SCROLL_START; break; - case GDK_End: - case GDK_KP_End: - scroll_type = GTK_SCROLL_END; break; - default: scroll_type = GTK_SCROLL_NONE; - } - - /* g_signal_emit_by_name (G_OBJECT (priv->main_scroll), "scroll-child", */ - /* scroll_type, FALSE, &return_value); */ - return FALSE; } else { return FALSE; } - } else { - return FALSE; } + return FALSE; } gboolean @@ -1791,6 +1920,8 @@ modest_msg_view_window_first_message_selected (ModestMsgViewWindow *window) typedef struct { TnyHeader *header; + gchar *msg_uid; + TnyFolder *folder; GtkTreeRowReference *row_reference; } MsgReaderInfo; @@ -1807,11 +1938,13 @@ message_reader_performer (gboolean canceled, info = (MsgReaderInfo *) user_data; if (canceled || err) { update_window_title (MODEST_MSG_VIEW_WINDOW (parent_window)); + modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (parent_window)); goto frees; } /* Register the header - it'll be unregistered in the callback */ - modest_window_mgr_register_header (modest_runtime_get_window_mgr (), info->header, NULL); + if (info->header) + modest_window_mgr_register_header (modest_runtime_get_window_mgr (), info->header, NULL); /* New mail operation */ mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window), @@ -1819,7 +1952,10 @@ message_reader_performer (gboolean canceled, NULL, NULL); modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op); - modest_mail_operation_get_msg (mail_op, info->header, TRUE, view_msg_cb, info->row_reference); + if (info->header) + modest_mail_operation_get_msg (mail_op, info->header, TRUE, view_msg_cb, info->row_reference); + else + modest_mail_operation_find_msg (mail_op, info->folder, info->msg_uid, TRUE, view_msg_cb, NULL); g_object_unref (mail_op); /* Update dimming rules */ @@ -1828,7 +1964,11 @@ message_reader_performer (gboolean canceled, frees: /* Frees. The row_reference will be freed by the view_msg_cb callback */ - g_object_unref (info->header); + g_free (info->msg_uid); + if (info->folder) + g_object_unref (info->folder); + if (info->header) + g_object_unref (info->header); g_slice_free (MsgReaderInfo, info); } @@ -1849,22 +1989,27 @@ static gboolean message_reader (ModestMsgViewWindow *window, ModestMsgViewWindowPrivate *priv, TnyHeader *header, + const gchar *msg_uid, + TnyFolder *folder, GtkTreeRowReference *row_reference) { ModestWindowMgr *mgr; - TnyAccount *account; - TnyFolder *folder; + TnyAccount *account = NULL; MsgReaderInfo *info; - g_return_val_if_fail (row_reference != NULL, FALSE); + /* We set the header from model while we're loading */ + tny_header_view_set_header (TNY_HEADER_VIEW (priv->msg_view), header); + gtk_window_set_title (GTK_WINDOW (window), _CS("ckdg_pb_updating")); + + if (header) + folder = NULL; + + if (folder) + g_object_ref (folder); mgr = modest_runtime_get_window_mgr (); /* Msg download completed */ - if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)) { - - /* We set the header from model while we're loading */ - tny_header_view_set_header (TNY_HEADER_VIEW (priv->msg_view), header); - gtk_window_set_title (GTK_WINDOW (window), _CS("ckdg_pb_updating")); + if (!header || !(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED)) { /* Ask the user if he wants to download the message if we're not online */ @@ -1878,10 +2023,24 @@ message_reader (ModestMsgViewWindow *window, return FALSE; } - folder = tny_header_get_folder (header); + if (header) { + folder = tny_header_get_folder (header); + } info = g_slice_new (MsgReaderInfo); - info->header = g_object_ref (header); - info->row_reference = gtk_tree_row_reference_copy (row_reference); + info->msg_uid = g_strdup (msg_uid); + if (header) + info->header = g_object_ref (header); + else + info->header = NULL; + if (folder) + info->folder = g_object_ref (folder); + else + info->folder = NULL; + if (row_reference) { + info->row_reference = gtk_tree_row_reference_copy (row_reference); + } else { + info->row_reference = NULL; + } /* Offer the connection dialog if necessary */ modest_platform_connect_if_remote_and_perform ((GtkWindow *) window, @@ -1889,25 +2048,43 @@ message_reader (ModestMsgViewWindow *window, TNY_FOLDER_STORE (folder), message_reader_performer, info); - g_object_unref (folder); + if (folder) + g_object_unref (folder); return TRUE; } } - - folder = tny_header_get_folder (header); - account = tny_folder_get_account (folder); + + if (header) { + folder = tny_header_get_folder (header); + } + if (folder) + account = tny_folder_get_account (folder); + info = g_slice_new (MsgReaderInfo); - info->header = g_object_ref (header); - info->row_reference = gtk_tree_row_reference_copy (row_reference); - + info->msg_uid = g_strdup (msg_uid); + if (folder) + info->folder = g_object_ref (folder); + else + info->folder = NULL; + if (header) + info->header = g_object_ref (header); + else + info->header = NULL; + if (row_reference) + info->row_reference = gtk_tree_row_reference_copy (row_reference); + else + info->row_reference = NULL; + message_reader_performer (FALSE, NULL, (GtkWindow *) window, account, info); - g_object_unref (account); - g_object_unref (folder); + if (account) + g_object_unref (account); + if (folder) + g_object_unref (folder); return TRUE; } -gboolean +gboolean modest_msg_view_window_select_next_message (ModestMsgViewWindow *window) { ModestMsgViewWindowPrivate *priv; @@ -1930,9 +2107,14 @@ modest_msg_view_window_select_next_message (ModestMsgViewWindow *window) tree models and reports the deletion when the row is still there */ if (!gtk_tree_row_reference_valid (priv->next_row_reference)) { + if (priv->next_row_reference) { + gtk_tree_row_reference_free (priv->next_row_reference); + } if (gtk_tree_row_reference_valid (priv->row_reference)) { priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference); select_next_valid_row (priv->header_model, &(priv->next_row_reference), FALSE, priv->is_outbox); + } else { + priv->next_row_reference = NULL; } } if (priv->next_row_reference) @@ -1952,7 +2134,7 @@ modest_msg_view_window_select_next_message (ModestMsgViewWindow *window) &header, -1); /* Read the message & show it */ - if (!message_reader (window, priv, header, row_reference)) { + if (!message_reader (window, priv, header, NULL, NULL, row_reference)) { retval = FALSE; } gtk_tree_row_reference_free (row_reference); @@ -1974,6 +2156,11 @@ modest_msg_view_window_select_previous_message (ModestMsgViewWindow *window) g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window), FALSE); priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window); + if (priv->row_reference && !gtk_tree_row_reference_valid (priv->row_reference)) { + gtk_tree_row_reference_free (priv->row_reference); + priv->row_reference = NULL; + } + /* Return inmediatly if there is no header model */ if (!priv->header_model || !priv->row_reference) return FALSE; @@ -1993,7 +2180,7 @@ modest_msg_view_window_select_previous_message (ModestMsgViewWindow *window) GtkTreeRowReference *row_reference; row_reference = gtk_tree_row_reference_new (priv->header_model, path); /* Read the message & show it */ - retval = message_reader (window, priv, header, row_reference); + retval = message_reader (window, priv, header, NULL, NULL, row_reference); gtk_tree_row_reference_free (row_reference); } else { finished = FALSE; @@ -2022,12 +2209,14 @@ view_msg_cb (ModestMailOperation *mail_op, modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (), header); row_reference = (GtkTreeRowReference *) user_data; - if (canceled) { - gtk_tree_row_reference_free (row_reference); - self = (ModestMsgViewWindow *) modest_mail_operation_get_source (mail_op); + self = (ModestMsgViewWindow *) modest_mail_operation_get_source (mail_op); + if (canceled || !self || MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self)->msg_view == NULL ) { + if (row_reference) + gtk_tree_row_reference_free (row_reference); if (self) { /* Restore window title */ update_window_title (self); + modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (self)); g_object_unref (self); } return; @@ -2035,41 +2224,105 @@ view_msg_cb (ModestMailOperation *mail_op, /* If there was any error */ if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) { - gtk_tree_row_reference_free (row_reference); - self = (ModestMsgViewWindow *) modest_mail_operation_get_source (mail_op); + if (row_reference) + gtk_tree_row_reference_free (row_reference); if (self) { + priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self); + /* First we check if the parent is a folder window */ + if (priv->msg_uid && !modest_hildon2_window_mgr_get_folder_window (MODEST_HILDON2_WINDOW_MGR (modest_runtime_get_window_mgr ()))) { + gboolean is_merge; + TnyAccount *account = NULL; + GtkWidget *header_window = NULL; + + is_merge = g_str_has_prefix (priv->msg_uid, "merge:"); + + /* Get the account */ + if (!is_merge) + account = tny_account_store_find_account (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()), + priv->msg_uid); + + if (is_merge || account) { + TnyFolder *folder = NULL; + + /* Try to get the message, if it's already downloaded + we don't need to connect */ + if (account) { + folder = modest_tny_folder_store_find_folder_from_uri (TNY_FOLDER_STORE (account), + priv->msg_uid); + } else { + ModestTnyAccountStore *account_store; + ModestTnyLocalFoldersAccount *local_folders_account; + + account_store = modest_runtime_get_account_store (); + local_folders_account = MODEST_TNY_LOCAL_FOLDERS_ACCOUNT ( + modest_tny_account_store_get_local_folders_account (account_store)); + folder = modest_tny_local_folders_account_get_merged_outbox (local_folders_account); + g_object_unref (local_folders_account); + } + if (account) g_object_unref (account); + + if (folder) { + header_window = (GtkWidget *) + modest_header_window_new ( + folder, + modest_window_get_active_account (MODEST_WINDOW (self)), + modest_window_get_active_mailbox (MODEST_WINDOW (self))); + if (!modest_window_mgr_register_window (modest_runtime_get_window_mgr (), + MODEST_WINDOW (header_window), + NULL)) { + gtk_widget_destroy (GTK_WIDGET (header_window)); + } else { + gtk_widget_show_all (GTK_WIDGET (header_window)); + } + g_object_unref (folder); + } + } + } + + /* Restore window title */ update_window_title (self); + modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (self)); g_object_unref (self); } return; } /* Get the window */ - self = (ModestMsgViewWindow *) modest_mail_operation_get_source (mail_op); g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self)); priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self); /* Update the row reference */ if (priv->row_reference != NULL) { gtk_tree_row_reference_free (priv->row_reference); - priv->row_reference = gtk_tree_row_reference_copy (row_reference); + priv->row_reference = (row_reference && gtk_tree_row_reference_valid (row_reference))?gtk_tree_row_reference_copy (row_reference):NULL; if (priv->next_row_reference != NULL) { gtk_tree_row_reference_free (priv->next_row_reference); } - priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference); - select_next_valid_row (priv->header_model, &(priv->next_row_reference), TRUE, priv->is_outbox); + if (priv->row_reference) { + priv->next_row_reference = gtk_tree_row_reference_copy (priv->row_reference); + select_next_valid_row (priv->header_model, &(priv->next_row_reference), TRUE, priv->is_outbox); + } else { + priv->next_row_reference = NULL; + } } /* Mark header as read */ - if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_SEEN)) + if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_SEEN)) { + gchar *uid; + tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN); + uid = modest_tny_folder_get_header_unique_id (header); + modest_platform_emit_msg_read_changed_signal (uid, TRUE); + g_free (uid); + } /* Set new message */ if (priv->msg_view != NULL && TNY_IS_MSG_VIEW (priv->msg_view)) { tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), msg); modest_msg_view_window_update_priority (self); update_window_title (MODEST_MSG_VIEW_WINDOW (self)); + update_branding (MODEST_MSG_VIEW_WINDOW (self)); modest_msg_view_grab_focus (MODEST_MSG_VIEW (priv->msg_view)); } @@ -2080,12 +2333,18 @@ view_msg_cb (ModestMailOperation *mail_op, } /* Notify the observers */ - g_signal_emit (G_OBJECT (self), signals[MSG_CHANGED_SIGNAL], + g_signal_emit (G_OBJECT (self), signals[MSG_CHANGED_SIGNAL], 0, priv->header_model, priv->row_reference); + /* Sync the flags if the message is not opened from a header + model, i.e, if it's opened from a notification */ + if (!priv->header_model) + sync_flags (self); + /* Frees */ g_object_unref (self); - gtk_tree_row_reference_free (row_reference); + if (row_reference) + gtk_tree_row_reference_free (row_reference); } TnyFolderType @@ -2124,7 +2383,7 @@ modest_msg_view_window_update_priority (ModestMsgViewWindow *window) priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window); - if (priv->header_model && priv->row_reference) { + if (priv->header_model && priv->row_reference && gtk_tree_row_reference_valid (priv->row_reference)) { GtkTreeIter iter; GtkTreePath *path = NULL; @@ -2172,24 +2431,22 @@ toolbar_resize (ModestMsgViewWindow *self) static_button_size = modest_window_mgr_get_fullscreen_mode (mgr)?120:120; if (parent_priv->toolbar) { - /* left size buttons */ + /* Set expandable and homogeneous tool buttons */ widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReply"); - gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE); - gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE); - gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1); - widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageMoveTo"); - gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE); - gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE); - gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1); + gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE); + gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE); + widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageReplyAll"); + gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE); + gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE); + widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarMessageForward"); + gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE); + gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE); widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDeleteMessage"); - gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE); - gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE); - gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1); - widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/FindInMessage"); - gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), FALSE); - gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), FALSE); - gtk_widget_set_size_request (GTK_WIDGET (widget), static_button_size, -1); - + gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE); + gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE); + widget = gtk_ui_manager_get_widget (parent_priv->ui_manager, "/ToolBar/ToolbarDownloadExternalImages"); + gtk_tool_item_set_expand (GTK_TOOL_ITEM (widget), TRUE); + gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (widget), TRUE); gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->next_toolitem), TRUE); gtk_tool_item_set_expand (GTK_TOOL_ITEM (priv->next_toolitem), TRUE); gtk_tool_item_set_homogeneous (GTK_TOOL_ITEM (priv->prev_toolitem), TRUE); @@ -2323,8 +2580,10 @@ on_mail_operation_started (ModestMailOperation *mail_op, tmp = priv->progress_widgets; source = modest_mail_operation_get_source(mail_op); if (G_OBJECT (self) == source) { - if (op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) { - set_toolbar_transfer_mode(self); + if (op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE || + op_type == MODEST_MAIL_OPERATION_TYPE_OPEN || + op_type == MODEST_MAIL_OPERATION_TYPE_DELETE) { + set_progress_hint (self, TRUE); while (tmp) { modest_progress_object_add_operation ( MODEST_PROGRESS_OBJECT (tmp->data), @@ -2334,9 +2593,12 @@ on_mail_operation_started (ModestMailOperation *mail_op, } } g_object_unref (source); + + /* Update dimming rules */ + check_dimming_rules_after_change (self); } -static void +static void on_mail_operation_finished (ModestMailOperation *mail_op, gpointer user_data) { @@ -2344,13 +2606,15 @@ on_mail_operation_finished (ModestMailOperation *mail_op, ModestMailOperationTypeOperation op_type; GSList *tmp; ModestMsgViewWindowPrivate *priv; - + self = MODEST_MSG_VIEW_WINDOW (user_data); priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self); op_type = modest_mail_operation_get_type_operation (mail_op); tmp = priv->progress_widgets; - - if (op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE) { + + if (op_type == MODEST_MAIL_OPERATION_TYPE_RECEIVE || + op_type == MODEST_MAIL_OPERATION_TYPE_OPEN || + op_type == MODEST_MAIL_OPERATION_TYPE_DELETE) { while (tmp) { modest_progress_object_remove_operation (MODEST_PROGRESS_OBJECT (tmp->data), mail_op); @@ -2369,7 +2633,6 @@ on_mail_operation_finished (ModestMailOperation *mail_op, won't let the user delete the message that has been readed for example */ check_dimming_rules_after_change (self); - } static void @@ -2422,6 +2685,12 @@ modest_msg_view_window_get_attachments (ModestMsgViewWindow *win) return selected_attachments; } +typedef struct { + ModestMsgViewWindow *self; + gchar *file_path; + gchar *attachment_uid; +} DecodeAsyncHelper; + static void on_decode_to_stream_async_handler (TnyMimePart *mime_part, gboolean cancelled, @@ -2429,25 +2698,115 @@ on_decode_to_stream_async_handler (TnyMimePart *mime_part, GError *err, gpointer user_data) { - gchar *filepath = (gchar *) user_data; + DecodeAsyncHelper *helper = (DecodeAsyncHelper *) user_data; + const gchar *content_type; + ModestMsgViewWindowPrivate *priv; + + priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (helper->self); if (cancelled || err) { if (err) { - modest_platform_information_banner (NULL, NULL, - _KR("cerm_device_memory_full")); + gchar *msg; + if ((err->domain == TNY_ERROR_DOMAIN) && + (err->code == TNY_IO_ERROR_WRITE) && + (errno == ENOSPC)) { + msg = g_strdup_printf (_KR("cerm_device_memory_full"), ""); + } else { + msg = g_strdup (_("mail_ib_file_operation_failed")); + } + modest_platform_information_banner (NULL, NULL, msg); + g_free (msg); } goto free; } - /* make the file read-only */ - g_chmod(filepath, 0444); + /* It could happen that the window was closed. So we + assume it is a cancelation */ + if (!GTK_WIDGET_VISIBLE (helper->self)) + goto free; - /* Activate the file */ - modest_platform_activate_file (filepath, tny_mime_part_get_content_type (mime_part)); + /* Remove the progress hint */ + set_progress_hint (helper->self, FALSE); + + content_type = tny_mime_part_get_content_type (mime_part); + if (content_type && g_str_has_prefix (content_type, "message/rfc822")) { + ModestWindowMgr *mgr; + ModestWindow *msg_win = NULL; + TnyMsg * msg; + gchar *account; + const gchar *mailbox; + TnyStream *file_stream; + gint fd; + + fd = g_open (helper->file_path, O_RDONLY, 0644); + if (fd != -1) { + TnyMsg *top_msg; + file_stream = tny_fs_stream_new (fd); + + mgr = modest_runtime_get_window_mgr (); + + account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (helper->self))); + mailbox = modest_window_get_active_mailbox (MODEST_WINDOW (helper->self)); + + if (!account) + account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr ()); + + msg = tny_camel_msg_new (); + tny_camel_msg_parse (msg, file_stream); + + if (priv->top_msg) + top_msg = g_object_ref (priv->top_msg); + else + top_msg = tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view)); + + msg_win = modest_msg_view_window_new_for_attachment (TNY_MSG (msg), top_msg, + account, mailbox, helper->attachment_uid); + if (top_msg) g_object_unref (top_msg); + modest_window_set_zoom (MODEST_WINDOW (msg_win), + modest_window_get_zoom (MODEST_WINDOW (helper->self))); + if (modest_window_mgr_register_window (mgr, msg_win, MODEST_WINDOW (helper->self))) + gtk_widget_show_all (GTK_WIDGET (msg_win)); + else + gtk_widget_destroy (GTK_WIDGET (msg_win)); + g_object_unref (msg); + g_object_unref (file_stream); + } else { + modest_platform_information_banner (NULL, NULL, _("mail_ib_file_operation_failed")); + } + + } else { + + /* make the file read-only */ + g_chmod(helper->file_path, 0444); + + /* Activate the file */ + modest_platform_activate_file (helper->file_path, content_type); + } free: /* Frees */ - g_free (filepath); + g_object_unref (helper->self); + g_free (helper->file_path); + g_free (helper->attachment_uid); + g_slice_free (DecodeAsyncHelper, helper); +} + +static void +view_attachment_connect_handler (gboolean canceled, + GError *err, + GtkWindow *parent_window, + TnyAccount *account, + TnyMimePart *part) +{ + + if (canceled || err) { + g_object_unref (part); + return; + } + + modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (parent_window), + part); + g_object_unref (part); } void @@ -2468,7 +2827,7 @@ modest_msg_view_window_view_attachment (ModestMsgViewWindow *window, attachments = modest_msg_view_get_attachments (MODEST_MSG_VIEW (priv->msg_view)); attachment_index = modest_list_index (attachments, (GObject *) mime_part); g_object_unref (attachments); - + if (msg_uid && attachment_index >= 0) { attachment_uid = g_strdup_printf ("%s/%d", msg_uid, attachment_index); } @@ -2499,7 +2858,29 @@ modest_msg_view_window_view_attachment (ModestMsgViewWindow *window, if (tny_mime_part_is_purged (mime_part)) goto frees; - if (!modest_tny_mime_part_is_msg (mime_part)) { + if (TNY_IS_CAMEL_BS_MIME_PART (mime_part) && + !tny_camel_bs_mime_part_is_fetched (TNY_CAMEL_BS_MIME_PART (mime_part))) { + gboolean is_merge; + TnyAccount *account; + + is_merge = g_str_has_prefix (priv->msg_uid, "merge:"); + account = NULL; + /* Get the account */ + if (!is_merge) + account = tny_account_store_find_account (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()), + priv->msg_uid); + + if (!tny_device_is_online (modest_runtime_get_device())) { + modest_platform_connect_and_perform (GTK_WINDOW (window), + TRUE, + TNY_ACCOUNT (account), + (ModestConnectedPerformer) view_attachment_connect_handler, + g_object_ref (mime_part)); + goto frees; + } + } + + if (!modest_tny_mime_part_is_msg (mime_part) && tny_mime_part_get_filename (mime_part)) { gchar *filepath = NULL; const gchar *att_filename = tny_mime_part_get_filename (mime_part); gboolean show_error_banner = FALSE; @@ -2508,10 +2889,45 @@ modest_msg_view_window_view_attachment (ModestMsgViewWindow *window, &filepath); if (temp_stream != NULL) { - tny_mime_part_decode_to_stream_async (mime_part, TNY_STREAM (temp_stream), - on_decode_to_stream_async_handler, - NULL, - g_strdup (filepath)); + ModestAccountMgr *mgr; + DecodeAsyncHelper *helper; + gboolean decode_in_provider; + ModestProtocol *protocol; + const gchar *account; + + /* Activate progress hint */ + set_progress_hint (window, TRUE); + + helper = g_slice_new0 (DecodeAsyncHelper); + helper->self = g_object_ref (window); + helper->file_path = g_strdup (filepath); + helper->attachment_uid = g_strdup (attachment_uid); + + decode_in_provider = FALSE; + mgr = modest_runtime_get_account_mgr (); + account = modest_window_get_active_account (MODEST_WINDOW (window)); + if (modest_account_mgr_account_is_multimailbox (mgr, account, &protocol)) { + if (MODEST_IS_ACCOUNT_PROTOCOL (protocol)) { + gchar *uri; + uri = g_strconcat ("file://", filepath, NULL); + decode_in_provider = + modest_account_protocol_decode_part_to_stream_async ( + MODEST_ACCOUNT_PROTOCOL (protocol), + mime_part, + filepath, + TNY_STREAM (temp_stream), + on_decode_to_stream_async_handler, + NULL, + helper); + g_free (uri); + } + } + + if (!decode_in_provider) + tny_mime_part_decode_to_stream_async (mime_part, TNY_STREAM (temp_stream), + on_decode_to_stream_async_handler, + NULL, + helper); g_object_unref (temp_stream); /* NOTE: files in the temporary area will be automatically * cleaned after some time if they are no longer in use */ @@ -2531,6 +2947,50 @@ modest_msg_view_window_view_attachment (ModestMsgViewWindow *window, g_free (filepath); if (show_error_banner) modest_platform_information_banner (NULL, NULL, _("mail_ib_file_operation_failed")); + } else if (!modest_tny_mime_part_is_msg (mime_part)) { + ModestWindowMgr *mgr; + ModestWindow *msg_win = NULL; + TnyMsg *current_msg; + gboolean found; + TnyHeader *header; + + current_msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (window)); + mgr = modest_runtime_get_window_mgr (); + header = tny_msg_get_header (TNY_MSG (current_msg)); + found = modest_window_mgr_find_registered_message_uid (mgr, + attachment_uid, + &msg_win); + + if (found) { + g_debug ("window for this body is already being created"); + } else { + TnyMsg *top_msg; + + /* it's not found, so create a new window for it */ + modest_window_mgr_register_header (mgr, header, attachment_uid); /* register the uid before building the window */ + gchar *account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (window))); + const gchar *mailbox = modest_window_get_active_mailbox (MODEST_WINDOW (window)); + if (!account) + account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr ()); + + if (priv->top_msg) + top_msg = g_object_ref (priv->top_msg); + else + top_msg = tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view)); + + msg_win = modest_msg_view_window_new_with_other_body (TNY_MSG (current_msg), TNY_MIME_PART (mime_part), top_msg, + account, mailbox, attachment_uid); + + if (top_msg) g_object_unref (top_msg); + + modest_window_set_zoom (MODEST_WINDOW (msg_win), + modest_window_get_zoom (MODEST_WINDOW (window))); + if (modest_window_mgr_register_window (mgr, msg_win, MODEST_WINDOW (window))) + gtk_widget_show_all (GTK_WIDGET (msg_win)); + else + gtk_widget_destroy (GTK_WIDGET (msg_win)); + } + g_object_unref (current_msg); } else { /* message attachment */ TnyHeader *header = NULL; @@ -2545,20 +3005,28 @@ modest_msg_view_window_view_attachment (ModestMsgViewWindow *window, if (found) { /* if it's found, but there is no msg_win, it's probably in the process of being created; * thus, we don't do anything */ - g_warning ("window for is already being created"); + g_debug ("window for is already being created"); } else { + TnyMsg *top_msg; /* it's not found, so create a new window for it */ modest_window_mgr_register_header (mgr, header, attachment_uid); /* register the uid before building the window */ gchar *account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (window))); const gchar *mailbox = modest_window_get_active_mailbox (MODEST_WINDOW (window)); if (!account) account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr ()); - msg_win = modest_msg_view_window_new_for_attachment (TNY_MSG (mime_part), account, - mailbox, attachment_uid); + if (priv->top_msg) + top_msg = g_object_ref (priv->top_msg); + else + top_msg = tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view)); + msg_win = modest_msg_view_window_new_for_attachment ( + TNY_MSG (mime_part), top_msg, account, + mailbox, attachment_uid); modest_window_set_zoom (MODEST_WINDOW (msg_win), modest_window_get_zoom (MODEST_WINDOW (window))); - modest_window_mgr_register_window (mgr, msg_win, MODEST_WINDOW (window)); - gtk_widget_show_all (GTK_WIDGET (msg_win)); + if (modest_window_mgr_register_window (mgr, msg_win, MODEST_WINDOW (window))) + gtk_widget_show_all (GTK_WIDGET (msg_win)); + else + gtk_widget_destroy (GTK_WIDGET (msg_win)); } } @@ -2579,18 +3047,20 @@ typedef struct { GList *pairs; GnomeVFSResult result; + gchar *uri; + ModestMsgViewWindow *window; } SaveMimePartInfo; static void save_mime_part_info_free (SaveMimePartInfo *info, gboolean with_struct); static gboolean idle_save_mime_part_show_result (SaveMimePartInfo *info); static gpointer save_mime_part_to_file (SaveMimePartInfo *info); -static void save_mime_parts_to_file_with_checks (SaveMimePartInfo *info); +static void save_mime_parts_to_file_with_checks (GtkWindow *parent, SaveMimePartInfo *info); -static void +static void save_mime_part_info_free (SaveMimePartInfo *info, gboolean with_struct) { - GList *node; + for (node = info->pairs; node != NULL; node = g_list_next (node)) { SaveMimePartPair *pair = (SaveMimePartPair *) node->data; g_free (pair->filename); @@ -2599,6 +3069,9 @@ save_mime_part_info_free (SaveMimePartInfo *info, gboolean with_struct) } g_list_free (info->pairs); info->pairs = NULL; + g_free (info->uri); + g_object_unref (info->window); + info->window = NULL; if (with_struct) { g_slice_free (SaveMimePartInfo, info); } @@ -2607,24 +3080,76 @@ save_mime_part_info_free (SaveMimePartInfo *info, gboolean with_struct) static gboolean idle_save_mime_part_show_result (SaveMimePartInfo *info) { - if (info->pairs != NULL) { - save_mime_part_to_file (info); + /* This is a GDK lock because we are an idle callback and + * hildon_banner_show_information is or does Gtk+ code */ + + gdk_threads_enter (); /* CHECKED */ + if (info->result == GNOME_VFS_ERROR_CANCELLED) { + /* nothing */ + } else if (info->result == GNOME_VFS_OK) { + hildon_banner_show_information (NULL, NULL, _CS("sfil_ib_saved")); + } else if (info->result == GNOME_VFS_ERROR_NO_SPACE) { + gchar *msg = NULL; + + /* Check if the uri belongs to the external mmc */ + if (g_str_has_prefix (info->uri, g_getenv (MODEST_MMC1_VOLUMEPATH_ENV))) + msg = g_strdup_printf (_KR("cerm_device_memory_full"), ""); + else + msg = g_strdup (_KR("cerm_memory_card_full")); + modest_platform_information_banner (NULL, NULL, msg); + g_free (msg); } else { - /* This is a GDK lock because we are an idle callback and - * hildon_banner_show_information is or does Gtk+ code */ + hildon_banner_show_information (NULL, NULL, _("mail_ib_file_operation_failed")); + } + set_progress_hint (info->window, FALSE); + save_mime_part_info_free (info, FALSE); + gdk_threads_leave (); /* CHECKED */ - gdk_threads_enter (); /* CHECKED */ - save_mime_part_info_free (info, TRUE); - if (info->result == GNOME_VFS_OK) { - hildon_banner_show_information (NULL, NULL, _CS("sfil_ib_saved")); - } else if (info->result == GNOME_VFS_ERROR_NO_SPACE) { - hildon_banner_show_information (NULL, NULL, - _KR("cerm_device_memory_full")); - } else { - hildon_banner_show_information (NULL, NULL, _("mail_ib_file_operation_failed")); + return FALSE; +} + +static void +save_mime_part_to_file_connect_handler (gboolean canceled, + GError *err, + GtkWindow *parent_window, + TnyAccount *account, + SaveMimePartInfo *info) +{ + if (canceled || err) { + if (canceled && !err) { + info->result = GNOME_VFS_ERROR_CANCELLED; } - gdk_threads_leave (); /* CHECKED */ + g_idle_add ((GSourceFunc) idle_save_mime_part_show_result, info); + } else { + g_thread_create ((GThreadFunc)save_mime_part_to_file, info, FALSE, NULL); } +} + +static gboolean +save_mime_part_to_file_connect_idle (SaveMimePartInfo *info) +{ + gboolean is_merge; + TnyAccount *account; + ModestMsgViewWindowPrivate *priv; + + priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (info->window); + + is_merge = g_str_has_prefix (priv->msg_uid, "merge:"); + account = NULL; + + /* Get the account */ + if (!is_merge) + account = tny_account_store_find_account (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()), + priv->msg_uid); + + modest_platform_connect_and_perform (GTK_WINDOW (info->window), + TRUE, + TNY_ACCOUNT (account), + (ModestConnectedPerformer) save_mime_part_to_file_connect_handler, + info); + + if (account) + g_object_unref (account); return FALSE; } @@ -2636,14 +3161,71 @@ save_mime_part_to_file (SaveMimePartInfo *info) TnyStream *stream; SaveMimePartPair *pair = (SaveMimePartPair *) info->pairs->data; + if (TNY_IS_CAMEL_BS_MIME_PART (pair->part) && + !tny_camel_bs_mime_part_is_fetched (TNY_CAMEL_BS_MIME_PART (pair->part))) { + gboolean check_online = TRUE; + ModestMsgViewWindowPrivate *priv = NULL; + + /* Check if we really need to connect to save the mime part */ + priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (info->window); + if (g_str_has_prefix (priv->msg_uid, "merge:")) { + check_online = FALSE; + } else { + TnyAccountStore *acc_store; + TnyAccount *account = NULL; + + acc_store = (TnyAccountStore*) modest_runtime_get_account_store (); + account = tny_account_store_find_account (acc_store, priv->msg_uid); + + if (account) { + if (tny_account_get_connection_status (account) == + TNY_CONNECTION_STATUS_CONNECTED) + check_online = FALSE; + g_object_unref (account); + } else { + check_online = !tny_device_is_online (tny_account_store_get_device (acc_store)); + } + } + + if (check_online) { + g_idle_add ((GSourceFunc) save_mime_part_to_file_connect_idle, info); + return NULL; + } + } + info->result = gnome_vfs_create (&handle, pair->filename, GNOME_VFS_OPEN_WRITE, FALSE, 0644); if (info->result == GNOME_VFS_OK) { GError *error = NULL; + gboolean decode_in_provider; + gssize written; + ModestAccountMgr *mgr; + const gchar *account; + ModestProtocol *protocol = NULL; + stream = tny_vfs_stream_new (handle); - if (tny_mime_part_decode_to_stream (pair->part, stream, &error) < 0) { + + decode_in_provider = FALSE; + mgr = modest_runtime_get_account_mgr (); + account = modest_window_get_active_account (MODEST_WINDOW (info->window)); + if (modest_account_mgr_account_is_multimailbox (mgr, account, &protocol)) { + if (MODEST_IS_ACCOUNT_PROTOCOL (protocol)) { + decode_in_provider = + modest_account_protocol_decode_part_to_stream ( + MODEST_ACCOUNT_PROTOCOL (protocol), + pair->part, + pair->filename, + stream, + &written, + &error); + } + } + if (!decode_in_provider) + written = tny_mime_part_decode_to_stream (pair->part, stream, &error); + + if (written < 0) { g_warning ("modest: could not save attachment %s: %d (%s)\n", pair->filename, error?error->code:-1, error?error->message:"Unknown error"); - if ((error->domain == TNY_ERROR_DOMAIN) && + if (error && (error->domain == TNY_ERROR_DOMAIN) && (error->code == TNY_IO_ERROR_WRITE) && (errno == ENOSPC)) { info->result = GNOME_VFS_ERROR_NO_SPACE; @@ -2652,51 +3234,80 @@ save_mime_part_to_file (SaveMimePartInfo *info) } } g_object_unref (G_OBJECT (stream)); - g_object_unref (pair->part); - g_slice_free (SaveMimePartPair, pair); - info->pairs = g_list_delete_link (info->pairs, info->pairs); } else { - g_warning ("modest: could not create save attachment %s: %s\n", pair->filename, gnome_vfs_result_to_string (info->result)); - save_mime_part_info_free (info, FALSE); + g_warning ("Could not create save attachment %s: %s\n", + pair->filename, gnome_vfs_result_to_string (info->result)); + } + + /* Go on saving remaining files */ + info->pairs = g_list_remove_link (info->pairs, info->pairs); + if (info->pairs != NULL) { + save_mime_part_to_file (info); + } else { + g_idle_add ((GSourceFunc) idle_save_mime_part_show_result, info); } - g_idle_add ((GSourceFunc) idle_save_mime_part_show_result, info); return NULL; } static void -save_mime_parts_to_file_with_checks (SaveMimePartInfo *info) +save_mime_parts_to_file_with_checks (GtkWindow *parent, + SaveMimePartInfo *info) { gboolean is_ok = TRUE; gint replaced_files = 0; const GList *files = info->pairs; - const GList *iter; + const GList *iter, *to_replace = NULL; for (iter = files; (iter != NULL) && (replaced_files < 2); iter = g_list_next(iter)) { SaveMimePartPair *pair = iter->data; - if (modest_utils_file_exists (pair->filename)) { + gchar *unescaped = g_uri_unescape_string (pair->filename, NULL); + + if (modest_utils_file_exists (unescaped)) { replaced_files++; + if (replaced_files == 1) + to_replace = iter; } + g_free (unescaped); } if (replaced_files) { - GtkWidget *confirm_overwrite_dialog; - const gchar *message = (replaced_files == 1) ? - _FM("docm_nc_replace_file") : _FM("docm_nc_replace_multiple"); - confirm_overwrite_dialog = hildon_note_new_confirmation (NULL, message); - if (gtk_dialog_run (GTK_DIALOG (confirm_overwrite_dialog)) != GTK_RESPONSE_OK) { - is_ok = FALSE; + gint response; + + if (replaced_files == 1) { + SaveMimePartPair *pair = to_replace->data; + const gchar *basename = strrchr (pair->filename, G_DIR_SEPARATOR) + 1; + gchar *escaped_basename, *message; + + escaped_basename = g_uri_unescape_string (basename, NULL); + message = g_strdup_printf ("%s\n%s", + _FM("docm_nc_replace_file"), + (escaped_basename) ? escaped_basename : ""); + response = modest_platform_run_confirmation_dialog (parent, message); + g_free (message); + g_free (escaped_basename); + } else { + response = modest_platform_run_confirmation_dialog (parent, + _FM("docm_nc_replace_multiple")); } - gtk_widget_destroy (confirm_overwrite_dialog); + if (response != GTK_RESPONSE_OK) + is_ok = FALSE; } if (!is_ok) { save_mime_part_info_free (info, TRUE); } else { + /* Start progress and launch thread */ + set_progress_hint (info->window, TRUE); g_thread_create ((GThreadFunc)save_mime_part_to_file, info, FALSE, NULL); } } +typedef struct _SaveAttachmentsInfo { + TnyList *attachments_list; + ModestMsgViewWindow *window; +} SaveAttachmentsInfo; + static void save_attachments_response (GtkDialog *dialog, gint arg1, @@ -2706,17 +3317,18 @@ save_attachments_response (GtkDialog *dialog, gchar *chooser_uri; GList *files_to_save = NULL; gchar *current_folder; + SaveAttachmentsInfo *sa_info = (SaveAttachmentsInfo *) user_data; - mime_parts = TNY_LIST (user_data); + mime_parts = TNY_LIST (sa_info->attachments_list); if (arg1 != GTK_RESPONSE_OK) goto end; chooser_uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog)); current_folder = gtk_file_chooser_get_current_folder_uri (GTK_FILE_CHOOSER (dialog)); - if (current_folder && current_folder != '\0') { + if (current_folder && *current_folder != '\0') { GError *err = NULL; - modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_SAVE_ATTACHMENT_PATH, + modest_conf_set_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_SAVE_ATTACHMENT_PATH, current_folder,&err); if (err != NULL) { g_debug ("Error storing latest used folder: %s", err->message); @@ -2726,8 +3338,18 @@ save_attachments_response (GtkDialog *dialog, g_free (current_folder); if (!modest_utils_folder_writable (chooser_uri)) { - hildon_banner_show_information - (NULL, NULL, _FM("sfil_ib_readonly_location")); + const gchar *err_msg; + +#ifdef MODEST_PLATFORM_MAEMO + if (modest_maemo_utils_in_usb_mode ()) { + err_msg = dgettext ("hildon-status-bar-usb", "usbh_ib_mmc_usb_connected"); + } else { + err_msg = _FM("sfil_ib_readonly_location"); + } +#else + err_msg = _FM("sfil_ib_readonly_location"); +#endif + hildon_banner_show_information (NULL, NULL, err_msg); } else { TnyIterator *iter; @@ -2757,21 +3379,47 @@ save_attachments_response (GtkDialog *dialog, } g_object_unref (iter); } - g_free (chooser_uri); if (files_to_save != NULL) { SaveMimePartInfo *info = g_slice_new0 (SaveMimePartInfo); info->pairs = files_to_save; info->result = TRUE; - save_mime_parts_to_file_with_checks (info); + info->uri = g_strdup (chooser_uri); + info->window = g_object_ref (sa_info->window); + save_mime_parts_to_file_with_checks ((GtkWindow *) dialog, info); } + g_free (chooser_uri); end: /* Free and close the dialog */ g_object_unref (mime_parts); + g_object_unref (sa_info->window); + g_slice_free (SaveAttachmentsInfo, sa_info); gtk_widget_destroy (GTK_WIDGET (dialog)); } +static gboolean +msg_is_attachment (TnyList *mime_parts) +{ + TnyIterator *iter; + gboolean retval = FALSE; + + if (tny_list_get_length (mime_parts) > 1) + return FALSE; + + iter = tny_list_create_iterator (mime_parts); + if (iter) { + TnyMimePart *part = TNY_MIME_PART (tny_iterator_get_current (iter)); + if (part) { + if (TNY_IS_MSG (part)) + retval = TRUE; + g_object_unref (part); + } + g_object_unref (iter); + } + return retval; +} + void modest_msg_view_window_save_attachments (ModestMsgViewWindow *window, TnyList *mime_parts) @@ -2781,15 +3429,37 @@ modest_msg_view_window_save_attachments (ModestMsgViewWindow *window, gchar *conf_folder = NULL; gchar *filename = NULL; gchar *save_multiple_str = NULL; + const gchar *root_folder = "file:///"; g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window)); priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (window); if (mime_parts == NULL) { + gboolean allow_msgs = FALSE; + /* In Hildon 2.2 save and delete operate over all the attachments as there's no * selection available */ mime_parts = modest_msg_view_get_attachments (MODEST_MSG_VIEW (priv->msg_view)); - if (mime_parts && !modest_maemo_utils_select_attachments (GTK_WINDOW (window), mime_parts, FALSE)) { + + /* Check if the message is composed by an unique MIME + part whose content disposition is attachment. There + could be messages like this: + + Date: Tue, 12 Jan 2010 20:40:59 +0000 + From: + To: + Subject: no body + Content-Type: image/jpeg + Content-Disposition: attachment; filename="bug7718.jpeg" + + whose unique MIME part is the message itself whose + content disposition is attachment + */ + if (mime_parts && msg_is_attachment (mime_parts)) + allow_msgs = TRUE; + + if (mime_parts && + !modest_maemo_utils_select_attachments (GTK_WINDOW (window), mime_parts, allow_msgs)) { g_object_unref (mime_parts); return; } @@ -2817,27 +3487,42 @@ modest_msg_view_window_save_attachments (ModestMsgViewWindow *window, filename = g_strdup (tny_mime_part_get_filename (mime_part)); } else { /* TODO: show any error? */ - g_warning ("Tried to save a non-file attachment"); + g_warning ("%s: Tried to save a non-file attachment", __FUNCTION__); g_object_unref (mime_parts); return; } g_object_unref (mime_part); } else { - save_multiple_str = g_strdup_printf (_FM("sfil_va_number_of_objects_attachments"), - tny_list_get_length (mime_parts)); + gint num = tny_list_get_length (mime_parts); + save_multiple_str = g_strdup_printf (dngettext("hildon-fm", + "sfil_va_number_of_objects_attachment", + "sfil_va_number_of_objects_attachments", + num), num); } save_dialog = hildon_file_chooser_dialog_new (GTK_WINDOW (window), GTK_FILE_CHOOSER_ACTION_SAVE); - /* set folder */ - conf_folder = modest_conf_get_string (modest_runtime_get_conf (), MODEST_CONF_LATEST_SAVE_ATTACHMENT_PATH, NULL); + /* Get last used folder */ + conf_folder = modest_conf_get_string (modest_runtime_get_conf (), + MODEST_CONF_LATEST_SAVE_ATTACHMENT_PATH, NULL); + + /* File chooser stops working if we select "file:///" as current folder */ + if (conf_folder && g_ascii_strcasecmp (root_folder, conf_folder) != 0) { + g_free (conf_folder); + conf_folder = NULL; + } + if (conf_folder && conf_folder[0] != '\0') { gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (save_dialog), conf_folder); } else { gchar *docs_folder; - /* Set the default folder to images folder */ - docs_folder = g_build_filename (g_getenv (MYDOCS_ENV), DOCS_FOLDER, NULL); + /* Set the default folder to documents folder */ + docs_folder = (gchar *) g_strdup(g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS)); + if (!docs_folder) { + /* fallback */ + docs_folder = g_build_filename (g_getenv (MYDOCS_ENV), DOCS_FOLDER, NULL); + } gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (save_dialog), docs_folder); g_free (docs_folder); } @@ -2854,13 +3539,18 @@ modest_msg_view_window_save_attachments (ModestMsgViewWindow *window, if (save_multiple_str) { g_object_set (G_OBJECT (save_dialog), "save-multiple", save_multiple_str, NULL); gtk_window_set_title (GTK_WINDOW (save_dialog), _FM("sfil_ti_save_objects_files")); + g_free (save_multiple_str); } /* We must run this asynchronously, because the hildon dialog performs a gtk_dialog_run by itself which leads to gdk deadlocks */ + SaveAttachmentsInfo *sa_info; + sa_info = g_slice_new (SaveAttachmentsInfo); + sa_info->attachments_list = mime_parts; + sa_info->window = g_object_ref (window); g_signal_connect (save_dialog, "response", - G_CALLBACK (save_attachments_response), mime_parts); + G_CALLBACK (save_attachments_response), sa_info); gtk_widget_show_all (save_dialog); } @@ -2891,7 +3581,7 @@ void modest_msg_view_window_remove_attachments (ModestMsgViewWindow *window, gboolean get_all) { ModestMsgViewWindowPrivate *priv; - TnyList *mime_parts = NULL; + TnyList *mime_parts = NULL, *tmp; gchar *confirmation_message; gint response; gint n_attachments; @@ -2905,17 +3595,20 @@ modest_msg_view_window_remove_attachments (ModestMsgViewWindow *window, gboolean * because we don't have selection */ mime_parts = modest_msg_view_get_attachments (MODEST_MSG_VIEW (priv->msg_view)); - - /* Remove already purged messages from mime parts list */ - iter = tny_list_create_iterator (mime_parts); + + /* Remove already purged messages from mime parts list. We use + a copy of the list to remove items in the original one */ + tmp = tny_list_copy (mime_parts); + iter = tny_list_create_iterator (tmp); while (!tny_iterator_is_done (iter)) { TnyMimePart *part = TNY_MIME_PART (tny_iterator_get_current (iter)); - tny_iterator_next (iter); - if (tny_mime_part_is_purged (part)) { + if (tny_mime_part_is_purged (part)) tny_list_remove (mime_parts, (GObject *) part); - } + g_object_unref (part); + tny_iterator_next (iter); } + g_object_unref (tmp); g_object_unref (iter); if (!modest_maemo_utils_select_attachments (GTK_WINDOW (window), mime_parts, TRUE) || @@ -2960,7 +3653,7 @@ modest_msg_view_window_remove_attachments (ModestMsgViewWindow *window, gboolean } priv->purge_timeout = g_timeout_add (2000, show_remove_attachment_information, window); - + iter = tny_list_create_iterator (mime_parts); while (!tny_iterator_is_done (iter)) { TnyMimePart *part; @@ -2977,6 +3670,7 @@ modest_msg_view_window_remove_attachments (ModestMsgViewWindow *window, gboolean tny_msg_rewrite_cache (msg); tny_msg_view_set_msg (TNY_MSG_VIEW (priv->msg_view), msg); g_object_unref (msg); + update_branding (MODEST_MSG_VIEW_WINDOW (window)); g_object_unref (mime_parts); @@ -2990,8 +3684,6 @@ modest_msg_view_window_remove_attachments (ModestMsgViewWindow *window, gboolean g_object_unref (priv->remove_attachment_banner); priv->remove_attachment_banner = NULL; } - - } @@ -3012,7 +3704,15 @@ update_window_title (ModestMsgViewWindow *window) msg = tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view)); - if (msg != NULL) { + if (priv->other_body) { + gchar *description; + + description = modest_tny_mime_part_get_header_value (priv->other_body, "Content-Description"); + if (description) { + g_strstrip (description); + subject = description; + } + } else if (msg != NULL) { header = tny_msg_get_header (msg); subject = tny_header_dup_subject (header); g_object_unref (header); @@ -3071,19 +3771,47 @@ typedef struct { gchar *cache_id; TnyStream *output_stream; GtkWidget *msg_view; + GtkWidget *window; } FetchImageData; gboolean +on_fetch_image_timeout_refresh_view (gpointer userdata) +{ + ModestMsgViewWindowPrivate *priv; + + priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (userdata); + update_progress_hint (MODEST_MSG_VIEW_WINDOW (userdata)); + /* Note that priv->msg_view is set to NULL when this window is + distroyed */ + if (priv->msg_view && GTK_WIDGET_DRAWABLE (priv->msg_view)) { + gtk_widget_queue_draw (GTK_WIDGET (priv->msg_view)); + } + priv->fetch_image_redraw_handler = 0; + g_object_unref (userdata); + return FALSE; +} + +gboolean on_fetch_image_idle_refresh_view (gpointer userdata) { FetchImageData *fidata = (FetchImageData *) userdata; - g_message ("REFRESH VIEW"); + + gdk_threads_enter (); if (GTK_WIDGET_DRAWABLE (fidata->msg_view)) { - g_message ("QUEUING DRAW"); - gtk_widget_queue_draw (fidata->msg_view); + ModestMsgViewWindowPrivate *priv; + + priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (fidata->window); + priv->fetching_images--; + if (priv->fetch_image_redraw_handler == 0) { + priv->fetch_image_redraw_handler = g_timeout_add (500, on_fetch_image_timeout_refresh_view, g_object_ref (fidata->window)); + } + } + gdk_threads_leave (); + g_object_unref (fidata->msg_view); + g_object_unref (fidata->window); g_slice_free (FetchImageData, fidata); return FALSE; } @@ -3096,12 +3824,37 @@ on_fetch_image_thread (gpointer userdata) TnyStream *cache_stream; cache = modest_runtime_get_images_cache (); - cache_stream = tny_stream_cache_get_stream (cache, fidata->cache_id, (TnyStreamCacheOpenStreamFetcher) fetch_image_open_stream, (gpointer) fidata->uri); + cache_stream = + tny_stream_cache_get_stream (cache, + fidata->cache_id, + (TnyStreamCacheOpenStreamFetcher) fetch_image_open_stream, + (gpointer) fidata->uri); g_free (fidata->cache_id); g_free (fidata->uri); if (cache_stream != NULL) { - tny_stream_write_to_stream (cache_stream, fidata->output_stream); + char buffer[4096]; + + while (G_LIKELY (!tny_stream_is_eos (cache_stream))) { + gssize nb_read; + + nb_read = tny_stream_read (cache_stream, buffer, sizeof (buffer)); + if (G_UNLIKELY (nb_read < 0)) { + break; + } else if (G_LIKELY (nb_read > 0)) { + gssize nb_written = 0; + + while (G_UNLIKELY (nb_written < nb_read)) { + gssize len; + + len = tny_stream_write (fidata->output_stream, buffer + nb_written, + nb_read - nb_written); + if (G_UNLIKELY (len < 0)) + break; + nb_written += len; + } + } + } tny_stream_close (cache_stream); g_object_unref (cache_stream); } @@ -3109,10 +3862,7 @@ on_fetch_image_thread (gpointer userdata) tny_stream_close (fidata->output_stream); g_object_unref (fidata->output_stream); - - gdk_threads_enter (); g_idle_add (on_fetch_image_idle_refresh_view, fidata); - gdk_threads_leave (); return NULL; } @@ -3133,10 +3883,12 @@ on_fetch_image (ModestMsgView *msgview, fidata = g_slice_new0 (FetchImageData); fidata->msg_view = g_object_ref (msgview); + fidata->window = g_object_ref (window); fidata->uri = g_strdup (uri); fidata->cache_id = modest_images_cache_get_id (current_account, uri); fidata->output_stream = g_object_ref (stream); + priv->fetching_images++; if (g_thread_create (on_fetch_image_thread, fidata, FALSE, NULL) == NULL) { g_object_unref (fidata->output_stream); g_free (fidata->cache_id); @@ -3144,8 +3896,11 @@ on_fetch_image (ModestMsgView *msgview, g_object_unref (fidata->msg_view); g_slice_free (FetchImageData, fidata); tny_stream_close (stream); + priv->fetching_images--; + update_progress_hint (window); return FALSE; } + update_progress_hint (window); return TRUE; } @@ -3156,16 +3911,23 @@ setup_menu (ModestMsgViewWindow *self) g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW(self)); /* Settings menu buttons */ - modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_replytoall"), NULL, - APP_MENU_CALLBACK (modest_ui_actions_on_reply_all), - MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_reply_msg)); - modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_forward"), "d", - APP_MENU_CALLBACK (modest_ui_actions_on_forward), - MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_reply_msg)); + modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_find"), NULL, + APP_MENU_CALLBACK (modest_msg_view_window_show_find_toolbar), + MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_find_in_msg)); + + modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), + dngettext(GETTEXT_PACKAGE, + "mcen_me_move_message", + "mcen_me_move_messages", + 1), + NULL, + APP_MENU_CALLBACK (modest_ui_actions_on_move_to), + MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_move_to)); modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_mark_as_read"), NULL, APP_MENU_CALLBACK (modest_ui_actions_on_mark_as_read), MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_mark_as_read_msg_in_view)); + modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_inbox_mark_as_unread"), NULL, APP_MENU_CALLBACK (modest_ui_actions_on_mark_as_unread), MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_mark_as_unread_msg_in_view)); @@ -3183,6 +3945,10 @@ setup_menu (ModestMsgViewWindow *self) modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_me_viewer_addtocontacts"), NULL, APP_MENU_CALLBACK (modest_ui_actions_add_to_contacts), MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_add_to_contacts)); + + modest_hildon2_window_add_to_menu (MODEST_HILDON2_WINDOW (self), _("mcen_ti_message_properties"), NULL, + APP_MENU_CALLBACK (modest_ui_actions_on_details), + MODEST_DIMMING_CALLBACK (modest_ui_dimming_rules_on_details)); } void @@ -3192,7 +3958,6 @@ modest_msg_view_window_add_to_contacts (ModestMsgViewWindow *self) priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self); GSList *recipients = NULL; TnyMsg *msg = NULL; - gboolean contacts_to_add = FALSE; msg = tny_msg_view_get_msg (TNY_MSG_VIEW (priv->msg_view)); if (msg == NULL) { @@ -3208,64 +3973,184 @@ modest_msg_view_window_add_to_contacts (ModestMsgViewWindow *self) g_object_unref (msg); } - if (recipients != NULL) { - GtkWidget *picker_dialog; - GtkWidget *selector; - GSList *node; - gchar *selected = NULL; + if (recipients) { + /* Offer the user to add recipients to the address book */ + modest_address_book_add_address_list_with_selector (recipients, (GtkWindow *) self); + g_slist_foreach (recipients, (GFunc) g_free, NULL); g_slist_free (recipients); + } +} - selector = hildon_touch_selector_new_text (); - g_object_ref (selector); +static gboolean +_modest_msg_view_window_map_event (GtkWidget *widget, + GdkEvent *event, + gpointer userdata) +{ + ModestMsgViewWindow *self = (ModestMsgViewWindow *) userdata; - for (node = recipients; node != NULL; node = g_slist_next (node)) { - if (!modest_address_book_has_address ((const gchar *) node->data)) { - hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), - (const gchar *) node->data); - contacts_to_add = TRUE; - } - } + update_progress_hint (self); + + return FALSE; +} + +void +modest_msg_view_window_fetch_images (ModestMsgViewWindow *self) +{ + ModestMsgViewWindowPrivate *priv; + priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self); - if (contacts_to_add) { - gint picker_result; + modest_msg_view_request_fetch_images (MODEST_MSG_VIEW (priv->msg_view)); +} - picker_dialog = hildon_picker_dialog_new (GTK_WINDOW (self)); - gtk_window_set_title (GTK_WINDOW (picker_dialog), _("mcen_me_viewer_addtocontacts")); +gboolean +modest_msg_view_window_has_blocked_external_images (ModestMsgViewWindow *self) +{ + ModestMsgViewWindowPrivate *priv; + priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self); - hildon_picker_dialog_set_selector (HILDON_PICKER_DIALOG (picker_dialog), - HILDON_TOUCH_SELECTOR (selector)); - - picker_result = gtk_dialog_run (GTK_DIALOG (picker_dialog)); + g_return_val_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self), FALSE); - if (picker_result == GTK_RESPONSE_OK) { - selected = hildon_touch_selector_get_current_text (HILDON_TOUCH_SELECTOR (selector)); - } - gtk_widget_destroy (picker_dialog); + return modest_msg_view_has_blocked_external_images (MODEST_MSG_VIEW (priv->msg_view)); +} + +void +modest_msg_view_window_reload (ModestMsgViewWindow *self) +{ + ModestMsgViewWindowPrivate *priv; + const gchar *msg_uid; + TnyHeader *header = NULL; + TnyFolder *folder = NULL; + + g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (self)); + + priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self); + + header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (self)); + if (!header) + return; + + folder = tny_header_get_folder (header); + g_object_unref (header); + + if (!folder) + return; - if (selected) - modest_address_book_add_address (selected); - g_free (selected); + msg_uid = modest_msg_view_window_get_message_uid (self); + if (msg_uid) { + GtkTreeRowReference *row_reference; + if (priv->row_reference && gtk_tree_row_reference_valid (priv->row_reference)) { + row_reference = priv->row_reference; } else { + row_reference = NULL; + } + if (!message_reader (self, priv, NULL, msg_uid, folder, row_reference)) + g_warning ("Shouldn't happen, trying to reload a message failed"); + } + + g_object_unref (folder); +} + +static void +update_branding (ModestMsgViewWindow *self) +{ + const gchar *account; + const gchar *mailbox; + ModestAccountMgr *mgr; + ModestProtocol *protocol = NULL; + gchar *service_name = NULL; + const GdkPixbuf *service_icon = NULL; + ModestMsgViewWindowPrivate *priv; - g_object_unref (selector); + priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self); + + account = modest_window_get_active_account (MODEST_WINDOW (self)); + mailbox = modest_window_get_active_mailbox (MODEST_WINDOW (self)); + + mgr = modest_runtime_get_account_mgr (); + if (modest_account_mgr_account_is_multimailbox (mgr, account, &protocol)) { + if (MODEST_IS_ACCOUNT_PROTOCOL (protocol)) { + service_name = modest_account_protocol_get_service_name (MODEST_ACCOUNT_PROTOCOL (protocol), + account, mailbox); + service_icon = modest_account_protocol_get_service_icon (MODEST_ACCOUNT_PROTOCOL (protocol), + account, mailbox, MODEST_ICON_SIZE_SMALL); } } - - if (recipients) {g_slist_foreach (recipients, (GFunc) g_free, NULL); g_slist_free (recipients);} + + modest_msg_view_set_branding (MODEST_MSG_VIEW (priv->msg_view), service_name, service_icon); + g_free (service_name); } -static gboolean -_modest_msg_view_window_map_event (GtkWidget *widget, - GdkEvent *event, - gpointer userdata) +static void +sync_flags (ModestMsgViewWindow *self) { - ModestMsgViewWindow *self = (ModestMsgViewWindow *) userdata; - ModestMsgViewWindowPrivate *priv = MODEST_MSG_VIEW_WINDOW_GET_PRIVATE (self); + TnyHeader *header = NULL; + + header = modest_msg_view_window_get_header (self); + if (!header) { + TnyMsg *msg = modest_msg_view_window_get_message (self); + if (msg) { + header = tny_msg_get_header (msg); + g_object_unref (msg); + } + } + + if (header) { + TnyFolder *folder = tny_header_get_folder (header); - if (priv->progress_hint) { - hildon_gtk_window_set_progress_indicator (GTK_WINDOW (self), TRUE); + if (folder) { + ModestMailOperation *mail_op; + + /* Sync folder, we need this to save the seen flag */ + mail_op = modest_mail_operation_new (NULL); + modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), + mail_op); + modest_mail_operation_sync_folder (mail_op, folder, FALSE, NULL, NULL); + g_object_unref (mail_op); + g_object_unref (folder); + } + g_object_unref (header); } +} + +static gboolean +on_realize (GtkWidget *widget, + gpointer userdata) +{ + GdkDisplay *display; + Atom atom; + unsigned long val = 1; + + display = gdk_drawable_get_display (widget->window); + atom = gdk_x11_get_xatom_by_name_for_display (display, "_HILDON_ZOOM_KEY_ATOM"); + XChangeProperty (GDK_DISPLAY_XDISPLAY (display), + GDK_WINDOW_XID (widget->window), atom, + XA_INTEGER, 32, PropModeReplace, + (unsigned char *) &val, 1); return FALSE; } + +static gboolean +on_handle_calendar (ModestMsgView *msgview, TnyMimePart *calendar_part, GtkContainer *container, ModestMsgViewWindow *self) +{ + const gchar *account_name; + ModestProtocolType proto_type; + ModestProtocol *protocol; + gboolean retval = FALSE; + + account_name = modest_window_get_active_account (MODEST_WINDOW (self)); + + /* Get proto */ + proto_type = modest_account_mgr_get_store_protocol (modest_runtime_get_account_mgr (), + account_name); + protocol = + modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (), + proto_type); + + if (MODEST_IS_ACCOUNT_PROTOCOL (protocol)) { + retval = modest_account_protocol_handle_calendar (MODEST_ACCOUNT_PROTOCOL (protocol), MODEST_WINDOW (self), + calendar_part, container); + } + return retval; +}