Fixes NB#113634, show progress information in Viewer when opening large attachments
[modest] / src / modest-ui-actions.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
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.
16  *
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.
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif /*HAVE_CONFIG_H*/
33
34 #include <glib/gi18n.h>
35 #include <glib/gprintf.h>
36 #include <string.h>
37 #include <modest-runtime.h>
38 #include <modest-defs.h>
39 #include <modest-tny-folder.h>
40 #include <modest-tny-msg.h>
41 #include <modest-tny-account.h>
42 #include <modest-address-book.h>
43 #include "modest-error.h"
44 #include "modest-ui-actions.h"
45 #include "modest-tny-platform-factory.h"
46 #include "modest-platform.h"
47 #include "modest-debug.h"
48 #include <tny-mime-part.h>
49 #include <tny-camel-folder.h>
50 #include <tny-camel-imap-folder.h>
51 #include <tny-camel-pop-folder.h>
52 #ifdef MODEST_TOOLKIT_HILDON2
53 #include <modest-accounts-window.h>
54 #include <hildon/hildon-pannable-area.h>
55 #include <hildon/hildon-gtk.h>
56 #include <modest-header-window.h>
57 #include <modest-folder-window.h>
58 #include <modest-maemo-utils.h>
59 #endif
60
61 #ifdef MODEST_PLATFORM_MAEMO
62 #include "maemo/modest-osso-state-saving.h"
63 #endif /* MODEST_PLATFORM_MAEMO */
64 #ifndef MODEST_TOOLKIT_GTK
65 #include "maemo/modest-hildon-includes.h"
66 #include "maemo/modest-connection-specific-smtp-window.h"
67 #endif /* !MODEST_TOOLKIT_GTK */
68 #include <modest-utils.h>
69
70 #include "widgets/modest-ui-constants.h"
71 #include <widgets/modest-main-window.h>
72 #include <widgets/modest-msg-view-window.h>
73 #include <widgets/modest-account-view-window.h>
74 #include <widgets/modest-details-dialog.h>
75 #include <widgets/modest-attachments-view.h>
76 #include "widgets/modest-folder-view.h"
77 #include "widgets/modest-global-settings-dialog.h"
78 #include "modest-account-mgr-helpers.h"
79 #include "modest-mail-operation.h"
80 #include "modest-text-utils.h"
81 #include <modest-widget-memory.h>
82 #include <tny-error.h>
83 #include <tny-simple-list.h>
84 #include <tny-msg-view.h>
85 #include <tny-device.h>
86 #include <tny-merge-folder.h>
87
88 #include <gtkhtml/gtkhtml.h>
89
90 #define MIN_FREE_SPACE 5 * 1024 * 1024
91 #define MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
92
93 typedef struct _GetMsgAsyncHelper {
94         ModestWindow *window;
95         ModestMailOperation *mail_op;
96         TnyIterator *iter;
97         guint num_ops;
98         GFunc func;
99         gpointer user_data;
100 } GetMsgAsyncHelper;
101
102 typedef enum _ReplyForwardAction {
103         ACTION_REPLY,
104         ACTION_REPLY_TO_ALL,
105         ACTION_FORWARD
106 } ReplyForwardAction;
107
108 typedef struct _ReplyForwardHelper {
109         guint reply_forward_type;
110         ReplyForwardAction action;
111         gchar *account_name;
112         gchar *mailbox;
113         GtkWidget *parent_window;
114         TnyHeader *header;
115 } ReplyForwardHelper;
116
117 typedef struct _MoveToHelper {
118         GtkTreeRowReference *reference;
119         GtkWidget *banner;
120 } MoveToHelper;
121
122 typedef struct _PasteAsAttachmentHelper {
123         ModestMsgEditWindow *window;
124         GtkWidget *banner;
125 } PasteAsAttachmentHelper;
126
127 typedef struct {
128         TnyList *list;
129         ModestWindow *win;
130 } MoveToInfo;
131
132 /*
133  * The do_headers_action uses this kind of functions to perform some
134  * action to each member of a list of headers
135  */
136 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
137
138 static void     do_headers_action     (ModestWindow *win,
139                                        HeadersFunc func,
140                                        gpointer user_data);
141
142 static void     open_msg_cb            (ModestMailOperation *mail_op,
143                                         TnyHeader *header,
144                                         gboolean canceled,
145                                         TnyMsg *msg,
146                                         GError *err,
147                                         gpointer user_data);
148
149 static void     reply_forward_cb       (ModestMailOperation *mail_op,
150                                         TnyHeader *header,
151                                         gboolean canceled,
152                                         TnyMsg *msg,
153                                         GError *err,
154                                         gpointer user_data);
155
156 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
157
158 static void     folder_refreshed_cb    (ModestMailOperation *mail_op,
159                                         TnyFolder *folder,
160                                         gpointer user_data);
161
162 static void     on_send_receive_finished (ModestMailOperation  *mail_op,
163                                           gpointer user_data);
164
165 static gint header_list_count_uncached_msgs (TnyList *header_list);
166
167 static gboolean connect_to_get_msg (ModestWindow *win,
168                                     gint num_of_uncached_msgs,
169                                     TnyAccount *account);
170
171 static gboolean remote_folder_has_leave_on_server (TnyFolderStore *folder);
172
173 static void     do_create_folder (GtkWindow *window,
174                                   TnyFolderStore *parent_folder,
175                                   const gchar *suggested_name);
176
177 static TnyAccount *get_account_from_folder_store (TnyFolderStore *folder_store);
178
179 static void modest_ui_actions_on_main_window_move_to (GtkAction *action,
180                                                       GtkWidget *folder_view,
181                                                       TnyFolderStore *dst_folder,
182                                                       ModestMainWindow *win);
183 #ifdef MODEST_TOOLKIT_HILDON2
184 static void modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
185                                                         TnyFolderStore *dst_folder,
186                                                         TnyList *selection,
187                                                         GtkWindow *win);
188 #endif
189
190 static void modest_ui_actions_on_window_move_to (GtkAction *action,
191                                                  TnyList *list_to_move,
192                                                  TnyFolderStore *dst_folder,
193                                                  ModestWindow *win);
194
195 /*
196  * This function checks whether a TnyFolderStore is a pop account
197  */
198 static gboolean
199 remote_folder_has_leave_on_server (TnyFolderStore *folder)
200 {
201         TnyAccount *account;
202         gboolean result;
203
204         g_return_val_if_fail (TNY_IS_FOLDER_STORE (folder), FALSE);
205
206         account = get_account_from_folder_store (folder);
207         result = (modest_protocol_registry_protocol_type_has_leave_on_server (modest_runtime_get_protocol_registry (),
208                                                                               modest_tny_account_get_protocol_type (account)));
209         g_object_unref (account);
210
211         return result;
212 }
213
214 /* FIXME: this should be merged with the similar code in modest-account-view-window */
215 /* Show the account creation wizard dialog.
216  * returns: TRUE if an account was created. FALSE if the user cancelled.
217  */
218 gboolean
219 modest_ui_actions_run_account_setup_wizard (ModestWindow *win)
220 {
221         gboolean result = FALSE;
222         GtkWindow *wizard;
223         gint dialog_response;
224
225         /* there is no such wizard yet */
226         wizard = GTK_WINDOW (modest_platform_get_account_settings_wizard ());
227         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (wizard), (GtkWindow *) win);
228
229 #ifndef MODEST_TOOLKIT_HILDON2
230         /* always present a main window in the background
231          * we do it here, so we cannot end up with two wizards (as this
232          * function might be called in modest_window_mgr_get_main_window as well */
233         if (!win)
234                 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
235                                                          TRUE);  /* create if not existent */
236 #else
237         if (!win) {
238                 GList *window_list;
239                 ModestWindowMgr *mgr;
240
241                 mgr = modest_runtime_get_window_mgr ();
242
243                 window_list = modest_window_mgr_get_window_list (mgr);
244                 if (window_list == NULL) {
245                         ModestWindow *old_win;
246                         win = MODEST_WINDOW (modest_accounts_window_new ());
247                         if (modest_window_mgr_register_window (mgr, win, NULL)) {
248                                 gtk_widget_show_all (GTK_WIDGET (win));
249                         } else {
250                                 gtk_widget_destroy (GTK_WIDGET (win));
251                                 win = NULL;
252                         }
253
254                         old_win = win;
255                         win = MODEST_WINDOW (modest_folder_window_new (NULL));
256                         if (modest_window_mgr_register_window (mgr, win, NULL)) {
257                                 gtk_widget_show_all (GTK_WIDGET (win));
258                         } else {
259                                 gtk_widget_destroy (GTK_WIDGET (win));
260                                 win = old_win;
261                         }
262                 } else {
263                         g_list_free (window_list);
264                 }
265         }
266 #endif
267
268         if (win)
269                 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
270
271         /* make sure the mainwindow is visible. We need to present the
272            wizard again to give it the focus back. show_all are needed
273            in order to get the widgets properly drawn (MainWindow main
274            paned won't be in its right position and the dialog will be
275            missplaced */
276 #ifndef MODEST_TOOLKIT_HILDON2
277         gtk_widget_show_all (GTK_WIDGET (win));
278         gtk_widget_show_all (GTK_WIDGET (wizard));
279         gtk_window_present (GTK_WINDOW (win));
280         gtk_window_present (GTK_WINDOW (wizard));
281 #endif
282
283         dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
284         gtk_widget_destroy (GTK_WIDGET (wizard));
285         if (gtk_events_pending ())
286                 gtk_main_iteration ();
287
288         if (dialog_response == GTK_RESPONSE_CANCEL) {
289                 result = FALSE;
290         } else {
291                 /* Check whether an account was created: */
292                 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
293         }
294         return result;
295 }
296
297
298 void
299 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
300 {
301         GtkWidget *about;
302         const gchar *authors[] = {
303                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
304                 NULL
305         };
306         about = gtk_about_dialog_new ();
307         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
308         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
309         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
310                                         _("Copyright (c) 2006, Nokia Corporation\n"
311                                           "All rights reserved."));
312         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
313                                        _("a modest e-mail client\n\n"
314                                          "design and implementation: Dirk-Jan C. Binnema\n"
315                                          "contributions from the fine people at KC and Ig\n"
316                                          "uses the tinymail email framework written by Philip van Hoof"));
317         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
318         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
319         gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
320         gtk_window_set_modal (GTK_WINDOW (about), TRUE);
321
322         gtk_dialog_run (GTK_DIALOG (about));
323         gtk_widget_destroy(about);
324 }
325
326 /*
327  * Gets the list of currently selected messages. If the win is the
328  * main window, then it returns a newly allocated list of the headers
329  * selected in the header view. If win is the msg view window, then
330  * the value returned is a list with just a single header.
331  *
332  * The caller of this funcion must free the list.
333  */
334 static TnyList *
335 get_selected_headers (ModestWindow *win)
336 {
337         if (MODEST_IS_MAIN_WINDOW(win)) {
338                 GtkWidget *header_view;
339
340                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
341                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
342                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
343
344         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
345                 /* for MsgViewWindows, we simply return a list with one element */
346                 TnyHeader *header;
347                 TnyList *list = NULL;
348
349                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
350                 if (header != NULL) {
351                         list = tny_simple_list_new ();
352                         tny_list_prepend (list, G_OBJECT(header));
353                         g_object_unref (G_OBJECT(header));
354                 }
355
356                 return list;
357
358 #ifdef MODEST_TOOLKIT_HILDON2
359         } else if (MODEST_IS_HEADER_WINDOW (win)) {
360                 GtkWidget *header_view;
361
362                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
363                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
364 #endif
365         } else
366                 return NULL;
367 }
368
369 static GtkTreeRowReference *
370 get_next_after_selected_headers (ModestHeaderView *header_view)
371 {
372         GtkTreeSelection *sel;
373         GList *selected_rows, *node;
374         GtkTreePath *path;
375         GtkTreeRowReference *result;
376         GtkTreeModel *model;
377
378         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
379         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
380         selected_rows = gtk_tree_selection_get_selected_rows (sel, NULL);
381
382         if (selected_rows == NULL)
383                 return NULL;
384
385         node = g_list_last (selected_rows);
386         path = gtk_tree_path_copy ((GtkTreePath *) node->data);
387         gtk_tree_path_next (path);
388
389         result = gtk_tree_row_reference_new (model, path);
390
391         gtk_tree_path_free (path);
392         g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
393         g_list_free (selected_rows);
394
395         return result;
396 }
397
398 static void
399 headers_action_mark_as_read (TnyHeader *header,
400                              ModestWindow *win,
401                              gpointer user_data)
402 {
403         TnyHeaderFlags flags;
404
405         g_return_if_fail (TNY_IS_HEADER(header));
406
407         flags = tny_header_get_flags (header);
408         if (flags & TNY_HEADER_FLAG_SEEN) return;
409         tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
410 }
411
412 static void
413 headers_action_mark_as_unread (TnyHeader *header,
414                                ModestWindow *win,
415                                gpointer user_data)
416 {
417         TnyHeaderFlags flags;
418
419         g_return_if_fail (TNY_IS_HEADER(header));
420
421         flags = tny_header_get_flags (header);
422         if (flags & TNY_HEADER_FLAG_SEEN)  {
423                 tny_header_unset_flag (header, TNY_HEADER_FLAG_SEEN);
424         }
425 }
426
427 /** After deleing a message that is currently visible in a window,
428  * show the next message from the list, or close the window if there are no more messages.
429  **/
430 void
431 modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
432 {
433         /* Close msg view window or select next */
434         if (!modest_msg_view_window_select_next_message (win) &&
435             !modest_msg_view_window_select_previous_message (win)) {
436                 gboolean ret_value;
437                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
438         }
439 }
440
441
442 void
443 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
444 {
445         modest_ui_actions_on_edit_mode_delete_message (win);
446 }
447
448 gboolean
449 modest_ui_actions_on_edit_mode_delete_message (ModestWindow *win)
450 {
451         TnyList *header_list = NULL;
452         TnyIterator *iter = NULL;
453         TnyHeader *header = NULL;
454         gchar *message = NULL;
455         gchar *desc = NULL;
456         gint response;
457         ModestWindowMgr *mgr;
458         GtkWidget *header_view = NULL;
459         gboolean retval = TRUE;
460
461         g_return_val_if_fail (MODEST_IS_WINDOW(win), FALSE);
462
463         /* Check first if the header view has the focus */
464         if (MODEST_IS_MAIN_WINDOW (win)) {
465                 header_view =
466                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
467                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
468                 if (!gtk_widget_is_focus (header_view))
469                         return FALSE;
470         }
471
472         /* Get the headers, either from the header view (if win is the main window),
473          * or from the message view window: */
474         header_list = get_selected_headers (win);
475         if (!header_list) return FALSE;
476
477         /* Check if any of the headers are already opened, or in the process of being opened */
478         if (MODEST_IS_MAIN_WINDOW (win)) {
479                 gint opened_headers = 0;
480
481                 iter = tny_list_create_iterator (header_list);
482                 mgr = modest_runtime_get_window_mgr ();
483                 while (!tny_iterator_is_done (iter)) {
484                         header = TNY_HEADER (tny_iterator_get_current (iter));
485                         if (header) {
486                                 if (modest_window_mgr_find_registered_header (mgr, header, NULL))
487                                         opened_headers++;
488                                 g_object_unref (header);
489                         }
490                         tny_iterator_next (iter);
491                 }
492                 g_object_unref (iter);
493
494                 if (opened_headers > 0) {
495                         gchar *msg;
496
497                         msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"),
498                                                opened_headers);
499
500                         modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg, FALSE);
501
502                         g_free (msg);
503                         g_object_unref (header_list);
504                         return FALSE;
505                 }
506         }
507
508         /* Select message */
509         if (tny_list_get_length(header_list) == 1) {
510                 iter = tny_list_create_iterator (header_list);
511                 header = TNY_HEADER (tny_iterator_get_current (iter));
512                 if (header) {
513                         gchar *subject;
514                         subject = tny_header_dup_subject (header);
515                         if (!subject)
516                                 subject = g_strdup (_("mail_va_no_subject"));
517                         desc = g_strdup_printf ("%s", subject);
518                         g_free (subject);
519                         g_object_unref (header);
520                 }
521
522                 g_object_unref (iter);
523         }
524         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages",
525                                            tny_list_get_length(header_list)), desc);
526
527         /* Confirmation dialog */
528         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
529                                                             message);
530
531
532         if (response == GTK_RESPONSE_OK) {
533                 ModestWindow *main_window = NULL;
534                 ModestWindowMgr *mgr = NULL;
535                 GtkTreeModel *model = NULL;
536                 GtkTreeSelection *sel = NULL;
537                 GList *sel_list = NULL, *tmp = NULL;
538                 GtkTreeRowReference *next_row_reference = NULL;
539                 GtkTreeRowReference *prev_row_reference = NULL;
540                 GtkTreePath *next_path = NULL;
541                 GtkTreePath *prev_path = NULL;
542                 ModestMailOperation *mail_op = NULL;
543
544                 /* Find last selected row */
545                 if (MODEST_IS_MAIN_WINDOW (win)) {
546                         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
547                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
548                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
549                         for (tmp=sel_list; tmp; tmp=tmp->next) {
550                                 if (tmp->next == NULL) {
551                                         prev_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
552                                         next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
553
554                                         gtk_tree_path_prev (prev_path);
555                                         gtk_tree_path_next (next_path);
556
557                                         prev_row_reference = gtk_tree_row_reference_new (model, prev_path);
558                                         next_row_reference = gtk_tree_row_reference_new (model, next_path);
559                                 }
560                         }
561                 }
562
563                 /* Disable window dimming management */
564                 modest_window_disable_dimming (MODEST_WINDOW(win));
565
566                 /* Remove each header. If it's a view window header_view == NULL */
567                 mail_op = modest_mail_operation_new ((GObject *) win);
568                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
569                                                  mail_op);
570                 modest_mail_operation_remove_msgs (mail_op, header_list, FALSE);
571                 g_object_unref (mail_op);
572
573                 /* Enable window dimming management */
574                 if (sel != NULL) {
575                         gtk_tree_selection_unselect_all (sel);
576                 }
577                 modest_window_enable_dimming (MODEST_WINDOW(win));
578
579                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
580                         modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
581
582                         /* Get main window */
583                         mgr = modest_runtime_get_window_mgr ();
584                         main_window = modest_window_mgr_get_main_window (mgr, FALSE); /* don't create */
585                 } else if (MODEST_IS_MAIN_WINDOW (win)) {
586                         /* Move cursor to next row */
587                         main_window = win;
588
589                         /* Select next or previous row */
590                         if (gtk_tree_row_reference_valid (next_row_reference)) {
591                                 gtk_tree_selection_select_path (sel, next_path);
592                         }
593                         else if (gtk_tree_row_reference_valid (prev_row_reference)) {
594                                 gtk_tree_selection_select_path (sel, prev_path);
595                         }
596
597                         /* Free */
598                         if (gtk_tree_row_reference_valid (next_row_reference))
599                                 gtk_tree_row_reference_free (next_row_reference);
600                         if (next_path != NULL)
601                                 gtk_tree_path_free (next_path);
602                         if (gtk_tree_row_reference_valid (prev_row_reference))
603                                 gtk_tree_row_reference_free (prev_row_reference);
604                         if (prev_path != NULL)
605                                 gtk_tree_path_free (prev_path);
606                 }
607
608                 /* Update toolbar dimming state */
609                 if (main_window) {
610                         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
611                         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
612                 }
613
614                 /* Free */
615                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
616                 g_list_free (sel_list);
617                 retval = TRUE;
618         } else {
619                 retval = FALSE;
620         }
621
622         /* Free*/
623         g_free(message);
624         g_free(desc);
625         g_object_unref (header_list);
626
627         return retval;
628 }
629
630
631
632
633 /* delete either message or folder, based on where we are */
634 void
635 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
636 {
637         g_return_if_fail (MODEST_IS_WINDOW(win));
638
639         /* Check first if the header view has the focus */
640         if (MODEST_IS_MAIN_WINDOW (win)) {
641                 GtkWidget *w;
642                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
643                                                          MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
644                 if (gtk_widget_is_focus (w)) {
645                         modest_ui_actions_on_delete_folder (action, MODEST_WINDOW(win));
646                         return;
647                 }
648         }
649         modest_ui_actions_on_delete_message (action, win);
650 }
651
652 void
653 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
654 {
655         ModestWindowMgr *mgr = NULL;
656
657 #ifdef MODEST_PLATFORM_MAEMO
658         modest_osso_save_state();
659 #endif /* MODEST_PLATFORM_MAEMO */
660
661         g_debug ("closing down, clearing %d item(s) from operation queue",
662                  modest_mail_operation_queue_num_elements
663                  (modest_runtime_get_mail_operation_queue()));
664
665         /* cancel all outstanding operations */
666         modest_mail_operation_queue_cancel_all
667                 (modest_runtime_get_mail_operation_queue());
668
669         g_debug ("queue has been cleared");
670
671
672         /* Check if there are opened editing windows */
673         mgr = modest_runtime_get_window_mgr ();
674         modest_window_mgr_close_all_windows (mgr);
675
676         /* note: when modest-tny-account-store is finalized,
677            it will automatically set all network connections
678            to offline */
679
680 /*      gtk_main_quit (); */
681 }
682
683 void
684 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
685 {
686         gboolean ret_value;
687
688         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
689
690 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
691 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
692 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
693 /*              gboolean ret_value; */
694 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
695 /*      } else if (MODEST_IS_WINDOW (win)) { */
696 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
697 /*      } else { */
698 /*              g_return_if_reached (); */
699 /*      } */
700 }
701
702 void
703 modest_ui_actions_add_to_contacts (GtkAction *action, ModestWindow *win)
704 {
705        g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (win));
706
707        modest_msg_view_window_add_to_contacts (MODEST_MSG_VIEW_WINDOW (win));
708 }
709
710 void
711 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
712 {
713         GtkClipboard *clipboard = NULL;
714         gchar *selection = NULL;
715
716         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
717         selection = gtk_clipboard_wait_for_text (clipboard);
718
719         /* Question: why is the clipboard being used here?
720          * It doesn't really make a lot of sense. */
721
722         if (selection)
723         {
724                 modest_address_book_add_address (selection);
725                 g_free (selection);
726         }
727 }
728
729 void
730 modest_ui_actions_on_new_account (GtkAction *action,
731                                   ModestWindow *window)
732 {
733         if (!modest_ui_actions_run_account_setup_wizard (window)) {
734                 g_debug ("%s: wizard was already running", __FUNCTION__);
735         }
736 }
737
738 void
739 modest_ui_actions_on_accounts (GtkAction *action,
740                                ModestWindow *win)
741 {
742         /* This is currently only implemented for Maemo */
743         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
744                 if (!modest_ui_actions_run_account_setup_wizard (win))
745                         g_debug ("%s: wizard was already running", __FUNCTION__);
746
747                 return;
748         } else {
749                 /* Show the list of accounts */
750                 GtkWindow *account_win = GTK_WINDOW (modest_account_view_window_new ());
751
752                 /* The accounts dialog must be modal */
753                 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (account_win), (GtkWindow *) win);
754                 modest_utils_show_dialog_and_forget (GTK_WINDOW (win), GTK_DIALOG (account_win));
755         }
756 }
757
758 void
759 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
760 {
761         /* This is currently only implemented for Maemo,
762          * because it requires an API (libconic) to detect different connection
763          * possiblities.
764          */
765 #ifndef MODEST_TOOLKIT_GTK /* Defined in config.h */
766
767         /* Create the window if necessary: */
768         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
769         modest_connection_specific_smtp_window_fill_with_connections (
770                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window),
771                 modest_runtime_get_account_mgr());
772
773         /* Show the window: */
774         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
775                                      GTK_WINDOW (specific_window), (GtkWindow *) win);
776         gtk_widget_show (specific_window);
777 #endif /* !MODEST_TOOLKIT_GTK */
778 }
779
780 void
781 modest_ui_actions_compose_msg(ModestWindow *win,
782                               const gchar *to_str,
783                               const gchar *cc_str,
784                               const gchar *bcc_str,
785                               const gchar *subject_str,
786                               const gchar *body_str,
787                               GSList *attachments,
788                               gboolean set_as_modified)
789 {
790         gchar *account_name = NULL;
791         const gchar *mailbox;
792         TnyMsg *msg = NULL;
793         TnyAccount *account = NULL;
794         TnyFolder *folder = NULL;
795         gchar *from_str = NULL, *signature = NULL, *body = NULL;
796         gchar *recipient = NULL;
797         gboolean use_signature = FALSE;
798         ModestWindow *msg_win = NULL;
799         ModestAccountMgr *mgr = modest_runtime_get_account_mgr();
800         ModestTnyAccountStore *store = modest_runtime_get_account_store();
801         GnomeVFSFileSize total_size, allowed_size;
802
803         /* we check for low-mem */
804         if (modest_platform_check_memory_low (win, TRUE))
805                 goto cleanup;
806
807 #ifdef MODEST_TOOLKIT_HILDON2
808         if (win)
809                 account_name = g_strdup (modest_window_get_active_account(win));
810 #endif
811         if (!account_name) {
812                 account_name = modest_account_mgr_get_default_account(mgr);
813         }
814         if (!account_name) {
815                 g_printerr ("modest: no account found\n");
816                 goto cleanup;
817         }
818
819         if (win)
820                 mailbox = modest_window_get_active_mailbox (win);
821         else
822                 mailbox = NULL;
823         account = modest_tny_account_store_get_server_account (store, account_name, TNY_ACCOUNT_TYPE_STORE);
824         if (!account) {
825                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
826                 goto cleanup;
827         }
828         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
829         if (!folder) {
830                 g_printerr ("modest: failed to find Drafts folder\n");
831                 goto cleanup;
832         }
833         from_str = modest_account_mgr_get_from_string (mgr, account_name, mailbox);
834         if (!from_str) {
835                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
836                 goto cleanup;
837         }
838
839         recipient = modest_text_utils_get_email_address (from_str);
840         signature = modest_account_mgr_get_signature_from_recipient (mgr, recipient, &use_signature);
841         g_free (recipient);
842         if (body_str != NULL) {
843                 body = use_signature ? g_strconcat(body_str, "\n--\n", signature, NULL) : g_strdup(body_str);
844         } else {
845                 body = use_signature ? g_strconcat("\n--\n", signature, NULL) : g_strdup("");
846         }
847
848         msg = modest_tny_msg_new (to_str, from_str, cc_str, bcc_str, subject_str, NULL, NULL, body, NULL, NULL, NULL);
849         if (!msg) {
850                 g_printerr ("modest: failed to create new msg\n");
851                 goto cleanup;
852         }
853
854         /* Create and register edit window */
855         /* This is destroyed by TODO. */
856         total_size = 0;
857         allowed_size = MODEST_MAX_ATTACHMENT_SIZE;
858         msg_win = modest_msg_edit_window_new (msg, account_name, mailbox, FALSE);
859
860         if (!modest_window_mgr_register_window (modest_runtime_get_window_mgr(), msg_win, win)) {
861                 gtk_widget_destroy (GTK_WIDGET (msg_win));
862                 goto cleanup;
863         }
864         modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (msg_win), set_as_modified);
865         gtk_widget_show_all (GTK_WIDGET (msg_win));
866
867         while (attachments) {
868                 total_size +=
869                         modest_msg_edit_window_attach_file_one((ModestMsgEditWindow *)msg_win,
870                                                                attachments->data, allowed_size);
871
872                 if (total_size > allowed_size) {
873                         g_warning ("%s: total size: %u",
874                                    __FUNCTION__, (unsigned int)total_size);
875                         break;
876                 }
877                 allowed_size -= total_size;
878
879                 attachments = g_slist_next(attachments);
880         }
881
882 cleanup:
883         g_free (from_str);
884         g_free (signature);
885         g_free (body);
886         g_free (account_name);
887         if (account)
888                 g_object_unref (G_OBJECT(account));
889         if (folder)
890                 g_object_unref (G_OBJECT(folder));
891         if (msg)
892                 g_object_unref (G_OBJECT(msg));
893 }
894
895 void
896 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
897 {
898         /* if there are no accounts yet, just show the wizard */
899         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE))
900                 if (!modest_ui_actions_run_account_setup_wizard (win))
901                         return;
902
903         modest_ui_actions_compose_msg(win, NULL, NULL, NULL, NULL, NULL, NULL, FALSE);
904 }
905
906
907 gboolean
908 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
909                                        TnyHeader *header,
910                                        TnyMsg *msg)
911 {
912         ModestMailOperationStatus status;
913
914         /* If there is no message or the operation was not successful */
915         status = modest_mail_operation_get_status (mail_op);
916         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
917                 const GError *error;
918
919                 /* If it's a memory low issue, then show a banner */
920                 error = modest_mail_operation_get_error (mail_op);
921                 if (error && error->domain == MODEST_MAIL_OPERATION_ERROR &&
922                     error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
923                         GObject *source = modest_mail_operation_get_source (mail_op);
924                         modest_platform_run_information_dialog (GTK_IS_WINDOW (source) ? GTK_WINDOW (source) : NULL,
925                                                                 _KR("memr_ib_operation_disabled"),
926                                                                 TRUE);
927                         g_object_unref (source);
928                 }
929
930                 if (error && ((error->code == TNY_SERVICE_ERROR_NO_SUCH_MESSAGE) ||
931                               error->code == TNY_SERVICE_ERROR_MESSAGE_NOT_AVAILABLE)) {
932                         gchar *subject, *msg, *format = NULL;
933                         TnyAccount *account;
934                         subject = tny_header_dup_subject (header);
935                         if (!subject)
936                                 subject = g_strdup (_("mail_va_no_subject"));
937
938                         account = modest_mail_operation_get_account (mail_op);
939                         if (account) {
940                                 ModestProtocol *protocol;
941                                 ModestProtocolType proto;
942                                 proto = modest_tny_account_get_protocol_type (account);
943                                 protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (), proto);
944                                 if (protocol)
945                                   format = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
946                                 g_object_unref (account);
947                         }
948
949                         if (!format)
950                                 format = g_strdup (_("emev_ni_ui_imap_message_not_available_in_server"));
951
952                         msg = g_strdup_printf (format, subject);
953                         modest_platform_run_information_dialog (NULL, msg, FALSE);
954                         g_free (msg);
955                         g_free (format);
956                         g_free (subject);
957                 }
958
959                 /* Remove the header from the preregistered uids */
960                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
961                                                      header);
962
963                 return FALSE;
964         }
965
966         return TRUE;
967 }
968
969 typedef struct {
970         guint idle_handler;
971         gchar *message;
972         GtkWidget *banner;
973 } OpenMsgBannerInfo;
974
975 typedef struct {
976         GtkTreeModel *model;
977         TnyHeader *header;
978         OpenMsgBannerInfo *banner_info;
979         GtkTreeRowReference *rowref;
980 } OpenMsgHelper;
981
982 gboolean
983 open_msg_banner_idle (gpointer userdata)
984 {
985         OpenMsgBannerInfo *banner_info = (OpenMsgBannerInfo *) userdata;
986
987         gdk_threads_enter ();
988         banner_info->idle_handler = 0;
989         banner_info->banner = modest_platform_animation_banner (NULL, NULL, banner_info->message);
990         if (banner_info->banner)
991                 g_object_ref (banner_info->banner);
992
993         gdk_threads_leave ();
994
995         return FALSE;
996 }
997
998 static GtkWidget *
999 get_header_view_from_window (ModestWindow *window)
1000 {
1001         GtkWidget *header_view;
1002
1003         if (MODEST_IS_MAIN_WINDOW (window)) {
1004                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
1005                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1006 #ifdef MODEST_TOOLKIT_HILDON2
1007         } else if (MODEST_IS_HEADER_WINDOW (window)){
1008                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window)));
1009 #endif
1010         } else {
1011                 header_view = NULL;
1012         }
1013
1014         return header_view;
1015 }
1016
1017 static gchar *
1018 get_info_from_header (TnyHeader *header, gboolean *is_draft, gboolean *can_open)
1019 {
1020         TnyFolder *folder;
1021         gchar *account = NULL;
1022         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
1023
1024         *is_draft = FALSE;
1025         *can_open = TRUE;
1026
1027         folder = tny_header_get_folder (header);
1028         /* Gets folder type (OUTBOX headers will be opened in edit window */
1029         if (modest_tny_folder_is_local_folder (folder)) {
1030                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1031                 if (folder_type == TNY_FOLDER_TYPE_INVALID)
1032                         g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1033         }
1034
1035         if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
1036                 TnyTransportAccount *traccount = NULL;
1037                 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
1038                 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
1039                 if (traccount) {
1040                         ModestTnySendQueue *send_queue = NULL;
1041                         ModestTnySendQueueStatus status;
1042                         gchar *msg_id;
1043                         account = g_strdup(modest_tny_account_get_parent_modest_account_name_for_server_account(
1044                                                    TNY_ACCOUNT(traccount)));
1045                         send_queue = modest_runtime_get_send_queue(traccount, TRUE);
1046                         if (TNY_IS_SEND_QUEUE (send_queue)) {
1047                                 msg_id = modest_tny_send_queue_get_msg_id (header);
1048                                 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
1049                                 g_free (msg_id);
1050                                 /* Only open messages in outbox with the editor if they are in Failed state */
1051                                 if (status == MODEST_TNY_SEND_QUEUE_FAILED) {
1052                                         *is_draft = TRUE;
1053                                 }
1054 #ifdef MODEST_TOOLKIT_HILDON2
1055                                 else {
1056                                         /* In Fremantle we can not
1057                                            open any message from
1058                                            outbox which is not in
1059                                            failed state */
1060                                         *can_open = FALSE;
1061                                 }
1062 #endif
1063                         }
1064                         g_object_unref(traccount);
1065                 } else {
1066                         g_warning("Cannot get transport account for message in outbox!!");
1067                 }
1068         } else if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
1069                 *is_draft = TRUE; /* Open in editor if the message is in the Drafts folder */
1070         }
1071
1072         if (!account) {
1073                 TnyAccount *acc = tny_folder_get_account (folder);
1074                 if (acc) {
1075                         account =
1076                                 g_strdup (modest_tny_account_get_parent_modest_account_name_for_server_account (acc));
1077                         g_object_unref (acc);
1078                 }
1079         }
1080
1081         g_object_unref (folder);
1082
1083         return account;
1084 }
1085
1086 static void
1087 open_msg_cb (ModestMailOperation *mail_op,
1088              TnyHeader *header,
1089              gboolean canceled,
1090              TnyMsg *msg,
1091              GError *err,
1092              gpointer user_data)
1093 {
1094         ModestWindowMgr *mgr = NULL;
1095         ModestWindow *parent_win = NULL;
1096         ModestWindow *win = NULL;
1097         gchar *account = NULL;
1098         gboolean open_in_editor = FALSE;
1099         gboolean can_open;
1100         OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
1101
1102         /* Do nothing if there was any problem with the mail
1103            operation. The error will be shown by the error_handler of
1104            the mail operation */
1105         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1106                 return;
1107
1108         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
1109
1110         /* Mark header as read */
1111         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
1112
1113         account = get_info_from_header (header, &open_in_editor, &can_open);
1114
1115         /* Get account */
1116         if (!account)
1117                 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
1118         if (!account)
1119                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1120
1121         if (open_in_editor) {
1122                 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
1123                 gchar *from_header = NULL, *acc_name;
1124                 gchar *mailbox = NULL;
1125
1126                 from_header = tny_header_dup_from (header);
1127
1128                 /* we cannot edit without a valid account... */
1129                 if (!modest_account_mgr_has_accounts(mgr, TRUE)) {
1130                         if (!modest_ui_actions_run_account_setup_wizard(parent_win)) {
1131                                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1132                                                                      header);
1133                                 g_free (from_header);
1134                                 goto cleanup;
1135                         }
1136                 }
1137
1138                 acc_name = modest_utils_get_account_name_from_recipient (from_header, &mailbox);
1139                 g_free (from_header);
1140                 if (acc_name) {
1141                         g_free (account);
1142                         account = acc_name;
1143                 }
1144
1145                 win = modest_msg_edit_window_new (msg, account, mailbox, TRUE);
1146                 if (mailbox)
1147                         g_free (mailbox);
1148         } else {
1149                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
1150                 const gchar *mailbox = NULL;
1151
1152                 if (parent_win && MODEST_IS_WINDOW (parent_win))
1153                         mailbox = modest_window_get_active_mailbox (MODEST_WINDOW (parent_win));
1154
1155                 if (helper->rowref && helper->model) {
1156                         win = modest_msg_view_window_new_with_header_model (msg, account, mailbox, (const gchar*) uid,
1157                                                                             helper->model, helper->rowref);
1158                 } else {
1159                         win = modest_msg_view_window_new_for_attachment (msg, account, mailbox, (const gchar*) uid);
1160                 }
1161                 g_free (uid);
1162         }
1163
1164         /* Register and show new window */
1165         if (win != NULL) {
1166                 mgr = modest_runtime_get_window_mgr ();
1167                 if (!modest_window_mgr_register_window (mgr, win, NULL)) {
1168                         gtk_widget_destroy (GTK_WIDGET (win));
1169                         goto cleanup;
1170                 }
1171                 gtk_widget_show_all (GTK_WIDGET(win));
1172         }
1173
1174         /* Update toolbar dimming state */
1175         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
1176                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
1177         }
1178
1179 cleanup:
1180         /* Free */
1181         g_free(account);
1182         g_object_unref (parent_win);
1183 }
1184
1185 static gboolean
1186 is_memory_full_error (GError *error, ModestMailOperation *mail_op)
1187 {
1188         gboolean enough_free_space = TRUE;
1189         GnomeVFSURI *cache_dir_uri;
1190         const gchar *cache_dir = NULL;
1191         GnomeVFSFileSize free_space;
1192         TnyAccountStore *acc_store;
1193
1194         acc_store = TNY_ACCOUNT_STORE (modest_runtime_get_account_store ());
1195
1196         /* Cache dir is different in case we're using an external storage (like MMC account) */
1197         if (mail_op) {
1198                 TnyAccount *account = modest_mail_operation_get_account (mail_op);
1199                 if (account) {
1200                         if (modest_tny_account_is_memory_card_account (account)) {
1201                                 cache_dir = g_getenv (MODEST_MMC1_VOLUMEPATH_ENV);
1202                         }
1203                         g_object_unref (account);
1204                 }
1205         }
1206
1207         /* Get the default local cache dir */
1208         if (!cache_dir)
1209                 cache_dir = tny_account_store_get_cache_dir (acc_store);
1210
1211         cache_dir_uri = gnome_vfs_uri_new (cache_dir);
1212         if (cache_dir_uri) {
1213                 if (gnome_vfs_get_volume_free_space (cache_dir_uri, &free_space) == GNOME_VFS_OK) {
1214                         if (free_space < MIN_FREE_SPACE)
1215                                 enough_free_space = FALSE;
1216                 }
1217                 gnome_vfs_uri_unref (cache_dir_uri);
1218         }
1219
1220         if ((error->code == TNY_SYSTEM_ERROR_MEMORY ||
1221              /* When asking for a mail and no space left on device
1222                 tinymail returns this error */
1223              error->code == TNY_SERVICE_ERROR_MESSAGE_NOT_AVAILABLE ||
1224              /* When the folder summary could not be read or
1225                 written */
1226              error->code == TNY_IO_ERROR_WRITE ||
1227              error->code == TNY_IO_ERROR_READ) &&
1228             !enough_free_space) {
1229                 return TRUE;
1230         } else {
1231                 return FALSE;
1232         }
1233 }
1234
1235 static gboolean
1236 check_memory_full_error (GtkWidget *parent_window, GError *err)
1237 {
1238         if (err == NULL)
1239                 return FALSE;
1240
1241         if (is_memory_full_error (err, NULL)) {
1242                 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
1243                 modest_platform_information_banner (parent_window, NULL, msg);
1244                 g_free (msg);
1245         } else if (err->code == TNY_SYSTEM_ERROR_MEMORY)
1246                 /* If the account was created in memory full
1247                    conditions then tinymail won't be able to
1248                    connect so it'll return this error code */
1249                 modest_platform_information_banner (parent_window,
1250                                                     NULL, _("emev_ui_imap_inbox_select_error"));
1251         else
1252                 return FALSE;
1253
1254         return TRUE;
1255 }
1256
1257 void
1258 modest_ui_actions_disk_operations_error_handler (ModestMailOperation *mail_op,
1259                                                  gpointer user_data)
1260 {
1261         const GError *error;
1262         GObject *win = NULL;
1263         ModestMailOperationStatus status;
1264
1265         win = modest_mail_operation_get_source (mail_op);
1266         error = modest_mail_operation_get_error (mail_op);
1267         status = modest_mail_operation_get_status (mail_op);
1268
1269         /* If the mail op has been cancelled then it's not an error:
1270            don't show any message */
1271         if (status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
1272                 if (is_memory_full_error ((GError *) error, mail_op)) {
1273                         gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
1274                         modest_platform_information_banner ((GtkWidget *) win, NULL, msg);
1275                         g_free (msg);
1276                 } else if (error->code == TNY_SYSTEM_ERROR_MEMORY) {
1277                         modest_platform_information_banner ((GtkWidget *) win,
1278                                                             NULL, _("emev_ui_imap_inbox_select_error"));
1279                 } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
1280                            error->code == MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
1281                         modest_platform_information_banner ((GtkWidget *) win,
1282                                                             NULL, _CS ("sfil_ni_unable_to_open_file_not_found"));
1283                 } else if (user_data) {
1284                         modest_platform_information_banner ((GtkWidget *) win,
1285                                                             NULL, user_data);
1286                 }
1287         }
1288
1289         if (win)
1290                 g_object_unref (win);
1291 }
1292
1293 /**
1294  * Returns the account a list of headers belongs to. It returns a
1295  * *new* reference so don't forget to unref it
1296  */
1297 static TnyAccount*
1298 get_account_from_header_list (TnyList *headers)
1299 {
1300         TnyAccount *account = NULL;
1301
1302         if (tny_list_get_length (headers) > 0) {
1303                 TnyIterator *iter = tny_list_create_iterator (headers);
1304                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1305                 TnyFolder *folder = tny_header_get_folder (header);
1306
1307                 if (!folder) {
1308                         g_object_unref (header);
1309
1310                         while (!tny_iterator_is_done (iter)) {
1311                                 header = TNY_HEADER (tny_iterator_get_current (iter));
1312                                 folder = tny_header_get_folder (header);
1313                                 if (folder)
1314                                         break;
1315                                 g_object_unref (header);
1316                                 header = NULL;
1317                                 tny_iterator_next (iter);
1318                         }
1319                 }
1320
1321                 if (folder) {
1322                         account = tny_folder_get_account (folder);
1323                         g_object_unref (folder);
1324                 }
1325
1326                 if (header)
1327                         g_object_unref (header);
1328
1329                 g_object_unref (iter);
1330         }
1331         return account;
1332 }
1333
1334 static TnyAccount*
1335 get_account_from_header (TnyHeader *header)
1336 {
1337         TnyAccount *account = NULL;
1338         TnyFolder *folder;
1339
1340         folder = tny_header_get_folder (header);
1341
1342         if (folder) {
1343                 account = tny_folder_get_account (folder);
1344                 g_object_unref (folder);
1345         }
1346         return account;
1347 }
1348
1349 static void
1350 open_msg_helper_destroyer (gpointer user_data)
1351 {
1352         OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
1353
1354         if (helper->banner_info) {
1355                 g_free (helper->banner_info->message);
1356                 if (helper->banner_info->idle_handler > 0) {
1357                         g_source_remove (helper->banner_info->idle_handler);
1358                         helper->banner_info->idle_handler = 0;
1359                 }
1360                 if (helper->banner_info->banner != NULL) {
1361                         gtk_widget_destroy (helper->banner_info->banner);
1362                         g_object_unref (helper->banner_info->banner);
1363                         helper->banner_info->banner = NULL;
1364                 }
1365                 g_slice_free (OpenMsgBannerInfo, helper->banner_info);
1366                 helper->banner_info = NULL;
1367         }
1368         g_object_unref (helper->model);
1369         g_object_unref (helper->header);
1370         gtk_tree_row_reference_free (helper->rowref);
1371         g_slice_free (OpenMsgHelper, helper);
1372 }
1373
1374 static void
1375 open_msg_performer(gboolean canceled,
1376                     GError *err,
1377                     GtkWindow *parent_window,
1378                     TnyAccount *account,
1379                     gpointer user_data)
1380 {
1381         ModestMailOperation *mail_op = NULL;
1382         gchar *error_msg = NULL;
1383         ModestProtocolType proto;
1384         TnyConnectionStatus status;
1385         OpenMsgHelper *helper = NULL;
1386         ModestProtocol *protocol;
1387         ModestProtocolRegistry *protocol_registry;
1388         gchar *subject;
1389
1390         helper = (OpenMsgHelper *) user_data;
1391
1392         status = tny_account_get_connection_status (account);
1393         if (err || canceled) {
1394                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (), helper->header);
1395                 /* Free the helper */
1396                 open_msg_helper_destroyer (helper);
1397
1398                 /* In memory full conditions we could get this error here */
1399                 check_memory_full_error ((GtkWidget *) parent_window, err);
1400
1401                 goto clean;
1402         }
1403
1404         /* Get the error message depending on the protocol */
1405         proto = modest_tny_account_get_protocol_type (account);
1406         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
1407                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
1408         }
1409
1410         protocol_registry = modest_runtime_get_protocol_registry ();
1411         subject = tny_header_dup_subject (helper->header);
1412
1413         protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, proto);
1414         error_msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
1415         if (subject)
1416                 g_free (subject);
1417
1418         if (error_msg == NULL) {
1419                 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1420         }
1421
1422 #ifndef MODEST_TOOLKIT_HILDON2
1423         gboolean show_open_draft = FALSE;
1424         if (modest_protocol_registry_protocol_type_has_tag (protocol_registry,
1425                                                             proto,
1426                                                             MODEST_PROTOCOL_REGISTRY_LOCAL_STORE_PROTOCOLS)) {
1427                 TnyFolder *folder;
1428                 TnyFolderType folder_type;
1429
1430                 folder = tny_header_get_folder (helper->header);
1431                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1432                 show_open_draft = (folder_type == TNY_FOLDER_TYPE_DRAFTS);
1433                 g_object_unref (folder);
1434         }
1435 #endif
1436
1437 #ifdef MODEST_TOOLKIT_HILDON2
1438         gboolean is_draft;
1439         gboolean can_open;
1440         gchar *account_name = get_info_from_header (helper->header, &is_draft, &can_open);
1441
1442         if (!can_open) {
1443                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (), helper->header);
1444                 g_free (account_name);
1445                 open_msg_helper_destroyer (helper);
1446                 goto clean;
1447         }
1448
1449         if (!is_draft) {
1450                 ModestWindow *window;
1451                 GtkWidget *header_view;
1452                 gchar *uid;
1453
1454                 header_view = get_header_view_from_window (MODEST_WINDOW (parent_window));
1455                 uid = modest_tny_folder_get_header_unique_id (helper->header);
1456                 if (header_view) {
1457                         const gchar *mailbox = NULL;
1458                         mailbox = modest_window_get_active_mailbox (MODEST_WINDOW (parent_window));
1459                         window = modest_msg_view_window_new_from_header_view 
1460                                 (MODEST_HEADER_VIEW (header_view), account_name, mailbox, uid, helper->rowref);
1461                         if (window != NULL) {
1462                                 if (!modest_window_mgr_register_window (modest_runtime_get_window_mgr (),
1463                                                                         window, NULL)) {
1464                                         gtk_widget_destroy (GTK_WIDGET (window));
1465                                 } else {
1466                                         gtk_widget_show_all (GTK_WIDGET(window));
1467                                 }
1468                         }
1469                 }
1470                 g_free (account_name);
1471                 g_free (uid);
1472                 open_msg_helper_destroyer (helper);
1473                 goto clean;
1474         }
1475         g_free (account_name);
1476 #endif
1477         /* Create the mail operation */
1478         mail_op =
1479                 modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
1480                                                                modest_ui_actions_disk_operations_error_handler,
1481                                                                g_strdup (error_msg), g_free);
1482         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1483                                          mail_op);
1484
1485
1486 #ifndef MODEST_TOOLKIT_HILDON2
1487         if (show_open_draft) {
1488                 helper->banner_info = g_slice_new (OpenMsgBannerInfo);
1489                 helper->banner_info->message = g_strdup (_("mail_ib_opening_draft_message"));
1490                 helper->banner_info->banner = NULL;
1491                 helper->banner_info->idle_handler = g_timeout_add (500, open_msg_banner_idle,
1492                                                                    helper->banner_info);
1493         }
1494 #endif
1495
1496
1497         TnyList *headers;
1498         headers = TNY_LIST (tny_simple_list_new ());
1499         tny_list_prepend (headers, G_OBJECT (helper->header));
1500         modest_mail_operation_get_msgs_full (mail_op,
1501                                              headers,
1502                                              open_msg_cb,
1503                                              helper,
1504                                              open_msg_helper_destroyer);
1505         g_object_unref (headers);
1506
1507         /* Frees */
1508  clean:
1509         if (error_msg)
1510                 g_free (error_msg);
1511         if (mail_op)
1512                 g_object_unref (mail_op);
1513         g_object_unref (account);
1514 }
1515
1516 /*
1517  * This function is used by both modest_ui_actions_on_open and
1518  * modest_ui_actions_on_header_activated. This way we always do the
1519  * same when trying to open messages.
1520  */
1521 static void
1522 open_msg_from_header (TnyHeader *header, GtkTreeRowReference *rowref, ModestWindow *win)
1523 {
1524         ModestWindowMgr *mgr = NULL;
1525         TnyAccount *account;
1526         gboolean cached = FALSE;
1527         gboolean found;
1528         GtkWidget *header_view = NULL;
1529         OpenMsgHelper *helper;
1530         ModestWindow *window;
1531
1532         g_return_if_fail (header != NULL && rowref != NULL);
1533
1534         mgr = modest_runtime_get_window_mgr ();
1535
1536         /* get model */
1537         header_view = get_header_view_from_window (MODEST_WINDOW (win));
1538         if (header_view == NULL)
1539                 return;
1540
1541         /* Get the account */
1542         account = get_account_from_header (header);
1543         if (!account)
1544                 return;
1545
1546         window = NULL;
1547         found = modest_window_mgr_find_registered_header (mgr, header, &window);
1548
1549         /* Do not open again the message and present the
1550            window to the user */
1551         if (found) {
1552                 if (window) {
1553 #ifndef MODEST_TOOLKIT_HILDON2
1554                         gtk_window_present (GTK_WINDOW (window));
1555 #endif
1556                 } else {
1557                         /* the header has been registered already, we don't do
1558                          * anything but wait for the window to come up*/
1559                         g_debug ("header %p already registered, waiting for window", header);
1560                 }
1561                 goto cleanup;
1562         }
1563
1564         /* Open each message */
1565         cached = tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED;
1566         if (!cached) {
1567                 /* Allways download if we are online. */
1568                 if (!tny_device_is_online (modest_runtime_get_device ())) {
1569                         gint response;
1570
1571                         /* If ask for user permission to download the messages */
1572                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1573                                                                             _("mcen_nc_get_msg"));
1574
1575                         /* End if the user does not want to continue */
1576                         if (response == GTK_RESPONSE_CANCEL) {
1577                                 goto cleanup;
1578                         }
1579                 }
1580         }
1581
1582         /* We register the window for opening */
1583         modest_window_mgr_register_header (mgr, header, NULL);
1584
1585         /* Create the helper. We need to get a reference to the model
1586            here because it could change while the message is readed
1587            (the user could switch between folders) */
1588         helper = g_slice_new (OpenMsgHelper);
1589         helper->model = g_object_ref (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)));
1590         helper->header = g_object_ref (header);
1591         helper->rowref = gtk_tree_row_reference_copy (rowref);
1592         helper->banner_info = NULL;
1593
1594         /* Connect to the account and perform */
1595         if (!cached) {
1596                 modest_platform_connect_and_perform ((GtkWindow *) win, TRUE, g_object_ref (account),
1597                                                      open_msg_performer, helper);
1598         } else {
1599                 /* Call directly the performer, do not need to connect */
1600                 open_msg_performer (FALSE, NULL, (GtkWindow *) win,
1601                                     g_object_ref (account), helper);
1602         }
1603 cleanup:
1604         /* Clean */
1605         if (account)
1606                 g_object_unref (account);
1607 }
1608
1609 void
1610 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1611 {
1612         TnyList *headers;
1613         TnyHeader *header;
1614         gint headers_count;
1615         TnyIterator *iter;
1616
1617         /* we check for low-mem; in that case, show a warning, and don't allow
1618          * opening
1619          */
1620         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
1621                 return;
1622
1623         /* Get headers */
1624         headers = get_selected_headers (win);
1625         if (!headers)
1626                 return;
1627
1628         headers_count = tny_list_get_length (headers);
1629         if (headers_count != 1) {
1630                 if (headers_count > 1) {
1631                         /* Don't allow activation if there are more than one message selected */
1632                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
1633                 }
1634
1635                 g_object_unref (headers);
1636                 return;
1637         }
1638
1639         iter = tny_list_create_iterator (headers);
1640         header = TNY_HEADER (tny_iterator_get_current (iter));
1641         g_object_unref (iter);
1642
1643         /* Open them */
1644         if (header) {
1645                 open_msg_from_header (header, NULL, win);
1646                 g_object_unref (header);
1647         }
1648
1649         g_object_unref(headers);
1650 }
1651
1652 static void
1653 rf_helper_window_closed (gpointer data,
1654                          GObject *object)
1655 {
1656         ReplyForwardHelper *helper = (ReplyForwardHelper *) data;
1657
1658         helper->parent_window = NULL;
1659 }
1660
1661 static ReplyForwardHelper*
1662 create_reply_forward_helper (ReplyForwardAction action,
1663                              ModestWindow *win,
1664                              guint reply_forward_type,
1665                              TnyHeader *header)
1666 {
1667         ReplyForwardHelper *rf_helper = NULL;
1668         const gchar *active_acc = modest_window_get_active_account (win);
1669         const gchar *active_mailbox = modest_window_get_active_mailbox (win);
1670
1671         rf_helper = g_slice_new0 (ReplyForwardHelper);
1672         rf_helper->reply_forward_type = reply_forward_type;
1673         rf_helper->action = action;
1674         rf_helper->parent_window = (MODEST_IS_WINDOW (win)) ? GTK_WIDGET (win) : NULL;
1675         rf_helper->header = (header) ? g_object_ref (header) : NULL;
1676         rf_helper->account_name = (active_acc) ?
1677                 g_strdup (active_acc) :
1678                 modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1679         rf_helper->mailbox = g_strdup (active_mailbox);
1680
1681         /* Note that window could be destroyed just AFTER calling
1682            register_window so we must ensure that this pointer does
1683            not hold invalid references */
1684         if (rf_helper->parent_window)
1685                 g_object_weak_ref (G_OBJECT (rf_helper->parent_window),
1686                                    rf_helper_window_closed, rf_helper);
1687
1688         return rf_helper;
1689 }
1690
1691 static void
1692 free_reply_forward_helper (gpointer data)
1693 {
1694         ReplyForwardHelper *helper;
1695
1696         helper = (ReplyForwardHelper *) data;
1697         g_free (helper->account_name);
1698         g_free (helper->mailbox);
1699         if (helper->header)
1700                 g_object_unref (helper->header);
1701         if (helper->parent_window)
1702                 g_object_weak_unref (G_OBJECT (helper->parent_window),
1703                                      rf_helper_window_closed, helper);
1704         g_slice_free (ReplyForwardHelper, helper);
1705 }
1706
1707 static void
1708 reply_forward_cb (ModestMailOperation *mail_op,
1709                   TnyHeader *header,
1710                   gboolean canceled,
1711                   TnyMsg *msg,
1712                   GError *err,
1713                   gpointer user_data)
1714 {
1715         TnyMsg *new_msg = NULL;
1716         ReplyForwardHelper *rf_helper;
1717         ModestWindow *msg_win = NULL;
1718         ModestEditType edit_type;
1719         gchar *from = NULL;
1720         TnyAccount *account = NULL;
1721         ModestWindowMgr *mgr = NULL;
1722         gchar *signature = NULL;
1723         gboolean use_signature;
1724         gchar *recipient;
1725
1726         /* If there was any error. The mail operation could be NULL,
1727            this means that we already have the message downloaded and
1728            that we didn't do a mail operation to retrieve it */
1729         rf_helper = (ReplyForwardHelper *) user_data;
1730         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1731                 goto cleanup;
1732
1733         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1734                                                    rf_helper->account_name, rf_helper->mailbox);
1735         recipient = modest_text_utils_get_email_address (from);
1736         signature = modest_account_mgr_get_signature_from_recipient (modest_runtime_get_account_mgr(), 
1737                                                                      recipient, 
1738                                                                      &use_signature);
1739         g_free (recipient);
1740
1741         /* Create reply mail */
1742         switch (rf_helper->action) {
1743         case ACTION_REPLY:
1744                 new_msg =
1745                         modest_tny_msg_create_reply_msg (msg, header, from,
1746                                                          (use_signature) ? signature : NULL,
1747                                                          rf_helper->reply_forward_type,
1748                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1749                 break;
1750         case ACTION_REPLY_TO_ALL:
1751                 new_msg =
1752                         modest_tny_msg_create_reply_msg (msg, header, from,
1753                                                          (use_signature) ? signature : NULL,
1754                                                          rf_helper->reply_forward_type,
1755                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1756                 edit_type = MODEST_EDIT_TYPE_REPLY;
1757                 break;
1758         case ACTION_FORWARD:
1759                 new_msg =
1760                         modest_tny_msg_create_forward_msg (msg, from, (use_signature) ? signature : NULL,
1761                                                            rf_helper->reply_forward_type);
1762                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1763                 break;
1764         default:
1765                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1766                                                      header);
1767                 g_return_if_reached ();
1768                 return;
1769         }
1770
1771         g_free (from);
1772         g_free (signature);
1773
1774         if (!new_msg) {
1775                 g_warning ("%s: failed to create message\n", __FUNCTION__);
1776                 goto cleanup;
1777         }
1778
1779         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1780                                                                        rf_helper->account_name,
1781                                                                        TNY_ACCOUNT_TYPE_STORE);
1782         if (!account) {
1783                 g_warning ("%s: failed to get tnyaccount for '%s'\n", __FUNCTION__, rf_helper->account_name);
1784                 goto cleanup;
1785         }
1786
1787         /* Create and register the windows */
1788         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, rf_helper->mailbox, FALSE);
1789         mgr = modest_runtime_get_window_mgr ();
1790         modest_window_mgr_register_window (mgr, msg_win, (ModestWindow *) rf_helper->parent_window);
1791
1792         /* Note that register_window could have deleted the account */
1793         if (MODEST_IS_WINDOW (rf_helper->parent_window)) {
1794                 gdouble parent_zoom;
1795
1796                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1797                 modest_window_set_zoom (msg_win, parent_zoom);
1798         }
1799
1800         /* Show edit window */
1801         gtk_widget_show_all (GTK_WIDGET (msg_win));
1802
1803 cleanup:
1804         /* We always unregister the header because the message is
1805            forwarded or replied so the original one is no longer
1806            opened */
1807         modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1808                                              header);
1809         if (new_msg)
1810                 g_object_unref (G_OBJECT (new_msg));
1811         if (account)
1812                 g_object_unref (G_OBJECT (account));
1813         free_reply_forward_helper (rf_helper);
1814 }
1815
1816 /* Checks a list of headers. If any of them are not currently
1817  * downloaded (CACHED) then returns TRUE else returns FALSE.
1818  */
1819 static gint
1820 header_list_count_uncached_msgs (TnyList *header_list)
1821 {
1822         TnyIterator *iter;
1823         gint uncached_messages = 0;
1824
1825         iter = tny_list_create_iterator (header_list);
1826         while (!tny_iterator_is_done (iter)) {
1827                 TnyHeader *header;
1828
1829                 header = TNY_HEADER (tny_iterator_get_current (iter));
1830                 if (header) {
1831                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1832                                 uncached_messages ++;
1833                         g_object_unref (header);
1834                 }
1835
1836                 tny_iterator_next (iter);
1837         }
1838         g_object_unref (iter);
1839
1840         return uncached_messages;
1841 }
1842
1843 /* Returns FALSE if the user does not want to download the
1844  * messages. Returns TRUE if the user allowed the download.
1845  */
1846 static gboolean
1847 connect_to_get_msg (ModestWindow *win,
1848                     gint num_of_uncached_msgs,
1849                     TnyAccount *account)
1850 {
1851         GtkResponseType response;
1852
1853         /* Allways download if we are online. */
1854         if (tny_device_is_online (modest_runtime_get_device ()))
1855                 return TRUE;
1856
1857         /* If offline, then ask for user permission to download the messages */
1858         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1859                         ngettext("mcen_nc_get_msg",
1860                         "mcen_nc_get_msgs",
1861                         num_of_uncached_msgs));
1862
1863         if (response == GTK_RESPONSE_CANCEL)
1864                 return FALSE;
1865
1866         return modest_platform_connect_and_wait((GtkWindow *) win, account);
1867 }
1868
1869 static void
1870 reply_forward_performer (gboolean canceled,
1871                          GError *err,
1872                          GtkWindow *parent_window,
1873                          TnyAccount *account,
1874                          gpointer user_data)
1875 {
1876         ReplyForwardHelper *rf_helper = NULL;
1877         ModestMailOperation *mail_op;
1878
1879         rf_helper = (ReplyForwardHelper *) user_data;
1880
1881         if (canceled || err) {
1882                 free_reply_forward_helper (rf_helper);
1883                 return;
1884         }
1885
1886         /* Retrieve the message */
1887         modest_window_mgr_register_header (modest_runtime_get_window_mgr (), rf_helper->header, NULL);
1888         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (parent_window),
1889                                                                  modest_ui_actions_disk_operations_error_handler,
1890                                                                  NULL, NULL);
1891         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1892         modest_mail_operation_get_msg (mail_op, rf_helper->header, TRUE, reply_forward_cb, rf_helper);
1893
1894         /* Frees */
1895         g_object_unref(mail_op);
1896 }
1897
1898 /*
1899  * Common code for the reply and forward actions
1900  */
1901 static void
1902 reply_forward (ReplyForwardAction action, ModestWindow *win)
1903 {
1904         ReplyForwardHelper *rf_helper = NULL;
1905         guint reply_forward_type;
1906
1907         g_return_if_fail (MODEST_IS_WINDOW(win));
1908
1909         /* we check for low-mem; in that case, show a warning, and don't allow
1910          * reply/forward (because it could potentially require a lot of memory */
1911         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
1912                 return;
1913
1914
1915         /* we need an account when editing */
1916         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1917                 if (!modest_ui_actions_run_account_setup_wizard (win))
1918                         return;
1919         }
1920
1921         reply_forward_type =
1922                 modest_conf_get_int (modest_runtime_get_conf (),
1923                                      (action == ACTION_FORWARD) ?
1924                                      MODEST_CONF_FORWARD_TYPE :
1925                                      MODEST_CONF_REPLY_TYPE,
1926                                      NULL);
1927
1928         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1929                 TnyMsg *msg = NULL;
1930                 TnyHeader *header = NULL;
1931                 /* Get header and message. Do not free them here, the
1932                    reply_forward_cb must do it */
1933                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1934                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
1935
1936                 if (msg && header) {
1937                         /* Create helper */
1938                         rf_helper = create_reply_forward_helper (action, win,
1939                                                                  reply_forward_type, header);
1940                         reply_forward_cb (NULL, header, FALSE, msg, NULL, rf_helper);
1941                 } else {
1942                         g_warning("%s: no message or header found in viewer\n", __FUNCTION__);
1943                 }
1944
1945                 if (msg)
1946                         g_object_unref (msg);
1947                 if (header)
1948                         g_object_unref (header);
1949         } else {
1950                 TnyHeader *header = NULL;
1951                 TnyIterator *iter;
1952                 gboolean do_retrieve = TRUE;
1953                 TnyList *header_list = NULL;
1954
1955                 header_list = get_selected_headers (win);
1956                 if (!header_list)
1957                         return;
1958                 /* Check that only one message is selected for replying */
1959                 if (tny_list_get_length (header_list) != 1) {
1960                         modest_platform_information_banner ((win) ? GTK_WIDGET (win) : NULL,
1961                                                             NULL, _("mcen_ib_select_one_message"));
1962                         g_object_unref (header_list);
1963                         return;
1964                 }
1965
1966                 /* Only reply/forward to one message */
1967                 iter = tny_list_create_iterator (header_list);
1968                 header = TNY_HEADER (tny_iterator_get_current (iter));
1969                 g_object_unref (iter);
1970
1971                 /* Retrieve messages */
1972                 do_retrieve = (action == ACTION_FORWARD) ||
1973                         (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1974
1975                 if (do_retrieve) {
1976                         TnyAccount *account = NULL;
1977                         TnyFolder *folder = NULL;
1978                         gdouble download = TRUE;
1979                         guint uncached_msgs = 0;
1980
1981                         folder = tny_header_get_folder (header);
1982                         if (!folder)
1983                                 goto do_retrieve_frees;
1984                         account = tny_folder_get_account (folder);
1985                         if (!account)
1986                                 goto do_retrieve_frees;
1987
1988                         uncached_msgs = header_list_count_uncached_msgs (header_list);
1989
1990                         if (uncached_msgs > 0) {
1991                                 /* Allways download if we are online. */
1992                                 if (!tny_device_is_online (modest_runtime_get_device ())) {
1993                                         gint response;
1994
1995                                         /* If ask for user permission to download the messages */
1996                                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1997                                                                                             ngettext("mcen_nc_get_msg",
1998                                                                                                      "mcen_nc_get_msgs",
1999                                                                                                      uncached_msgs));
2000
2001                                         /* End if the user does not want to continue */
2002                                         if (response == GTK_RESPONSE_CANCEL)
2003                                                 download = FALSE;
2004                                 }
2005                         }
2006
2007                         if (download) {
2008                                 /* Create helper */
2009                                 rf_helper = create_reply_forward_helper (action, win,
2010                                                                          reply_forward_type, header);
2011                                 if (uncached_msgs > 0) {
2012                                         modest_platform_connect_and_perform (GTK_WINDOW (win),
2013                                                                              TRUE, account,
2014                                                                              reply_forward_performer,
2015                                                                              rf_helper);
2016                                 } else {
2017                                         reply_forward_performer (FALSE, NULL, GTK_WINDOW (win),
2018                                                                  account, rf_helper);
2019                                 }
2020                         }
2021                 do_retrieve_frees:
2022                         if (account)
2023                                 g_object_unref (account);
2024                         if (folder)
2025                                 g_object_unref (folder);
2026                 } else {
2027                         reply_forward_cb (NULL, header, FALSE, NULL, NULL, rf_helper);
2028                 }
2029                 /* Frees */
2030                 g_object_unref (header_list);
2031                 g_object_unref (header);
2032         }
2033 }
2034
2035 void
2036 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
2037 {
2038         g_return_if_fail (MODEST_IS_WINDOW(win));
2039
2040         reply_forward (ACTION_REPLY, win);
2041 }
2042
2043 void
2044 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
2045 {
2046         g_return_if_fail (MODEST_IS_WINDOW(win));
2047
2048         reply_forward (ACTION_FORWARD, win);
2049 }
2050
2051 void
2052 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
2053 {
2054         g_return_if_fail (MODEST_IS_WINDOW(win));
2055
2056         reply_forward (ACTION_REPLY_TO_ALL, win);
2057 }
2058
2059 void
2060 modest_ui_actions_on_next (GtkAction *action,
2061                            ModestWindow *window)
2062 {
2063         if (MODEST_IS_MAIN_WINDOW (window)) {
2064                 GtkWidget *header_view;
2065
2066                 header_view = modest_main_window_get_child_widget (
2067                                 MODEST_MAIN_WINDOW(window),
2068                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2069                 if (!header_view)
2070                         return;
2071
2072                 modest_header_view_select_next (
2073                                 MODEST_HEADER_VIEW(header_view));
2074         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2075                 modest_msg_view_window_select_next_message (
2076                                 MODEST_MSG_VIEW_WINDOW (window));
2077         } else {
2078                 g_return_if_reached ();
2079         }
2080 }
2081
2082 void
2083 modest_ui_actions_on_prev (GtkAction *action,
2084                            ModestWindow *window)
2085 {
2086         g_return_if_fail (MODEST_IS_WINDOW(window));
2087
2088         if (MODEST_IS_MAIN_WINDOW (window)) {
2089                 GtkWidget *header_view;
2090                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
2091                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2092                 if (!header_view)
2093                         return;
2094
2095                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view));
2096         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2097                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
2098         } else {
2099                 g_return_if_reached ();
2100         }
2101 }
2102
2103 void
2104 modest_ui_actions_on_sort (GtkAction *action,
2105                            ModestWindow *window)
2106 {
2107         GtkWidget *header_view = NULL;
2108
2109         g_return_if_fail (MODEST_IS_WINDOW(window));
2110
2111         if (MODEST_IS_MAIN_WINDOW (window)) {
2112                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
2113                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2114 #ifdef MODEST_TOOLKIT_HILDON2
2115         } else if (MODEST_IS_HEADER_WINDOW (window)) {
2116                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window)));
2117 #endif
2118         }
2119
2120         if (!header_view) {
2121                 modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
2122
2123                 return;
2124         }
2125
2126         /* Show sorting dialog */
2127         modest_utils_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);
2128 }
2129
2130 static void
2131 new_messages_arrived (ModestMailOperation *self,
2132                       TnyList *new_headers,
2133                       gpointer user_data)
2134 {
2135         GObject *source;
2136         gboolean show_visual_notifications;
2137
2138         source = modest_mail_operation_get_source (self);
2139         show_visual_notifications = (source) ? FALSE : TRUE;
2140         if (source)
2141                 g_object_unref (source);
2142
2143         /* Notify new messages have been downloaded. If the
2144            send&receive was invoked by the user then do not show any
2145            visual notification, only play a sound and activate the LED
2146            (for the Maemo version) */
2147         if (TNY_IS_LIST(new_headers) && (tny_list_get_length (new_headers)) > 0)
2148                 modest_platform_on_new_headers_received (new_headers,
2149                                                          show_visual_notifications);
2150
2151 }
2152
2153 gboolean
2154 retrieve_all_messages_cb (GObject *source,
2155                           guint num_msgs,
2156                           guint retrieve_limit)
2157 {
2158         GtkWindow *window;
2159         gchar *msg;
2160         gint response;
2161
2162         window = GTK_WINDOW (source);
2163         msg = g_strdup_printf (_("mail_nc_msg_count_limit_exceeded"),
2164                                num_msgs, retrieve_limit);
2165
2166         /* Ask the user if they want to retrieve all the messages */
2167         response =
2168                 modest_platform_run_confirmation_dialog_with_buttons (window, msg,
2169                                                                       _("mcen_bd_get_all"),
2170                                                                       _("mcen_bd_newest_only"));
2171         /* Free and return */
2172         g_free (msg);
2173         return (response == GTK_RESPONSE_ACCEPT) ? TRUE : FALSE;
2174 }
2175
2176 typedef struct {
2177         TnyAccount *account;
2178         ModestWindow *win;
2179         gchar *account_name;
2180         gboolean poke_status;
2181         gboolean interactive;
2182         ModestMailOperation *mail_op;
2183 } SendReceiveInfo;
2184
2185 static void
2186 do_send_receive_performer (gboolean canceled,
2187                            GError *err,
2188                            GtkWindow *parent_window,
2189                            TnyAccount *account,
2190                            gpointer user_data)
2191 {
2192         SendReceiveInfo *info;
2193
2194         info = (SendReceiveInfo *) user_data;
2195
2196         if (err || canceled) {
2197                 /* In memory full conditions we could get this error here */
2198                 check_memory_full_error ((GtkWidget *) parent_window, err);
2199
2200                 if (info->mail_op) {
2201                         modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (),
2202                                                             info->mail_op);
2203                 }
2204                 goto clean;
2205         }
2206
2207         /* Set send/receive operation in progress */
2208         if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
2209                 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
2210         }
2211
2212         if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
2213                 g_signal_connect (G_OBJECT (info->mail_op), "operation-finished",
2214                                   G_CALLBACK (on_send_receive_finished),
2215                                   info->win);
2216
2217         /* Send & receive. */
2218         modest_mail_operation_update_account (info->mail_op, info->account_name, info->poke_status, info->interactive,
2219                                               (info->win) ? retrieve_all_messages_cb : NULL,
2220                                               new_messages_arrived, info->win);
2221
2222  clean:
2223         /* Frees */
2224         if (info->mail_op)
2225                 g_object_unref (G_OBJECT (info->mail_op));
2226         if (info->account_name)
2227                 g_free (info->account_name);
2228         if (info->win)
2229                 g_object_unref (info->win);
2230         if (info->account)
2231                 g_object_unref (info->account);
2232         g_slice_free (SendReceiveInfo, info);
2233 }
2234
2235 /*
2236  * This function performs the send & receive required actions. The
2237  * window is used to create the mail operation. Typically it should
2238  * always be the main window, but we pass it as argument in order to
2239  * be more flexible.
2240  */
2241 void
2242 modest_ui_actions_do_send_receive (const gchar *account_name,
2243                                    gboolean force_connection,
2244                                    gboolean poke_status,
2245                                    gboolean interactive,
2246                                    ModestWindow *win)
2247 {
2248         gchar *acc_name = NULL;
2249         SendReceiveInfo *info;
2250         ModestTnyAccountStore *acc_store;
2251
2252         /* If no account name was provided then get the current account, and if
2253            there is no current account then pick the default one: */
2254         if (!account_name) {
2255                 if (win)
2256                         acc_name = g_strdup (modest_window_get_active_account (win));
2257                 if (!acc_name)
2258                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
2259                 if (!acc_name) {
2260                         g_printerr ("modest: cannot get default account\n");
2261                         return;
2262                 }
2263         } else {
2264                 acc_name = g_strdup (account_name);
2265         }
2266
2267         acc_store = modest_runtime_get_account_store ();
2268
2269         /* Create the info for the connect and perform */
2270         info = g_slice_new (SendReceiveInfo);
2271         info->account_name = acc_name;
2272         info->win = (win) ? g_object_ref (win) : NULL;
2273         info->poke_status = poke_status;
2274         info->interactive = interactive;
2275         info->account = modest_tny_account_store_get_server_account (acc_store, acc_name,
2276                                                                      TNY_ACCOUNT_TYPE_STORE);
2277         /* We need to create the operation here, because otherwise it
2278            could happen that the queue emits the queue-empty signal
2279            while we're trying to connect the account */
2280         info->mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
2281                                                                        modest_ui_actions_disk_operations_error_handler,
2282                                                                        NULL, NULL);
2283         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), info->mail_op);
2284
2285         /* Invoke the connect and perform */
2286         modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL,
2287                                              force_connection, info->account,
2288                                              do_send_receive_performer, info);
2289 }
2290
2291
2292 static void
2293 modest_ui_actions_do_cancel_send (const gchar *account_name,
2294                                   ModestWindow *win)
2295 {
2296         TnyTransportAccount *transport_account;
2297         TnySendQueue *send_queue = NULL;
2298         GError *error = NULL;
2299
2300         /* Get transport account */
2301         transport_account =
2302                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2303                                       (modest_runtime_get_account_store(),
2304                                        account_name,
2305                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2306         if (!transport_account) {
2307                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2308                 goto frees;
2309         }
2310
2311         /* Get send queue*/
2312         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account, TRUE));
2313         if (!TNY_IS_SEND_QUEUE(send_queue)) {
2314                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
2315                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2316                              "modest: could not find send queue for account\n");
2317         } else {
2318                 /* Cancel the current send */
2319                 tny_account_cancel (TNY_ACCOUNT (transport_account));
2320
2321                 /* Suspend all pending messages */
2322                 tny_send_queue_cancel (send_queue, TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, &error);
2323         }
2324
2325  frees:
2326         if (transport_account != NULL)
2327                 g_object_unref (G_OBJECT (transport_account));
2328 }
2329
2330 static void
2331 modest_ui_actions_cancel_send_all (ModestWindow *win)
2332 {
2333         GSList *account_names, *iter;
2334
2335         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2336                                                           TRUE);
2337
2338         iter = account_names;
2339         while (iter) {
2340                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
2341                 iter = g_slist_next (iter);
2342         }
2343
2344         modest_account_mgr_free_account_names (account_names);
2345         account_names = NULL;
2346 }
2347
2348 void
2349 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
2350
2351 {
2352         /* Check if accounts exist */
2353         gboolean accounts_exist =
2354                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2355
2356         /* If not, allow the user to create an account before trying to send/receive. */
2357         if (!accounts_exist)
2358                 modest_ui_actions_on_accounts (NULL, win);
2359
2360         /* Cancel all sending operaitons */
2361         modest_ui_actions_cancel_send_all (win);
2362 }
2363
2364 /*
2365  * Refreshes all accounts. This function will be used by automatic
2366  * updates
2367  */
2368 void
2369 modest_ui_actions_do_send_receive_all (ModestWindow *win,
2370                                        gboolean force_connection,
2371                                        gboolean poke_status,
2372                                        gboolean interactive)
2373 {
2374         GSList *account_names, *iter;
2375
2376         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2377                                                           TRUE);
2378
2379         iter = account_names;
2380         while (iter) {
2381                 modest_ui_actions_do_send_receive ((const char*) iter->data,
2382                                                    force_connection,
2383                                                    poke_status, interactive, win);
2384                 iter = g_slist_next (iter);
2385         }
2386
2387         modest_account_mgr_free_account_names (account_names);
2388         account_names = NULL;
2389 }
2390
2391 /*
2392  * Handler of the click on Send&Receive button in the main toolbar
2393  */
2394 void
2395 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
2396 {
2397         /* Check if accounts exist */
2398         gboolean accounts_exist;
2399
2400         accounts_exist =
2401                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2402
2403         /* If not, allow the user to create an account before trying to send/receive. */
2404         if (!accounts_exist)
2405                 modest_ui_actions_on_accounts (NULL, win);
2406
2407         /* Refresh the current folder. The if is always TRUE it's just an extra check */
2408         if (MODEST_IS_MAIN_WINDOW (win)) {
2409                 GtkWidget *folder_view;
2410                 TnyFolderStore *folder_store;
2411
2412                 folder_view =
2413                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2414                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2415                 if (!folder_view)
2416                         return;
2417
2418                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2419
2420                 if (folder_store)
2421                         g_object_unref (folder_store);
2422                 /* Refresh the active account. Force the connection if needed
2423                    and poke the status of all folders */
2424                 modest_ui_actions_do_send_receive (NULL, TRUE, TRUE, TRUE, win);
2425 #ifdef MODEST_TOOLKIT_HILDON2
2426         } else if (MODEST_IS_ACCOUNTS_WINDOW (win)) {
2427                 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2428 #endif
2429         } else {
2430                 const gchar *active_account;
2431                 active_account = modest_window_get_active_account (MODEST_WINDOW (win));
2432
2433                 modest_ui_actions_do_send_receive (active_account, TRUE, TRUE, TRUE, win);
2434         }
2435
2436 }
2437
2438
2439 void
2440 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
2441 {
2442         ModestConf *conf;
2443         GtkWidget *header_view;
2444
2445         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2446
2447         header_view = modest_main_window_get_child_widget (main_window,
2448                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2449         if (!header_view)
2450                 return;
2451
2452         conf = modest_runtime_get_conf ();
2453
2454         /* what is saved/restored is depending on the style; thus; we save with
2455          * old style, then update the style, and restore for this new style
2456          */
2457         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
2458
2459         if (modest_header_view_get_style
2460             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
2461                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2462                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
2463         else
2464                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2465                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
2466
2467         modest_widget_memory_restore (conf, G_OBJECT(header_view),
2468                                       MODEST_CONF_HEADER_VIEW_KEY);
2469 }
2470
2471
2472 void
2473 modest_ui_actions_on_header_selected (ModestHeaderView *header_view,
2474                                       TnyHeader *header,
2475                                       ModestMainWindow *main_window)
2476 {
2477         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2478         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2479
2480         /* in the case the folder is empty, show the empty folder message and focus
2481          * folder view */
2482         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
2483                 if (modest_header_view_is_empty (header_view)) {
2484                         TnyFolder *folder = modest_header_view_get_folder (header_view);
2485                         GtkWidget *folder_view =
2486                                 modest_main_window_get_child_widget (main_window,
2487                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2488                         if (folder != NULL) {
2489                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
2490                                 g_object_unref (folder);
2491                         }
2492                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
2493                         return;
2494                 }
2495         }
2496         /* If no header has been selected then exit */
2497         if (!header)
2498                 return;
2499
2500         /* Update focus */
2501         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
2502             gtk_widget_grab_focus (GTK_WIDGET(header_view));
2503
2504         /* Update toolbar dimming state */
2505         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2506         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2507 }
2508
2509 void
2510 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
2511                                        TnyHeader *header,
2512                                        GtkTreePath *path,
2513                                        ModestWindow *window)
2514 {
2515         GtkWidget *open_widget;
2516         GtkTreeRowReference *rowref;
2517
2518         g_return_if_fail (MODEST_IS_WINDOW(window));
2519         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2520         g_return_if_fail (TNY_IS_HEADER (header));
2521
2522         if (modest_header_view_count_selected_headers (header_view) > 1) {
2523                 /* Don't allow activation if there are more than one message selected */
2524                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
2525                 return;
2526         }
2527
2528         /* we check for low-mem; in that case, show a warning, and don't allow
2529          * activating headers
2530          */
2531         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2532                 return;
2533
2534         if (MODEST_IS_MAIN_WINDOW (window)) {
2535                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2536                 open_widget = modest_window_get_action_widget (MODEST_WINDOW (window), "/MenuBar/EmailMenu/EmailOpenMenu");
2537                 if (!GTK_WIDGET_IS_SENSITIVE (open_widget))
2538                         return;
2539         }
2540
2541         rowref = gtk_tree_row_reference_new (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)), path);
2542         open_msg_from_header (header, rowref, MODEST_WINDOW (window));
2543         gtk_tree_row_reference_free (rowref);
2544 }
2545
2546 static void
2547 set_active_account_from_tny_account (TnyAccount *account,
2548                                      ModestWindow *window)
2549 {
2550         const gchar *server_acc_name = tny_account_get_id (account);
2551
2552         /* We need the TnyAccount provided by the
2553            account store because that is the one that
2554            knows the name of the Modest account */
2555         TnyAccount *modest_server_account =
2556                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2557                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID,
2558                                                              server_acc_name);
2559         if (!modest_server_account) {
2560                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2561                 return;
2562         }
2563
2564         /* Update active account, but only if it's not a pseudo-account */
2565         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2566             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2567                 const gchar *modest_acc_name =
2568                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2569                 if (modest_acc_name)
2570                         modest_window_set_active_account (window, modest_acc_name);
2571         }
2572
2573         g_object_unref (modest_server_account);
2574 }
2575
2576
2577 static void
2578 folder_refreshed_cb (ModestMailOperation *mail_op,
2579                      TnyFolder *folder,
2580                      gpointer user_data)
2581 {
2582         ModestMainWindow *win = NULL;
2583         GtkWidget *folder_view, *header_view;
2584         const GError *error;
2585
2586         g_return_if_fail (TNY_IS_FOLDER (folder));
2587
2588         win = MODEST_MAIN_WINDOW (user_data);
2589
2590         /* Check if the operation failed due to memory low conditions */
2591         error = modest_mail_operation_get_error (mail_op);
2592         if (error && error->domain == MODEST_MAIL_OPERATION_ERROR &&
2593             error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
2594                 modest_platform_run_information_dialog (GTK_WINDOW (win),
2595                                                         _KR("memr_ib_operation_disabled"),
2596                                                         TRUE);
2597                 return;
2598         }
2599
2600         folder_view =
2601                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2602         header_view =
2603                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2604
2605         if (folder_view) {
2606                 TnyFolderStore *current_folder;
2607
2608                 current_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2609                 if (current_folder) {
2610                         gboolean different = ((TnyFolderStore *) folder != current_folder);
2611                         g_object_unref (current_folder);
2612                         if (different)
2613                                 return;
2614                 }
2615         }
2616
2617         /* Check if folder is empty and set headers view contents style */
2618         if ((tny_folder_get_all_count (folder) == 0) ||
2619             modest_header_view_is_empty (MODEST_HEADER_VIEW (header_view)))
2620                 modest_main_window_set_contents_style (win,
2621                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2622 }
2623
2624 void
2625 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2626                                                TnyFolderStore *folder_store,
2627                                                gboolean selected,
2628                                                ModestMainWindow *main_window)
2629 {
2630         ModestConf *conf;
2631         GtkWidget *header_view;
2632
2633         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2634
2635         header_view = modest_main_window_get_child_widget(main_window,
2636                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2637         if (!header_view)
2638                 return;
2639
2640         conf = modest_runtime_get_conf ();
2641
2642         if (TNY_IS_ACCOUNT (folder_store)) {
2643                 if (selected) {
2644                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2645
2646                         /* Show account details */
2647                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2648                 }
2649         } else {
2650                 if (TNY_IS_FOLDER (folder_store) && selected) {
2651                         TnyAccount *account;
2652                         const gchar *account_name = NULL;
2653
2654                         /* Update the active account */
2655                         account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2656                         if (account) {
2657                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2658                                 account_name =
2659                                         modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2660                                 g_object_unref (account);
2661                                 account = NULL;
2662                         }
2663
2664                         /* Set the header style by default, it could
2665                            be changed later by the refresh callback to
2666                            empty */
2667                         modest_main_window_set_contents_style (main_window,
2668                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2669
2670                         /* Set folder on header view. This function
2671                            will call tny_folder_refresh_async so we
2672                            pass a callback that will be called when
2673                            finished. We use that callback to set the
2674                            empty view if there are no messages */
2675                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2676                                                        TNY_FOLDER (folder_store),
2677                                                        TRUE,
2678                                                        MODEST_WINDOW (main_window),
2679                                                        folder_refreshed_cb,
2680                                                        main_window);
2681
2682                         /* Restore configuration. We need to do this
2683                            *after* the set_folder because the widget
2684                            memory asks the header view about its
2685                            folder  */
2686                         modest_widget_memory_restore (modest_runtime_get_conf (),
2687                                                       G_OBJECT(header_view),
2688                                                       MODEST_CONF_HEADER_VIEW_KEY);
2689                 } else {
2690                         /* No need to save the header view
2691                            configuration for Maemo because it only
2692                            saves the sorting stuff and that it's
2693                            already being done by the sort
2694                            dialog. Remove it when the GNOME version
2695                            has the same behaviour */
2696 #ifdef MODEST_TOOLKIT_GTK
2697                         if (modest_main_window_get_contents_style (main_window) ==
2698                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2699                                 modest_widget_memory_save (conf, G_OBJECT (header_view),
2700                                                            MODEST_CONF_HEADER_VIEW_KEY);
2701 #endif
2702                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2703                 }
2704         }
2705
2706         /* Update dimming state */
2707         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2708         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2709 }
2710
2711 void
2712 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2713                                      ModestWindow *win)
2714 {
2715         GtkWidget *dialog;
2716         gchar *txt, *item;
2717         gboolean online;
2718
2719         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2720
2721         online = tny_device_is_online (modest_runtime_get_device());
2722
2723         if (online) {
2724                 /* already online -- the item is simply not there... */
2725                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2726                                                  GTK_DIALOG_MODAL,
2727                                                  GTK_MESSAGE_WARNING,
2728                                                  GTK_BUTTONS_NONE,
2729                                                  _("The %s you selected cannot be found"),
2730                                                  item);
2731                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2732                 gtk_dialog_run (GTK_DIALOG(dialog));
2733         } else {
2734                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2735                                                       GTK_WINDOW (win),
2736                                                       GTK_DIALOG_MODAL,
2737                                                       _("mcen_bd_dialog_cancel"),
2738                                                       GTK_RESPONSE_REJECT,
2739                                                       _("mcen_bd_dialog_ok"),
2740                                                       GTK_RESPONSE_ACCEPT,
2741                                                       NULL);
2742                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2743                                          "Do you want to get online?"), item);
2744                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
2745                                     gtk_label_new (txt), FALSE, FALSE, 0);
2746                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2747                 g_free (txt);
2748
2749                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2750                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2751                         /* TODO: Comment about why is this commented out: */
2752                         /* modest_platform_connect_and_wait (); */
2753                 }
2754         }
2755         gtk_widget_destroy (dialog);
2756 }
2757
2758 void
2759 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2760                                      ModestWindow *win)
2761 {
2762         /* g_message ("%s %s", __FUNCTION__, link); */
2763 }
2764
2765
2766 void
2767 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2768                                         ModestWindow *win)
2769 {
2770         modest_platform_activate_uri (link);
2771 }
2772
2773 void
2774 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2775                                           ModestWindow *win)
2776 {
2777         modest_platform_show_uri_popup (link);
2778 }
2779
2780 void
2781 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2782                                              ModestWindow *win)
2783 {
2784         /* we check for low-mem; in that case, show a warning, and don't allow
2785          * viewing attachments
2786          */
2787         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
2788                 return;
2789
2790         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2791 }
2792
2793 void
2794 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2795                                           const gchar *address,
2796                                           ModestWindow *win)
2797 {
2798         /* g_message ("%s %s", __FUNCTION__, address); */
2799 }
2800
2801 static void
2802 on_save_to_drafts_cb (ModestMailOperation *mail_op,
2803                       TnyMsg *saved_draft,
2804                       gpointer user_data)
2805 {
2806         ModestMsgEditWindow *edit_window;
2807
2808         /* TODO: in hildon 2 we have to dim and undim the header views while we're saving */
2809 #ifndef MODEST_TOOLKIT_HILDON2
2810         ModestMainWindow *win;
2811
2812         /* FIXME. Make the header view sensitive again. This is a
2813          * temporary hack. See modest_ui_actions_on_save_to_drafts()
2814          * for details */
2815         win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2816                                          modest_runtime_get_window_mgr(), FALSE));
2817         if (win != NULL) {
2818                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2819                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2820                 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2821         }
2822 #endif
2823
2824         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2825
2826         /* Set draft is there was no error */
2827         if (!modest_mail_operation_get_error (mail_op))
2828                 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2829
2830         g_object_unref(edit_window);
2831 }
2832
2833 static gboolean
2834 enough_space_for_message (ModestMsgEditWindow *edit_window,
2835                           MsgData *data)
2836 {
2837         TnyAccountStore *acc_store;
2838         guint64 available_disk, expected_size;
2839         gint parts_count;
2840         guint64 parts_size;
2841
2842         /* Check size */
2843         acc_store = TNY_ACCOUNT_STORE (modest_runtime_get_account_store());
2844         available_disk = modest_utils_get_available_space (NULL);
2845         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2846         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2847                                                       data->html_body,
2848                                                       parts_count,
2849                                                       parts_size);
2850
2851         /* Double check: memory full condition or message too big */
2852         if (available_disk < MIN_FREE_SPACE ||
2853             expected_size > available_disk) {
2854                 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
2855                 modest_platform_information_banner (NULL, NULL, msg);
2856                 g_free (msg);
2857
2858                 return FALSE;
2859         }
2860
2861         /*
2862          * djcb: if we're in low-memory state, we only allow for
2863          * saving messages smaller than
2864          * MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h) this
2865          * should still allow for sending anything critical...
2866          */
2867         if ((expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) &&
2868             modest_platform_check_memory_low (MODEST_WINDOW(edit_window), TRUE))
2869                 return FALSE;
2870
2871         /*
2872          * djcb: we also make sure that the attachments are smaller than the max size
2873          * this is for the case where we'd try to forward a message with attachments
2874          * bigger than our max allowed size, or sending an message from drafts which
2875          * somehow got past our checks when attaching.
2876          */
2877         if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
2878                 modest_platform_run_information_dialog (
2879                         GTK_WINDOW(edit_window),
2880                         _KR("memr_ib_operation_disabled"),
2881                         TRUE);
2882                 return FALSE;
2883         }
2884
2885         return TRUE;
2886 }
2887
2888 gboolean
2889 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2890 {
2891         TnyTransportAccount *transport_account;
2892         ModestMailOperation *mail_operation;
2893         MsgData *data;
2894         gchar *account_name;
2895         ModestAccountMgr *account_mgr;
2896         gboolean had_error = FALSE;
2897         ModestMainWindow *win = NULL;
2898
2899         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
2900
2901         data = modest_msg_edit_window_get_msg_data (edit_window);
2902
2903         /* Check size */
2904         if (!enough_space_for_message (edit_window, data)) {
2905                 modest_msg_edit_window_free_msg_data (edit_window, data);
2906                 return FALSE;
2907         }
2908
2909         account_name = g_strdup (data->account_name);
2910         account_mgr = modest_runtime_get_account_mgr();
2911         if (!account_name)
2912                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2913         if (!account_name)
2914                 account_name = modest_account_mgr_get_default_account (account_mgr);
2915         if (!account_name) {
2916                 g_printerr ("modest: no account found\n");
2917                 modest_msg_edit_window_free_msg_data (edit_window, data);
2918                 return FALSE;
2919         }
2920
2921         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2922                 account_name = g_strdup (data->account_name);
2923         }
2924
2925         transport_account =
2926                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2927                                       (modest_runtime_get_account_store (),
2928                                        account_name,
2929                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2930         if (!transport_account) {
2931                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2932                 g_free (account_name);
2933                 modest_msg_edit_window_free_msg_data (edit_window, data);
2934                 return FALSE;
2935         }
2936
2937         /* Create the mail operation */
2938         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler,
2939                                                                         NULL, NULL);
2940         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2941
2942         modest_mail_operation_save_to_drafts (mail_operation,
2943                                               transport_account,
2944                                               data->draft_msg,
2945                                               data->from,
2946                                               data->to, 
2947                                               data->cc, 
2948                                               data->bcc,
2949                                               data->subject,
2950                                               data->plain_body,
2951                                               data->html_body,
2952                                               data->attachments,
2953                                               data->images,
2954                                               data->priority_flags,
2955                                               data->references,
2956                                               data->in_reply_to,
2957                                               on_save_to_drafts_cb,
2958                                               g_object_ref(edit_window));
2959
2960 #ifdef MODEST_TOOLKIT_HILDON2
2961         /* In hildon2 we always show the information banner on saving to drafts.
2962          * It will be a system information banner in this case.
2963          */
2964         gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2965         modest_platform_information_banner (NULL, NULL, text);
2966         g_free (text);
2967 #else
2968         /* Use the main window as the parent of the banner, if the
2969            main window does not exist it won't be shown, if the parent
2970            window exists then it's properly shown. We don't use the
2971            editor window because it could be closed (save to drafts
2972            could happen after closing the window */
2973         win = (ModestMainWindow *)
2974                 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
2975         if (win) {
2976                 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2977                 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
2978                 g_free (text);
2979         }
2980 #endif
2981         modest_msg_edit_window_set_modified (edit_window, FALSE);
2982
2983         /* Frees */
2984         g_free (account_name);
2985         g_object_unref (G_OBJECT (transport_account));
2986         g_object_unref (G_OBJECT (mail_operation));
2987
2988         modest_msg_edit_window_free_msg_data (edit_window, data);
2989
2990         /* ** FIXME **
2991          * If the drafts folder is selected then make the header view
2992          * insensitive while the message is being saved to drafts
2993          * (it'll be sensitive again in on_save_to_drafts_cb()). This
2994          * is not very clean but it avoids letting the drafts folder
2995          * in an inconsistent state: the user could edit the message
2996          * being saved and undesirable things would happen.
2997          * In the average case the user won't notice anything at
2998          * all. In the worst case (the user is editing a really big
2999          * file from Drafts) the header view will be insensitive
3000          * during the saving process (10 or 20 seconds, depending on
3001          * the message). Anyway this is just a quick workaround: once
3002          * we find a better solution it should be removed
3003          * See NB#65125 (commend #18) for details.
3004          */
3005         if (!had_error && win != NULL) {
3006                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
3007                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
3008                 if (view != NULL) {
3009                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
3010                         if (folder) {
3011                                 if (modest_tny_folder_is_local_folder(folder)) {
3012                                         TnyFolderType folder_type;
3013                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
3014                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
3015                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
3016                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3017                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
3018                                         }
3019                                 }
3020                         }
3021                         if (folder != NULL) g_object_unref(folder);
3022                 }
3023         }
3024
3025         return !had_error;
3026 }
3027
3028 /* For instance, when clicking the Send toolbar button when editing a message: */
3029 gboolean
3030 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
3031 {
3032         TnyTransportAccount *transport_account = NULL;
3033         gboolean had_error = FALSE;
3034         MsgData *data;
3035         ModestAccountMgr *account_mgr;
3036         gchar *account_name;
3037         ModestMailOperation *mail_operation;
3038
3039         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
3040
3041         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
3042                 return TRUE;
3043
3044         data = modest_msg_edit_window_get_msg_data (edit_window);
3045
3046         /* Check size */
3047         if (!enough_space_for_message (edit_window, data)) {
3048                 modest_msg_edit_window_free_msg_data (edit_window, data);
3049                 return FALSE;
3050         }
3051
3052         account_mgr = modest_runtime_get_account_mgr();
3053         account_name = g_strdup (data->account_name);
3054         if (!account_name)
3055                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
3056
3057         if (!account_name)
3058                 account_name = modest_account_mgr_get_default_account (account_mgr);
3059
3060         if (!account_name) {
3061                 modest_msg_edit_window_free_msg_data (edit_window, data);
3062                 /* Run account setup wizard */
3063                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
3064                         return TRUE;
3065                 }
3066         }
3067
3068         /* Get the currently-active transport account for this modest account: */
3069         if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
3070                 transport_account =
3071                         TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3072                                               (modest_runtime_get_account_store (),
3073                                                account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
3074         }
3075
3076         if (!transport_account) {
3077                 modest_msg_edit_window_free_msg_data (edit_window, data);
3078                 /* Run account setup wizard */
3079                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
3080                         return TRUE;
3081         }
3082
3083
3084         /* Create the mail operation */
3085         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler, NULL, NULL);
3086         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3087
3088         modest_mail_operation_send_new_mail (mail_operation,
3089                                              transport_account,
3090                                              data->draft_msg,
3091                                              data->from,
3092                                              data->to,
3093                                              data->cc,
3094                                              data->bcc,
3095                                              data->subject,
3096                                              data->plain_body,
3097                                              data->html_body,
3098                                              data->attachments,
3099                                              data->images,
3100                                              data->references,
3101                                              data->in_reply_to,
3102                                              data->priority_flags);
3103
3104         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3105                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
3106
3107         if (modest_mail_operation_get_error (mail_operation) != NULL) {
3108                 const GError *error = modest_mail_operation_get_error (mail_operation);
3109                 if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3110                     error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
3111                         g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
3112                         modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
3113                         had_error = TRUE;
3114                 }
3115         }
3116
3117         /* Free data: */
3118         g_free (account_name);
3119         g_object_unref (G_OBJECT (transport_account));
3120         g_object_unref (G_OBJECT (mail_operation));
3121
3122         modest_msg_edit_window_free_msg_data (edit_window, data);
3123
3124         if (!had_error) {
3125                 modest_msg_edit_window_set_sent (edit_window, TRUE);
3126
3127                 /* Save settings and close the window: */
3128                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
3129         }
3130
3131         return !had_error;
3132 }
3133
3134 void
3135 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
3136                                   ModestMsgEditWindow *window)
3137 {
3138         ModestMsgEditFormatState *format_state = NULL;
3139
3140         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3141         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3142
3143         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3144                 return;
3145
3146         format_state = modest_msg_edit_window_get_format_state (window);
3147         g_return_if_fail (format_state != NULL);
3148
3149         format_state->bold = gtk_toggle_action_get_active (action);
3150         modest_msg_edit_window_set_format_state (window, format_state);
3151         g_free (format_state);
3152
3153 }
3154
3155 void
3156 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
3157                                      ModestMsgEditWindow *window)
3158 {
3159         ModestMsgEditFormatState *format_state = NULL;
3160
3161         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3162         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3163
3164         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3165                 return;
3166
3167         format_state = modest_msg_edit_window_get_format_state (window);
3168         g_return_if_fail (format_state != NULL);
3169
3170         format_state->italics = gtk_toggle_action_get_active (action);
3171         modest_msg_edit_window_set_format_state (window, format_state);
3172         g_free (format_state);
3173
3174 }
3175
3176 void
3177 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
3178                                      ModestMsgEditWindow *window)
3179 {
3180         ModestMsgEditFormatState *format_state = NULL;
3181
3182         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3183         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3184
3185         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3186                 return;
3187
3188         format_state = modest_msg_edit_window_get_format_state (window);
3189         g_return_if_fail (format_state != NULL);
3190
3191         format_state->bullet = gtk_toggle_action_get_active (action);
3192         modest_msg_edit_window_set_format_state (window, format_state);
3193         g_free (format_state);
3194
3195 }
3196
3197 void
3198 modest_ui_actions_on_change_justify (GtkRadioAction *action,
3199                                      GtkRadioAction *selected,
3200                                      ModestMsgEditWindow *window)
3201 {
3202         ModestMsgEditFormatState *format_state = NULL;
3203         GtkJustification value;
3204
3205         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3206
3207         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3208                 return;
3209
3210         value = gtk_radio_action_get_current_value (selected);
3211
3212         format_state = modest_msg_edit_window_get_format_state (window);
3213         g_return_if_fail (format_state != NULL);
3214
3215         format_state->justification = value;
3216         modest_msg_edit_window_set_format_state (window, format_state);
3217         g_free (format_state);
3218 }
3219
3220 void
3221 modest_ui_actions_on_select_editor_color (GtkAction *action,
3222                                           ModestMsgEditWindow *window)
3223 {
3224         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3225         g_return_if_fail (GTK_IS_ACTION (action));
3226
3227         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3228                 return;
3229
3230         modest_msg_edit_window_select_color (window);
3231 }
3232
3233 void
3234 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
3235                                                      ModestMsgEditWindow *window)
3236 {
3237         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3238         g_return_if_fail (GTK_IS_ACTION (action));
3239
3240         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3241                 return;
3242
3243         modest_msg_edit_window_select_background_color (window);
3244 }
3245
3246 void
3247 modest_ui_actions_on_insert_image (GObject *object,
3248                                    ModestMsgEditWindow *window)
3249 {
3250         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3251
3252
3253         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3254                 return;
3255
3256         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3257                 return;
3258
3259         modest_msg_edit_window_insert_image (window);
3260 }
3261
3262 void
3263 modest_ui_actions_on_attach_file (GtkAction *action,
3264                                   ModestMsgEditWindow *window)
3265 {
3266         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3267         g_return_if_fail (GTK_IS_ACTION (action));
3268
3269         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3270                 return;
3271
3272         modest_msg_edit_window_offer_attach_file (window);
3273 }
3274
3275 void
3276 modest_ui_actions_on_remove_attachments (GtkAction *action,
3277                                          ModestMsgEditWindow *window)
3278 {
3279         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3280
3281         modest_msg_edit_window_remove_attachments (window, NULL);
3282 }
3283
3284 static void
3285 do_create_folder_cb (ModestMailOperation *mail_op,
3286                      TnyFolderStore *parent_folder,
3287                      TnyFolder *new_folder,
3288                      gpointer user_data)
3289 {
3290         gchar *suggested_name = (gchar *) user_data;
3291         GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
3292         const GError *error;
3293
3294         error = modest_mail_operation_get_error (mail_op);
3295         if (error) {
3296
3297                 /* Show an error. If there was some problem writing to
3298                    disk, show it, otherwise show the generic folder
3299                    create error. We do it here and not in an error
3300                    handler because the call to do_create_folder will
3301                    stop the main loop in a gtk_dialog_run and then,
3302                    the message won't be shown until that dialog is
3303                    closed */
3304                 modest_ui_actions_disk_operations_error_handler (mail_op,
3305                                                                  _("mail_in_ui_folder_create_error"));
3306
3307                 if (!is_memory_full_error ((GError *) error, mail_op)) {
3308                         /* Try again if there is no full memory condition */
3309                         do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
3310                 }
3311         } else {
3312                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
3313                  * FIXME: any other? */
3314                 GtkWidget *folder_view;
3315
3316                 if (MODEST_IS_MAIN_WINDOW(source_win))
3317                         folder_view =
3318                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
3319                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3320                 else
3321                         folder_view = GTK_WIDGET(g_object_get_data (G_OBJECT (source_win),
3322                                                                     MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
3323
3324                 /* Select the newly created folder. It could happen
3325                    that the widget is no longer there (i.e. the window
3326                    has been destroyed, so we need to check this */
3327                 if (folder_view)
3328                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
3329                                                           new_folder, FALSE);
3330                 g_object_unref (new_folder);
3331         }
3332         /* Free. Note that the first time it'll be NULL so noop */
3333         g_free (suggested_name);
3334         g_object_unref (source_win);
3335 }
3336
3337 typedef struct {
3338         gchar *folder_name;
3339         TnyFolderStore *parent;
3340 } CreateFolderConnect;
3341
3342 static void
3343 do_create_folder_performer (gboolean canceled,
3344                          GError *err,
3345                          GtkWindow *parent_window,
3346                          TnyAccount *account,
3347                          gpointer user_data)
3348 {
3349         CreateFolderConnect *helper = (CreateFolderConnect *) user_data;
3350         ModestMailOperation *mail_op;
3351
3352         if (canceled || err) {
3353                 /* In memory full conditions we could get this error here */
3354                 check_memory_full_error ((GtkWidget *) parent_window, err);
3355                 goto frees;
3356         }
3357
3358         mail_op  = modest_mail_operation_new ((GObject *) parent_window);
3359         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3360                                          mail_op);
3361         modest_mail_operation_create_folder (mail_op,
3362                                              helper->parent,
3363                                              (const gchar *) helper->folder_name,
3364                                              do_create_folder_cb,
3365                                              g_strdup (helper->folder_name));
3366         g_object_unref (mail_op);
3367
3368  frees:
3369         if (helper->parent)
3370                 g_object_unref (helper->parent);
3371         if (helper->folder_name)
3372                 g_free (helper->folder_name);
3373         g_slice_free (CreateFolderConnect, helper);
3374 }
3375
3376
3377 static void
3378 do_create_folder (GtkWindow *parent_window,
3379                   TnyFolderStore *suggested_parent,
3380                   const gchar *suggested_name)
3381 {
3382         gint result;
3383         gchar *folder_name = NULL;
3384         TnyFolderStore *parent_folder = NULL;
3385
3386         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
3387                                                         suggested_parent,
3388                                                         (gchar *) suggested_name,
3389                                                         &folder_name,
3390                                                         &parent_folder);
3391
3392         if (result == GTK_RESPONSE_ACCEPT && parent_folder) {
3393                 CreateFolderConnect *helper = (CreateFolderConnect *) g_slice_new0 (CreateFolderConnect);
3394                 helper->folder_name = g_strdup (folder_name);
3395                 helper->parent = g_object_ref (parent_folder);
3396
3397                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window),
3398                                                                TRUE,
3399                                                                parent_folder,
3400                                                                do_create_folder_performer,
3401                                                                helper);
3402         }
3403
3404         if (folder_name)
3405                 g_free (folder_name);
3406         if (parent_folder)
3407                 g_object_unref (parent_folder);
3408 }
3409
3410 static void
3411 modest_ui_actions_create_folder(GtkWidget *parent_window,
3412                                 GtkWidget *folder_view)
3413 {
3414         TnyFolderStore *parent_folder;
3415
3416 #ifdef MODEST_TOOLKIT_HILDON2
3417         ModestTnyAccountStore *acc_store;
3418
3419         acc_store = modest_runtime_get_account_store ();
3420
3421         parent_folder = (TnyFolderStore *)
3422                 modest_tny_account_store_get_local_folders_account (acc_store);
3423 #else
3424         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3425 #endif
3426
3427         if (parent_folder) {
3428                 do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
3429                 g_object_unref (parent_folder);
3430         }
3431 }
3432
3433 void
3434 modest_ui_actions_on_new_folder (GtkAction *action, ModestWindow *window)
3435 {
3436
3437         g_return_if_fail (MODEST_IS_WINDOW(window));
3438
3439         if (MODEST_IS_MAIN_WINDOW (window)) {
3440                 GtkWidget *folder_view;
3441
3442                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3443                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3444                 if (!folder_view)
3445                         return;
3446
3447                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view);
3448 #ifdef MODEST_TOOLKIT_HILDON2
3449         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3450                 GtkWidget *folder_view;
3451
3452                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3453                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view);
3454 #endif
3455         } else {
3456                 g_assert_not_reached ();
3457         }
3458 }
3459
3460 static void
3461 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
3462                                                gpointer user_data)
3463 {
3464         const GError *error = NULL;
3465         gchar *message = NULL;
3466         gboolean mem_full;
3467
3468         /* Get error message */
3469         error = modest_mail_operation_get_error (mail_op);
3470         if (!error)
3471                 g_return_if_reached ();
3472
3473         mem_full = is_memory_full_error ((GError *) error, mail_op);
3474         if (mem_full) {
3475                 message = g_strdup_printf (_KR("cerm_device_memory_full"), "");
3476         } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3477                    error->code == MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS) {
3478                 message = _CS("ckdg_ib_folder_already_exists");
3479         } else if (error->domain == TNY_ERROR_DOMAIN &&
3480                    error->code == TNY_SERVICE_ERROR_STATE) {
3481                 /* This means that the folder is already in use (a
3482                    message is opened for example */
3483                 message = _("emev_ni_internal_error");
3484         } else {
3485                 message = _CS("ckdg_ib_unable_to_rename");
3486         }
3487
3488         /* We don't set a parent for the dialog because the dialog
3489            will be destroyed so the banner won't appear */
3490         modest_platform_information_banner (NULL, NULL, message);
3491
3492         if (mem_full)
3493                 g_free (message);
3494 }
3495
3496 typedef struct {
3497         TnyFolderStore *folder;
3498         gchar *new_name;
3499 } RenameFolderInfo;
3500
3501 static void
3502 on_rename_folder_cb (ModestMailOperation *mail_op,
3503                      TnyFolder *new_folder,
3504                      gpointer user_data)
3505 {
3506         ModestFolderView *folder_view;
3507
3508         /* If the window was closed when renaming a folder, or if
3509          * it's not a main window this will happen */
3510         if (!MODEST_IS_FOLDER_VIEW (user_data))
3511                 return;
3512
3513         folder_view = MODEST_FOLDER_VIEW (user_data);
3514         /* Note that if the rename fails new_folder will be NULL */
3515         if (new_folder) {
3516                 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
3517         } else {
3518                 modest_folder_view_select_first_inbox_or_local (folder_view);
3519         }
3520         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
3521 }
3522
3523 static void
3524 on_rename_folder_performer (gboolean canceled,
3525                             GError *err,
3526                             GtkWindow *parent_window,
3527                             TnyAccount *account,
3528                             gpointer user_data)
3529 {
3530         ModestMailOperation *mail_op = NULL;
3531         GtkTreeSelection *sel = NULL;
3532         GtkWidget *folder_view = NULL;
3533         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
3534
3535         if (canceled || err) {
3536                 /* In memory full conditions we could get this error here */
3537                 check_memory_full_error ((GtkWidget *) parent_window, err);
3538         } else {
3539
3540                 mail_op =
3541                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3542                                         modest_ui_actions_rename_folder_error_handler,
3543                                         parent_window, NULL);
3544
3545                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3546                                 mail_op);
3547
3548                 if (MODEST_IS_MAIN_WINDOW(parent_window)) {
3549
3550                         folder_view = modest_main_window_get_child_widget (
3551                                 MODEST_MAIN_WINDOW (parent_window),
3552                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3553                 }
3554 #ifdef MODEST_TOOLKIT_HILDON2
3555                 else if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3556                         ModestFolderWindow *folder_window = (ModestFolderWindow *) parent_window;
3557                         folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (folder_window));
3558                 }
3559 #endif
3560
3561                 /* Clear the folders view */
3562                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3563                 gtk_tree_selection_unselect_all (sel);
3564
3565                 /* Actually rename the folder */
3566                 modest_mail_operation_rename_folder (mail_op,
3567                                                      TNY_FOLDER (data->folder),
3568                                                      (const gchar *) (data->new_name),
3569                                                      on_rename_folder_cb,
3570                                                      folder_view);
3571                 g_object_unref (mail_op);
3572         }
3573
3574         g_object_unref (data->folder);
3575         g_free (data->new_name);
3576         g_free (data);
3577 }
3578
3579 void
3580 modest_ui_actions_on_rename_folder (GtkAction *action,
3581                                      ModestWindow *window)
3582 {
3583         modest_ui_actions_on_edit_mode_rename_folder (window);
3584 }
3585
3586 gboolean
3587 modest_ui_actions_on_edit_mode_rename_folder (ModestWindow *window)
3588 {
3589         TnyFolderStore *folder;
3590         GtkWidget *folder_view;
3591         gboolean do_rename = TRUE;
3592
3593         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3594
3595         if (MODEST_IS_MAIN_WINDOW (window)) {
3596                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3597                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3598                 if (!folder_view)
3599                         return FALSE;
3600
3601 #ifdef MODEST_TOOLKIT_HILDON2
3602         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3603                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3604 #endif
3605         } else {
3606                 return FALSE;
3607         }
3608
3609         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3610
3611         if (!folder)
3612                 return FALSE;
3613
3614         if (TNY_IS_FOLDER (folder)) {
3615                 gchar *folder_name = NULL;
3616                 gint response;
3617                 const gchar *current_name;
3618                 TnyFolderStore *parent;
3619
3620                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
3621                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
3622                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (window),
3623                                                                      parent, current_name,
3624                                                                      &folder_name);
3625                 g_object_unref (parent);
3626
3627                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
3628                         do_rename = FALSE;
3629                 } else {
3630                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
3631                         rename_folder_data->folder = g_object_ref (folder);
3632                         rename_folder_data->new_name = folder_name;
3633                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(window), TRUE,
3634                                         folder, on_rename_folder_performer, rename_folder_data);
3635                 }
3636         }
3637         g_object_unref (folder);
3638         return do_rename;
3639 }
3640
3641 static void
3642 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3643                                                gpointer user_data)
3644 {
3645         GObject *win = modest_mail_operation_get_source (mail_op);
3646
3647         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3648                                                 _("mail_in_ui_folder_delete_error"),
3649                                                 FALSE);
3650         g_object_unref (win);
3651 }
3652
3653 typedef struct {
3654         TnyFolderStore *folder;
3655         gboolean move_to_trash;
3656 } DeleteFolderInfo;
3657
3658 static void
3659 on_delete_folder_cb (gboolean canceled,
3660                   GError *err,
3661                   GtkWindow *parent_window,
3662                   TnyAccount *account,
3663                   gpointer user_data)
3664 {
3665         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3666         GtkWidget *folder_view;
3667         ModestMailOperation *mail_op;
3668         GtkTreeSelection *sel;
3669
3670         if (!MODEST_IS_WINDOW(parent_window) || canceled || (err!=NULL)) {
3671                 g_object_unref (G_OBJECT (info->folder));
3672                 g_free (info);
3673                 return;
3674         }
3675
3676         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
3677                 folder_view = modest_main_window_get_child_widget (
3678                         MODEST_MAIN_WINDOW (parent_window),
3679                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3680 #ifdef MODEST_TOOLKIT_HILDON2
3681         } else if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3682                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (parent_window)));
3683 #endif
3684         } else {
3685                 g_object_unref (G_OBJECT (info->folder));
3686                 g_free (info);
3687                 return;
3688         }
3689
3690         /* Unselect the folder before deleting it to free the headers */
3691         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3692         gtk_tree_selection_unselect_all (sel);
3693
3694         /* Create the mail operation */
3695         mail_op =
3696                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3697                                 modest_ui_actions_delete_folder_error_handler,
3698                                 NULL, NULL);
3699
3700         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3701                         mail_op);
3702         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3703
3704         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3705
3706         g_object_unref (G_OBJECT (mail_op));
3707         g_object_unref (G_OBJECT (info->folder));
3708         g_free (info);
3709 }
3710
3711 static gboolean
3712 delete_folder (ModestWindow *window, gboolean move_to_trash)
3713 {
3714         TnyFolderStore *folder;
3715         GtkWidget *folder_view;
3716         gint response;
3717         gchar *message;
3718
3719         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3720
3721         if (MODEST_IS_MAIN_WINDOW (window)) {
3722
3723                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3724                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3725 #ifdef MODEST_TOOLKIT_HILDON2
3726         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3727                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3728 #endif
3729         } else {
3730                 return FALSE;
3731         }
3732         if (!folder_view)
3733                 return FALSE;
3734
3735         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3736
3737         if (!folder)
3738                 return FALSE;
3739
3740         /* Show an error if it's an account */
3741         if (!TNY_IS_FOLDER (folder)) {
3742                 modest_platform_run_information_dialog (GTK_WINDOW (window),
3743                                                         _("mail_in_ui_folder_delete_error"),
3744                                                         FALSE);
3745                 g_object_unref (G_OBJECT (folder));
3746                 return FALSE;
3747         }
3748
3749         /* Ask the user */
3750         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"),
3751                                     tny_folder_get_name (TNY_FOLDER (folder)));
3752         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
3753                                                             (const gchar *) message);
3754         g_free (message);
3755
3756         if (response == GTK_RESPONSE_OK) {
3757                 DeleteFolderInfo *info;
3758                 info = g_new0(DeleteFolderInfo, 1);
3759                 info->folder = folder;
3760                 info->move_to_trash = move_to_trash;
3761                 g_object_ref (G_OBJECT (info->folder));
3762                 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder));
3763                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (window),
3764                                                                TRUE,
3765                                                                TNY_FOLDER_STORE (account),
3766                                                                on_delete_folder_cb, info);
3767                 g_object_unref (account);
3768                 return TRUE;
3769         } else {
3770                 return FALSE;
3771         }
3772         g_object_unref (G_OBJECT (folder));
3773 }
3774
3775 void
3776 modest_ui_actions_on_delete_folder (GtkAction *action,
3777                                     ModestWindow *window)
3778 {
3779         modest_ui_actions_on_edit_mode_delete_folder (window);
3780 }
3781
3782 gboolean
3783 modest_ui_actions_on_edit_mode_delete_folder (ModestWindow *window)
3784 {
3785         g_return_val_if_fail (MODEST_IS_WINDOW(window), TRUE);
3786
3787         return delete_folder (window, FALSE);
3788 }
3789
3790 void
3791 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
3792 {
3793         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3794
3795         delete_folder (MODEST_WINDOW (main_window), TRUE);
3796 }
3797
3798
3799 typedef struct _PasswordDialogFields {
3800         GtkWidget *username;
3801         GtkWidget *password;
3802         GtkWidget *dialog;
3803 } PasswordDialogFields;
3804
3805 static void
3806 password_dialog_check_field (GtkEditable *editable,
3807                              PasswordDialogFields *fields)
3808 {
3809         const gchar *value;
3810         gboolean any_value_empty = FALSE;
3811
3812 #ifdef MODEST_TOOLKIT_HILDON2
3813         value = hildon_entry_get_text (HILDON_ENTRY (fields->username));
3814 #else
3815         value = gtk_entry_get_text (GTK_ENTRY (fields->username));
3816 #endif
3817         if ((value == NULL) || value[0] == '\0') {
3818                 any_value_empty = TRUE;
3819         }
3820 #ifdef MODEST_TOOLKIT_HILDON2
3821         value = hildon_entry_get_text (HILDON_ENTRY (fields->password));
3822 #else
3823         value = gtk_entry_get_text (GTK_ENTRY (fields->password));
3824 #endif
3825         if ((value == NULL) || value[0] == '\0') {
3826                 any_value_empty = TRUE;
3827         }
3828         gtk_dialog_set_response_sensitive (GTK_DIALOG (fields->dialog), GTK_RESPONSE_ACCEPT, !any_value_empty);
3829 }
3830
3831 void
3832 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
3833                                          const gchar* server_account_name,
3834                                          gchar **username,
3835                                          gchar **password,
3836                                          gboolean *cancel,
3837                                          gboolean *remember,
3838                                          ModestMainWindow *main_window)
3839 {
3840         g_return_if_fail(server_account_name);
3841         gboolean completed = FALSE;
3842         PasswordDialogFields *fields = NULL;
3843
3844         /* Initalize output parameters: */
3845         if (cancel)
3846                 *cancel = FALSE;
3847
3848         if (remember)
3849                 *remember = TRUE;
3850
3851 #ifndef MODEST_TOOLKIT_GTK
3852         /* Maemo uses a different (awkward) button order,
3853          * It should probably just use gtk_alternative_dialog_button_order ().
3854          */
3855 #ifdef MODEST_TOOLKIT_HILDON2
3856         GtkWidget *dialog =
3857                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3858                                              NULL,
3859                                              GTK_DIALOG_MODAL,
3860                                              _HL("wdgt_bd_done"),
3861                                              GTK_RESPONSE_ACCEPT,
3862                                              NULL);
3863         gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
3864                                         HILDON_MARGIN_DOUBLE);
3865 #else
3866         GtkWidget *dialog =
3867                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3868                                              NULL,
3869                                              GTK_DIALOG_MODAL,
3870                                              _("mcen_bd_dialog_ok"),
3871                                              GTK_RESPONSE_ACCEPT,
3872                                              _("mcen_bd_dialog_cancel"),
3873                                              GTK_RESPONSE_REJECT,
3874                                              NULL);
3875 #endif /* MODEST_TOOLKIT_HILDON2 */
3876 #else
3877         GtkWidget *dialog =
3878                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3879                                              NULL,
3880                                              GTK_DIALOG_MODAL,
3881                                              GTK_STOCK_CANCEL,
3882                                              GTK_RESPONSE_REJECT,
3883                                              GTK_STOCK_OK,
3884                                              GTK_RESPONSE_ACCEPT,
3885                                              NULL);
3886 #endif /* MODEST_TOOLKIT_GTK */
3887
3888         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog), NULL);
3889
3890         gchar *server_name = modest_account_mgr_get_server_account_hostname (
3891                 modest_runtime_get_account_mgr(), server_account_name);
3892         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3893                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3894                 if (cancel)
3895                         *cancel = TRUE;
3896                 gtk_widget_destroy (dialog);
3897                 return;
3898         }
3899
3900         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
3901         GtkWidget *label = gtk_label_new (txt);
3902         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3903         g_free (txt);
3904         g_free (server_name);
3905         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label,
3906                             FALSE, FALSE, 0);
3907         server_name = NULL;
3908
3909         /* username: */
3910         gchar *initial_username = modest_account_mgr_get_server_account_username (
3911                 modest_runtime_get_account_mgr(), server_account_name);
3912
3913 #ifdef MODEST_TOOLKIT_HILDON2
3914         GtkWidget *entry_username = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
3915         if (initial_username)
3916                 hildon_entry_set_text (HILDON_ENTRY (entry_username), initial_username);
3917 #else
3918         GtkWidget *entry_username = gtk_entry_new ();
3919         if (initial_username)
3920                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
3921 #endif
3922         /* Dim this if a connection has ever succeeded with this username,
3923          * as per the UI spec: */
3924         /* const gboolean username_known =  */
3925         /*      modest_account_mgr_get_server_account_username_has_succeeded( */
3926         /*              modest_runtime_get_account_mgr(), server_account_name); */
3927         /* gtk_widget_set_sensitive (entry_username, !username_known); */
3928
3929         /* We drop the username sensitive code and disallow changing it here
3930          * as tinymail does not support really changing the username in the callback
3931          */
3932         gtk_widget_set_sensitive (entry_username, FALSE);
3933
3934 #ifndef MODEST_TOOLKIT_GTK
3935         /* Auto-capitalization is the default, so let's turn it off: */
3936         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
3937
3938         /* Create a size group to be used by all captions.
3939          * Note that HildonCaption does not create a default size group if we do not specify one.
3940          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
3941         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3942
3943 #ifdef MODEST_TOOLKIT_HILDON2
3944         GtkWidget *caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
3945                                                                   _("mail_fi_username"), FALSE,
3946                                                                   entry_username);
3947 #else
3948         GtkWidget *caption = hildon_caption_new (sizegroup,
3949                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
3950 #endif
3951         gtk_widget_show (entry_username);
3952         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
3953                 FALSE, FALSE, MODEST_MARGIN_HALF);
3954         gtk_widget_show (caption);
3955 #else
3956         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
3957                             TRUE, FALSE, 0);
3958 #endif /* !MODEST_TOOLKIT_GTK */
3959
3960         /* password: */
3961 #ifdef MODEST_TOOLKIT_HILDON2
3962         GtkWidget *entry_password = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
3963 #else
3964         GtkWidget *entry_password = gtk_entry_new ();
3965 #endif
3966         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
3967         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
3968
3969 #ifndef MODEST_TOOLKIT_GTK
3970         /* Auto-capitalization is the default, so let's turn it off: */
3971         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
3972                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
3973
3974 #ifdef MODEST_TOOLKIT_HILDON2
3975         caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
3976                                                        _("mail_fi_password"), FALSE,
3977                                                        entry_password);
3978 #else
3979         caption = hildon_caption_new (sizegroup,
3980                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
3981 #endif
3982         gtk_widget_show (entry_password);
3983         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
3984                 FALSE, FALSE, MODEST_MARGIN_HALF);
3985         gtk_widget_show (caption);
3986         g_object_unref (sizegroup);
3987 #else
3988         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
3989                             TRUE, FALSE, 0);
3990 #endif /* !MODEST_TOOLKIT_GTK */
3991
3992         if (initial_username != NULL)
3993                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
3994
3995 /* This is not in the Maemo UI spec:
3996         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
3997         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
3998                             TRUE, FALSE, 0);
3999 */
4000
4001         fields = g_slice_new0 (PasswordDialogFields);
4002         fields->username = entry_username;
4003         fields->password = entry_password;
4004         fields->dialog = dialog;
4005
4006         g_signal_connect (entry_username, "changed", G_CALLBACK (password_dialog_check_field), fields);
4007         g_signal_connect (entry_password, "changed", G_CALLBACK (password_dialog_check_field), fields);
4008         password_dialog_check_field (NULL, fields);
4009
4010         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4011
4012         while (!completed) {
4013
4014                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
4015                         if (username) {
4016 #ifdef MODEST_TOOLKIT_HILDON2
4017                                 *username = g_strdup (hildon_entry_get_text (HILDON_ENTRY(entry_username)));
4018 #else
4019                                 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
4020 #endif
4021
4022                                 /* Note that an empty field becomes the "" string */
4023                                 if (*username && strlen (*username) > 0) {
4024                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(),
4025                                                                                         server_account_name,
4026                                                                                         *username);
4027                                         completed = TRUE;
4028
4029                                         const gboolean username_was_changed =
4030                                                 (strcmp (*username, initial_username) != 0);
4031                                         if (username_was_changed) {
4032                                                 g_warning ("%s: tinymail does not yet support changing the "
4033                                                            "username in the get_password() callback.\n", __FUNCTION__);
4034                                         }
4035                                 } else {
4036                                         g_free (*username);
4037                                         *username = NULL;
4038                                         /* Show error */
4039                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL,
4040                                                                             _("mcen_ib_username_pw_incorrect"));
4041                                         completed = FALSE;
4042                                 }
4043                         }
4044
4045                         if (password) {
4046 #ifdef MODEST_TOOLKIT_HILDON2
4047                                 *password = g_strdup (hildon_entry_get_text (HILDON_ENTRY(entry_password)));
4048 #else
4049                                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
4050 #endif
4051
4052                                 /* We do not save the password in the configuration,
4053                                  * because this function is only called for passwords that should
4054                                  * not be remembered:
4055                                  modest_server_account_set_password (
4056                                  modest_runtime_get_account_mgr(), server_account_name,
4057                                  *password);
4058                                  */
4059                         }
4060                         if (cancel)
4061                                 *cancel   = FALSE;
4062                 } else {
4063 #ifndef MODEST_TOOLKIT_HILDON2
4064                         /* Set parent to NULL or the banner will disappear with its parent dialog */
4065                         modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
4066 #endif
4067                         completed = TRUE;
4068                         if (username)
4069                                 *username = NULL;
4070                         if (password)
4071                                 *password = NULL;
4072                         if (cancel)
4073                                 *cancel   = TRUE;
4074                 }
4075         }
4076
4077 /* This is not in the Maemo UI spec:
4078         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
4079                 *remember = TRUE;
4080         else
4081                 *remember = FALSE;
4082 */
4083
4084         g_free (initial_username);
4085         gtk_widget_destroy (dialog);
4086         g_slice_free (PasswordDialogFields, fields);
4087
4088         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
4089 }
4090
4091 void
4092 modest_ui_actions_on_cut (GtkAction *action,
4093                           ModestWindow *window)
4094 {
4095         GtkWidget *focused_widget;
4096         GtkClipboard *clipboard;
4097
4098         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4099         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4100         if (GTK_IS_EDITABLE (focused_widget)) {
4101                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
4102                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4103                 gtk_clipboard_store (clipboard);
4104         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4105                 GtkTextBuffer *buffer;
4106
4107                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4108                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4109                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
4110                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4111                         gtk_clipboard_store (clipboard);
4112                 }
4113         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4114                 TnyList *header_list = modest_header_view_get_selected_headers (
4115                                 MODEST_HEADER_VIEW (focused_widget));
4116                 gboolean continue_download = FALSE;
4117                 gint num_of_unc_msgs;
4118
4119                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4120
4121                 if (num_of_unc_msgs) {
4122                         TnyAccount *account = get_account_from_header_list (header_list);
4123                         if (account) {
4124                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4125                                 g_object_unref (account);
4126                         }
4127                 }
4128
4129                 if (num_of_unc_msgs == 0 || continue_download) {
4130 /*                      modest_platform_information_banner (
4131                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
4132                         modest_header_view_cut_selection (
4133                                         MODEST_HEADER_VIEW (focused_widget));
4134                 }
4135
4136                 g_object_unref (header_list);
4137         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4138                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
4139         }
4140 }
4141
4142 void
4143 modest_ui_actions_on_copy (GtkAction *action,
4144                            ModestWindow *window)
4145 {
4146         GtkClipboard *clipboard;
4147         GtkWidget *focused_widget;
4148         gboolean copied = TRUE;
4149
4150         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4151         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4152
4153         if (GTK_IS_LABEL (focused_widget)) {
4154                 gchar *selection;
4155                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
4156                 gtk_clipboard_set_text (clipboard, selection, -1);
4157                 g_free (selection);
4158                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4159                 gtk_clipboard_store (clipboard);
4160         } else if (GTK_IS_EDITABLE (focused_widget)) {
4161                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
4162                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4163                 gtk_clipboard_store (clipboard);
4164         } else if (GTK_IS_HTML (focused_widget)) {
4165                 const gchar *sel;
4166                 int len = -1;
4167                 sel = gtk_html_get_selection_html (GTK_HTML (focused_widget), &len);
4168                 if ((sel == NULL) || (sel[0] == '\0')) {
4169                         copied = FALSE;
4170                 } else {
4171                         gtk_html_copy (GTK_HTML (focused_widget));
4172                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4173                         gtk_clipboard_store (clipboard);
4174                 }
4175         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4176                 GtkTextBuffer *buffer;
4177                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4178                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4179                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
4180                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4181                         gtk_clipboard_store (clipboard);
4182                 }
4183         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4184                 TnyList *header_list = modest_header_view_get_selected_headers (
4185                                 MODEST_HEADER_VIEW (focused_widget));
4186                 gboolean continue_download = FALSE;
4187                 gint num_of_unc_msgs;
4188
4189                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4190
4191                 if (num_of_unc_msgs) {
4192                         TnyAccount *account = get_account_from_header_list (header_list);
4193                         if (account) {
4194                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4195                                 g_object_unref (account);
4196                         }
4197                 }
4198
4199                 if (num_of_unc_msgs == 0 || continue_download) {
4200                         modest_platform_information_banner (
4201                                         NULL, NULL, _CS("mcen_ib_getting_items"));
4202                         modest_header_view_copy_selection (
4203                                         MODEST_HEADER_VIEW (focused_widget));
4204                 } else
4205                         copied = FALSE;
4206
4207                 g_object_unref (header_list);
4208
4209         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4210                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
4211         }
4212
4213         /* Show information banner if there was a copy to clipboard */
4214         if(copied)
4215                 modest_platform_information_banner (
4216                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
4217 }
4218
4219 void
4220 modest_ui_actions_on_undo (GtkAction *action,
4221                            ModestWindow *window)
4222 {
4223         ModestEmailClipboard *clipboard = NULL;
4224
4225         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4226                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
4227         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4228                 /* Clear clipboard source */
4229                 clipboard = modest_runtime_get_email_clipboard ();
4230                 modest_email_clipboard_clear (clipboard);
4231         }
4232         else {
4233                 g_return_if_reached ();
4234         }
4235 }
4236
4237 void
4238 modest_ui_actions_on_redo (GtkAction *action,
4239                            ModestWindow *window)
4240 {
4241         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4242                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
4243         }
4244         else {
4245                 g_return_if_reached ();
4246         }
4247 }
4248
4249
4250 static void
4251 destroy_information_note (ModestMailOperation *mail_op,
4252                           gpointer user_data)
4253 {
4254         /* destroy information note */
4255         gtk_widget_destroy (GTK_WIDGET(user_data));
4256 }
4257
4258 static void
4259 destroy_folder_information_note (ModestMailOperation *mail_op,
4260                                  TnyFolder *new_folder,
4261                                  gpointer user_data)
4262 {
4263         /* destroy information note */
4264         gtk_widget_destroy (GTK_WIDGET(user_data));
4265 }
4266
4267
4268 static void
4269 paste_as_attachment_free (gpointer data)
4270 {
4271         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
4272
4273         if (helper->banner) {
4274                 gtk_widget_destroy (helper->banner);
4275                 g_object_unref (helper->banner);
4276         }
4277         g_free (helper);
4278 }
4279
4280 static void
4281 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
4282                             TnyHeader *header,
4283                             TnyMsg *msg,
4284                             gpointer userdata)
4285 {
4286         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
4287         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
4288
4289         if (msg == NULL)
4290                 return;
4291
4292         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
4293
4294 }
4295
4296 void
4297 modest_ui_actions_on_paste (GtkAction *action,
4298                             ModestWindow *window)
4299 {
4300         GtkWidget *focused_widget = NULL;
4301         GtkWidget *inf_note = NULL;
4302         ModestMailOperation *mail_op = NULL;
4303
4304         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4305         if (GTK_IS_EDITABLE (focused_widget)) {
4306                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
4307         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4308                 ModestEmailClipboard *e_clipboard = NULL;
4309                 e_clipboard = modest_runtime_get_email_clipboard ();
4310                 if (modest_email_clipboard_cleared (e_clipboard)) {
4311                         GtkTextBuffer *buffer;
4312                         GtkClipboard *clipboard;
4313
4314                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4315                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4316                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
4317                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4318                         ModestMailOperation *mail_op;
4319                         TnyFolder *src_folder = NULL;
4320                         TnyList *data = NULL;
4321                         gboolean delete;
4322                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
4323                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
4324                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4325                                                                            _CS("ckct_nw_pasting"));
4326                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
4327                         mail_op = modest_mail_operation_new (G_OBJECT (window));
4328                         if (helper->banner != NULL) {
4329                                 g_object_ref (G_OBJECT (helper->banner));
4330                                 gtk_widget_show (GTK_WIDGET (helper->banner));
4331                         }
4332
4333                         if (data != NULL) {
4334                                 modest_mail_operation_get_msgs_full (mail_op,
4335                                                                      data,
4336                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
4337                                                                      helper,
4338                                                                      paste_as_attachment_free);
4339                         }
4340                         /* Free */
4341                         if (data)
4342                                 g_object_unref (data);
4343                         if (src_folder)
4344                                 g_object_unref (src_folder);
4345
4346                 }
4347         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4348                 ModestEmailClipboard *clipboard = NULL;
4349                 TnyFolder *src_folder = NULL;
4350                 TnyFolderStore *folder_store = NULL;
4351                 TnyList *data = NULL;
4352                 gboolean delete = FALSE;
4353
4354                 /* Check clipboard source */
4355                 clipboard = modest_runtime_get_email_clipboard ();
4356                 if (modest_email_clipboard_cleared (clipboard))
4357                         return;
4358
4359                 /* Get elements to paste */
4360                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
4361
4362                 /* Create a new mail operation */
4363                 mail_op = modest_mail_operation_new (G_OBJECT(window));
4364
4365                 /* Get destination folder */
4366                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
4367
4368                 /* transfer messages  */
4369                 if (data != NULL) {
4370                         gint response = 0;
4371
4372                         /* Ask for user confirmation */
4373                         response =
4374                                 modest_ui_actions_msgs_move_to_confirmation (window,
4375                                                                              TNY_FOLDER (folder_store),
4376                                                                              delete,
4377                                                                              data);
4378
4379                         if (response == GTK_RESPONSE_OK) {
4380                                 /* Launch notification */
4381                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4382                                                                              _CS("ckct_nw_pasting"));
4383                                 if (inf_note != NULL)  {
4384                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4385                                         gtk_widget_show (GTK_WIDGET(inf_note));
4386                                 }
4387
4388                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4389                                 modest_mail_operation_xfer_msgs (mail_op,
4390                                                                  data,
4391                                                                  TNY_FOLDER (folder_store),
4392                                                                  delete,
4393                                                                  destroy_information_note,
4394                                                                  inf_note);
4395                         } else {
4396                                 g_object_unref (mail_op);
4397                         }
4398
4399                 } else if (src_folder != NULL) {
4400                         /* Launch notification */
4401                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4402                                                                      _CS("ckct_nw_pasting"));
4403                         if (inf_note != NULL)  {
4404                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4405                                 gtk_widget_show (GTK_WIDGET(inf_note));
4406                         }
4407
4408                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4409                         modest_mail_operation_xfer_folder (mail_op,
4410                                                            src_folder,
4411                                                            folder_store,
4412                                                            delete,
4413                                                            destroy_folder_information_note,
4414                                                            inf_note);
4415                 }
4416
4417                 /* Free */
4418                 if (data != NULL)
4419                         g_object_unref (data);
4420                 if (src_folder != NULL)
4421                         g_object_unref (src_folder);
4422                 if (folder_store != NULL)
4423                         g_object_unref (folder_store);
4424         }
4425 }
4426
4427
4428 void
4429 modest_ui_actions_on_select_all (GtkAction *action,
4430                                  ModestWindow *window)
4431 {
4432         GtkWidget *focused_widget;
4433
4434         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4435         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
4436                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
4437         } else if (GTK_IS_LABEL (focused_widget)) {
4438                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
4439         } else if (GTK_IS_EDITABLE (focused_widget)) {
4440                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
4441         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4442                 GtkTextBuffer *buffer;
4443                 GtkTextIter start, end;
4444
4445                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4446                 gtk_text_buffer_get_start_iter (buffer, &start);
4447                 gtk_text_buffer_get_end_iter (buffer, &end);
4448                 gtk_text_buffer_select_range (buffer, &start, &end);
4449         } else if (GTK_IS_HTML (focused_widget)) {
4450                 gtk_html_select_all (GTK_HTML (focused_widget));
4451         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4452                 GtkWidget *header_view = focused_widget;
4453                 GtkTreeSelection *selection = NULL;
4454
4455                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
4456                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4457                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4458                 }
4459
4460                 /* Disable window dimming management */
4461                 modest_window_disable_dimming (MODEST_WINDOW(window));
4462
4463                 /* Select all messages */
4464                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
4465                 gtk_tree_selection_select_all (selection);
4466
4467                 /* Set focuse on header view */
4468                 gtk_widget_grab_focus (header_view);
4469
4470                 /* Enable window dimming management */
4471                 modest_window_enable_dimming (MODEST_WINDOW(window));
4472                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
4473                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
4474         }
4475
4476 }
4477
4478 void
4479 modest_ui_actions_on_mark_as_read (GtkAction *action,
4480                                    ModestWindow *window)
4481 {
4482         g_return_if_fail (MODEST_IS_WINDOW(window));
4483
4484         /* Mark each header as read */
4485         do_headers_action (window, headers_action_mark_as_read, NULL);
4486 }
4487
4488 void
4489 modest_ui_actions_on_mark_as_unread (GtkAction *action,
4490                                      ModestWindow *window)
4491 {
4492         g_return_if_fail (MODEST_IS_WINDOW(window));
4493
4494         /* Mark each header as read */
4495         do_headers_action (window, headers_action_mark_as_unread, NULL);
4496 }
4497
4498 void
4499 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
4500                                   GtkRadioAction *selected,
4501                                   ModestWindow *window)
4502 {
4503         gint value;
4504
4505         value = gtk_radio_action_get_current_value (selected);
4506         if (MODEST_IS_WINDOW (window)) {
4507                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
4508         }
4509 }
4510
4511 void
4512 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
4513                                                GtkRadioAction *selected,
4514                                                ModestWindow *window)
4515 {
4516         TnyHeaderFlags flags;
4517         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4518
4519         flags = gtk_radio_action_get_current_value (selected);
4520         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
4521 }
4522
4523 void
4524 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
4525                                                   GtkRadioAction *selected,
4526                                                   ModestWindow *window)
4527 {
4528         gint file_format;
4529
4530         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4531
4532         file_format = gtk_radio_action_get_current_value (selected);
4533         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
4534 }
4535
4536
4537 void
4538 modest_ui_actions_on_zoom_plus (GtkAction *action,
4539                                 ModestWindow *window)
4540 {
4541         g_return_if_fail (MODEST_IS_WINDOW (window));
4542
4543         modest_window_zoom_plus (MODEST_WINDOW (window));
4544 }
4545
4546 void
4547 modest_ui_actions_on_zoom_minus (GtkAction *action,
4548                                  ModestWindow *window)
4549 {
4550         g_return_if_fail (MODEST_IS_WINDOW (window));
4551
4552         modest_window_zoom_minus (MODEST_WINDOW (window));
4553 }
4554
4555 void
4556 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
4557                                            ModestWindow *window)
4558 {
4559         ModestWindowMgr *mgr;
4560         gboolean fullscreen, active;
4561         g_return_if_fail (MODEST_IS_WINDOW (window));
4562
4563         mgr = modest_runtime_get_window_mgr ();
4564
4565         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4566         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4567
4568         if (active != fullscreen) {
4569                 modest_window_mgr_set_fullscreen_mode (mgr, active);
4570 #ifndef MODEST_TOOLKIT_HILDON2
4571                 gtk_window_present (GTK_WINDOW (window));
4572 #endif
4573         }
4574 }
4575
4576 void
4577 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4578                                         ModestWindow *window)
4579 {
4580         ModestWindowMgr *mgr;
4581         gboolean fullscreen;
4582
4583         g_return_if_fail (MODEST_IS_WINDOW (window));
4584
4585         mgr = modest_runtime_get_window_mgr ();
4586         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4587         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4588
4589 #ifndef MODEST_TOOLKIT_HILDON2
4590         gtk_window_present (GTK_WINDOW (window));
4591 #endif
4592 }
4593
4594 /*
4595  * Used by modest_ui_actions_on_details to call do_headers_action
4596  */
4597 static void
4598 headers_action_show_details (TnyHeader *header,
4599                              ModestWindow *window,
4600                              gpointer user_data)
4601
4602 {
4603         gboolean async_retrieval;
4604         TnyMsg *msg = NULL;
4605
4606         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4607                 async_retrieval = TRUE;
4608                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (window));
4609         } else {
4610                 async_retrieval = FALSE;
4611         }
4612         modest_platform_run_header_details_dialog (GTK_WINDOW (window), header, async_retrieval, msg);
4613         if (msg)
4614                 g_object_unref (msg);
4615 }
4616
4617 /*
4618  * Show the header details in a ModestDetailsDialog widget
4619  */
4620 void
4621 modest_ui_actions_on_details (GtkAction *action,
4622                               ModestWindow *win)
4623 {
4624         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4625                 TnyMsg *msg;
4626                 TnyHeader *header;
4627
4628                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4629                 if (!msg)
4630                         return;
4631
4632                 header = tny_msg_get_header (msg);
4633                 if (header) {
4634                         headers_action_show_details (header, win, NULL);
4635                         g_object_unref (header);
4636                 }
4637                 g_object_unref (msg);
4638
4639         } else if (MODEST_IS_MAIN_WINDOW (win)) {
4640                 GtkWidget *folder_view, *header_view;
4641
4642                 /* Check which widget has the focus */
4643                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4644                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4645                 if (gtk_widget_is_focus (folder_view)) {
4646                         TnyFolderStore *folder_store
4647                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4648                         if (!folder_store) {
4649                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4650                                 return;
4651                         }
4652                         /* Show only when it's a folder */
4653                         /* This function should not be called for account items,
4654                          * because we dim the menu item for them. */
4655                         if (TNY_IS_FOLDER (folder_store)) {
4656                                 modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4657                                                                            TNY_FOLDER (folder_store));
4658                         }
4659
4660                         g_object_unref (folder_store);
4661
4662                 } else {
4663                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4664                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4665                         /* Show details of each header */
4666                         do_headers_action (win, headers_action_show_details, header_view);
4667                 }
4668 #ifdef MODEST_TOOLKIT_HILDON2
4669         } else if (MODEST_IS_HEADER_WINDOW (win)) {
4670                 TnyFolder *folder;
4671                 GtkWidget *header_view;
4672
4673                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
4674                 folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
4675                 if (folder) {
4676                         modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4677                                                                    folder);
4678                         g_object_unref (folder);
4679                 }
4680 #endif
4681         }
4682 }
4683
4684 void
4685 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4686                                      ModestMsgEditWindow *window)
4687 {
4688         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4689
4690         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4691 }
4692
4693 void
4694 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4695                                       ModestMsgEditWindow *window)
4696 {
4697         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4698
4699         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4700 }
4701
4702 void
4703 modest_ui_actions_toggle_folders_view (GtkAction *action,
4704                                        ModestMainWindow *main_window)
4705 {
4706         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4707
4708         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4709                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4710         else
4711                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4712 }
4713
4714 void
4715 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
4716                                      ModestWindow *window)
4717 {
4718         gboolean active, fullscreen = FALSE;
4719         ModestWindowMgr *mgr;
4720
4721         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4722
4723         /* Check if we want to toggle the toolbar view in fullscreen
4724            or normal mode */
4725         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
4726                      "ViewShowToolbarFullScreen")) {
4727                 fullscreen = TRUE;
4728         }
4729
4730         /* Toggle toolbar */
4731         mgr = modest_runtime_get_window_mgr ();
4732         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4733 }
4734
4735 void
4736 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4737                                            ModestMsgEditWindow *window)
4738 {
4739         modest_msg_edit_window_select_font (window);
4740 }
4741
4742
4743 void
4744 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4745                                                   const gchar *display_name,
4746                                                   GtkWindow *window)
4747 {
4748         /* don't update the display name if it was already set;
4749          * updating the display name apparently is expensive */
4750         const gchar* old_name = gtk_window_get_title (window);
4751
4752         if (display_name == NULL)
4753                 display_name = " ";
4754
4755         if (old_name && display_name && strcmp (old_name, display_name) == 0)
4756                 return; /* don't do anything */
4757
4758         /* This is usually used to change the title of the main window, which
4759          * is the one that holds the folder view. Note that this change can
4760          * happen even when the widget doesn't have the focus. */
4761         gtk_window_set_title (window, display_name);
4762
4763 }
4764
4765 void
4766 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4767 {
4768         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4769         modest_msg_edit_window_select_contacts (window);
4770 }
4771
4772 void
4773 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4774 {
4775         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4776         modest_msg_edit_window_check_names (window, FALSE);
4777 }
4778
4779 #ifndef MODEST_TOOLKIT_HILDON2
4780 /*
4781  * This function is used to track changes in the selection of the
4782  * folder view that is inside the "move to" dialog to enable/disable
4783  * the OK button because we do not want the user to select a disallowed
4784  * destination for a folder.
4785  * The user also not desired to be able to use NEW button on items where
4786  * folder creation is not possibel.
4787  */
4788 static void
4789 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4790                                             TnyFolderStore *folder_store,
4791                                             gboolean selected,
4792                                             gpointer user_data)
4793 {
4794         GtkWidget *dialog = NULL;
4795         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4796         gboolean moving_folder = FALSE;
4797         gboolean is_local_account = TRUE;
4798         GtkWidget *folder_view = NULL;
4799         ModestTnyFolderRules rules;
4800
4801         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4802
4803         if (!selected)
4804                 return;
4805
4806         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4807         if (!dialog)
4808                 return;
4809
4810         /* check if folder_store is an remote account */
4811         if (TNY_IS_ACCOUNT (folder_store)) {
4812                 TnyAccount *local_account = NULL;
4813                 TnyAccount *mmc_account = NULL;
4814                 ModestTnyAccountStore *account_store = NULL;
4815
4816                 account_store = modest_runtime_get_account_store ();
4817                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4818                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4819
4820                 if ((gpointer) local_account != (gpointer) folder_store &&
4821                     (gpointer) mmc_account != (gpointer) folder_store) {
4822                         ModestProtocolType proto;
4823                         proto = modest_tny_account_get_protocol_type (TNY_ACCOUNT (folder_store));
4824                         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
4825                                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
4826                         }
4827                         is_local_account = FALSE;
4828                         /* New button should be dimmed on remote
4829                            POP account root */
4830                         new_sensitive = (modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
4831                                                                                          proto,
4832                                                                                          MODEST_PROTOCOL_REGISTRY_STORE_HAS_FOLDERS));
4833                 }
4834                 g_object_unref (local_account);
4835
4836                 /* It could not exist */
4837                 if (mmc_account)
4838                         g_object_unref (mmc_account);
4839         }
4840
4841         /* Check the target folder rules */
4842         if (TNY_IS_FOLDER (folder_store)) {
4843                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
4844                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
4845                         ok_sensitive = FALSE;
4846                         new_sensitive = FALSE;
4847                         goto end;
4848                 }
4849         }
4850
4851         /* Check if we're moving a folder */
4852         if (MODEST_IS_MAIN_WINDOW (user_data)) {
4853                 /* Get the widgets */
4854                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
4855                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4856                 if (gtk_widget_is_focus (folder_view))
4857                         moving_folder = TRUE;
4858         }
4859
4860         if (moving_folder) {
4861                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
4862
4863                 /* Get the folder to move */
4864                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4865
4866                 /* Check that we're not moving to the same folder */
4867                 if (TNY_IS_FOLDER (moved_folder)) {
4868                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
4869                         if (parent == folder_store)
4870                                 ok_sensitive = FALSE;
4871                         g_object_unref (parent);
4872                 }
4873
4874                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
4875                         /* Do not allow to move to an account unless it's the
4876                            local folders account */
4877                         if (!is_local_account)
4878                                 ok_sensitive = FALSE;
4879                 }
4880
4881                 if (ok_sensitive && (moved_folder == folder_store)) {
4882                         /* Do not allow to move to itself */
4883                         ok_sensitive = FALSE;
4884                 }
4885                 g_object_unref (moved_folder);
4886         } else {
4887                 TnyFolder *src_folder = NULL;
4888
4889                 /* Moving a message */
4890                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
4891
4892                         TnyHeader *header = NULL;
4893                         header = modest_msg_view_window_get_header
4894                                 (MODEST_MSG_VIEW_WINDOW (user_data));
4895                         if (!TNY_IS_HEADER(header))
4896                                 g_warning ("%s: could not get source header", __FUNCTION__);
4897                         else
4898                                 src_folder = tny_header_get_folder (header);
4899
4900                         if (header)
4901                                 g_object_unref (header);
4902                 } else {
4903                         src_folder =
4904                                 TNY_FOLDER (modest_folder_view_get_selected
4905                                             (MODEST_FOLDER_VIEW (folder_view)));
4906                 }
4907
4908                 if (TNY_IS_FOLDER(src_folder)) {
4909                         /* Do not allow to move the msg to the same folder */
4910                         /* Do not allow to move the msg to an account */
4911                         if ((gpointer) src_folder == (gpointer) folder_store ||
4912                             TNY_IS_ACCOUNT (folder_store))
4913                                 ok_sensitive = FALSE;
4914                         g_object_unref (src_folder);
4915                 } else
4916                         g_warning ("%s: could not get source folder", __FUNCTION__);
4917         }
4918
4919  end:
4920         /* Set sensitivity of the OK and NEW button */
4921         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, ok_sensitive);
4922         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), MODEST_GTK_RESPONSE_NEW_FOLDER, new_sensitive);
4923 }
4924 #endif
4925
4926 static void
4927 on_move_to_dialog_response (GtkDialog *dialog,
4928                             gint       response,
4929                             gpointer   user_data)
4930 {
4931         GtkWidget *parent_win;
4932         MoveToInfo *helper = NULL;
4933         ModestFolderView *folder_view;
4934
4935         helper = (MoveToInfo *) user_data;
4936
4937         parent_win = (GtkWidget *) helper->win;
4938         folder_view = MODEST_FOLDER_VIEW (g_object_get_data (G_OBJECT (dialog),
4939                                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4940
4941         switch (response) {
4942                 TnyFolderStore *dst_folder;
4943
4944         case MODEST_GTK_RESPONSE_NEW_FOLDER:
4945                 modest_ui_actions_create_folder (GTK_WIDGET (dialog), GTK_WIDGET (folder_view));
4946                 return;
4947         case GTK_RESPONSE_NONE:
4948         case GTK_RESPONSE_CANCEL:
4949         case GTK_RESPONSE_DELETE_EVENT:
4950                 break;
4951         case GTK_RESPONSE_OK:
4952                 dst_folder = modest_folder_view_get_selected (folder_view);
4953
4954                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
4955                         /* Clean list to move used for filtering */
4956                         modest_folder_view_set_list_to_move (folder_view, NULL);
4957
4958                         modest_ui_actions_on_main_window_move_to (NULL,
4959                                                                   GTK_WIDGET (folder_view),
4960                                                                   dst_folder,
4961                                                                   MODEST_MAIN_WINDOW (parent_win));
4962 #ifdef MODEST_TOOLKIT_HILDON2
4963                 } else if (MODEST_IS_FOLDER_WINDOW (parent_win)) {
4964                         /* Clean list to move used for filtering */
4965                         modest_folder_view_set_list_to_move (folder_view, NULL);
4966
4967                         modest_ui_actions_on_folder_window_move_to (GTK_WIDGET (folder_view),
4968                                                                     dst_folder,
4969                                                                     helper->list,
4970                                                                     GTK_WINDOW (parent_win));
4971 #endif
4972                 } else {
4973                         /* if the user selected a root folder
4974                            (account) then do not perform any action */
4975                         if (TNY_IS_ACCOUNT (dst_folder)) {
4976                                 g_signal_stop_emission_by_name (dialog, "response");
4977                                 return;
4978                         }
4979
4980                         /* Clean list to move used for filtering */
4981                         modest_folder_view_set_list_to_move (folder_view, NULL);
4982
4983                         /* Moving from headers window in edit mode */
4984                         modest_ui_actions_on_window_move_to (NULL, helper->list,
4985                                                              dst_folder,
4986                                                              MODEST_WINDOW (parent_win));
4987                 }
4988
4989                 if (dst_folder)
4990                         g_object_unref (dst_folder);
4991
4992                 break;
4993         default:
4994                 g_warning ("%s unexpected response id %d", __FUNCTION__, response);
4995         }
4996
4997         /* Free the helper and exit */
4998         if (helper->list)
4999                 g_object_unref (helper->list);
5000         g_slice_free (MoveToInfo, helper);
5001         gtk_widget_destroy (GTK_WIDGET (dialog));
5002 }
5003
5004 static GtkWidget*
5005 create_move_to_dialog (GtkWindow *win,
5006                        GtkWidget *folder_view,
5007                        TnyList *list_to_move)
5008 {
5009         GtkWidget *dialog, *tree_view = NULL;
5010
5011         dialog = modest_platform_create_move_to_dialog (win, &tree_view);
5012
5013 #ifndef MODEST_TOOLKIT_HILDON2
5014         /* Track changes in the selection to
5015          * disable the OK button whenever "Move to" is not possible
5016          * disbale NEW button whenever New is not possible */
5017         g_signal_connect (tree_view,
5018                           "folder_selection_changed",
5019                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
5020                           win);
5021 #endif
5022
5023         /* It could happen that we're trying to move a message from a
5024            window (msg window for example) after the main window was
5025            closed, so we can not just get the model of the folder
5026            view */
5027         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
5028                 const gchar *visible_id = NULL;
5029
5030                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5031                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5032                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
5033                                                MODEST_FOLDER_VIEW(tree_view));
5034
5035                 visible_id =
5036                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
5037
5038                 /* Show the same account than the one that is shown in the main window */
5039                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(tree_view),
5040                                                                              visible_id);
5041         } else {
5042                 const gchar *active_account_name = NULL;
5043                 ModestAccountMgr *mgr = NULL;
5044                 ModestAccountSettings *settings = NULL;
5045                 ModestServerAccountSettings *store_settings = NULL;
5046
5047                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5048                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5049                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (tree_view),
5050                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
5051
5052                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
5053                 mgr = modest_runtime_get_account_mgr ();
5054                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
5055
5056                 if (settings) {
5057                         const gchar *store_account_name;
5058                         store_settings = modest_account_settings_get_store_settings (settings);
5059                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
5060
5061                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (tree_view),
5062                                                                                      store_account_name);
5063                         g_object_unref (store_settings);
5064                         g_object_unref (settings);
5065                 }
5066         }
5067
5068         /* we keep a pointer to the embedded folder view, so we can
5069          *   retrieve it with get_folder_view_from_move_to_dialog (see
5070          *   above) later (needed for focus handling)
5071          */
5072         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, tree_view);
5073
5074         /* Hide special folders */
5075 #ifndef MODEST_TOOLKIT_HILDON2
5076         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (tree_view), FALSE);
5077 #endif
5078         if (list_to_move)
5079                 modest_folder_view_set_list_to_move (MODEST_FOLDER_VIEW (tree_view), list_to_move);
5080 #ifndef MODEST_TOOLKIT_HILDON2
5081         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5082 #endif
5083
5084         gtk_widget_show (GTK_WIDGET (tree_view));
5085
5086         return dialog;
5087 }
5088
5089 /*
5090  * Shows a confirmation dialog to the user when we're moving messages
5091  * from a remote server to the local storage. Returns the dialog
5092  * response. If it's other kind of movement then it always returns
5093  * GTK_RESPONSE_OK
5094  *
5095  * This one is used by the next functions:
5096  *      modest_ui_actions_on_paste                      - commented out
5097  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
5098  */
5099 gint
5100 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
5101                                              TnyFolder *dest_folder,
5102                                              gboolean delete,
5103                                              TnyList *headers)
5104 {
5105         gint response = GTK_RESPONSE_OK;
5106         TnyAccount *account = NULL;
5107         TnyFolder *src_folder = NULL;
5108         TnyIterator *iter = NULL;
5109         TnyHeader *header = NULL;
5110
5111         /* return with OK if the destination is a remote folder */
5112         if (modest_tny_folder_is_remote_folder (dest_folder))
5113                 return GTK_RESPONSE_OK;
5114
5115         /* Get source folder */
5116         iter = tny_list_create_iterator (headers);
5117         header = TNY_HEADER (tny_iterator_get_current (iter));
5118         if (header) {
5119                 src_folder = tny_header_get_folder (header);
5120                 g_object_unref (header);
5121         }
5122         g_object_unref (iter);
5123
5124         /* if no src_folder, message may be an attahcment */
5125         if (src_folder == NULL)
5126                 return GTK_RESPONSE_CANCEL;
5127
5128         /* If the source is a local or MMC folder */
5129         if (!modest_tny_folder_is_remote_folder (src_folder)) {
5130                 g_object_unref (src_folder);
5131                 return GTK_RESPONSE_OK;
5132         }
5133
5134         /* Get the account */
5135         account = tny_folder_get_account (src_folder);
5136
5137         /* now if offline we ask the user */
5138         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
5139                 response = GTK_RESPONSE_OK;
5140         else
5141                 response = GTK_RESPONSE_CANCEL;
5142
5143         /* Frees */
5144         g_object_unref (src_folder);
5145         g_object_unref (account);
5146
5147         return response;
5148 }
5149
5150 static void
5151 move_to_helper_destroyer (gpointer user_data)
5152 {
5153         MoveToHelper *helper = (MoveToHelper *) user_data;
5154
5155         /* Close the "Pasting" information banner */
5156         if (helper->banner) {
5157                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
5158                 g_object_unref (helper->banner);
5159         }
5160         if (gtk_tree_row_reference_valid (helper->reference)) {
5161                 gtk_tree_row_reference_free (helper->reference);
5162                 helper->reference = NULL;
5163         }
5164         g_free (helper);
5165 }
5166
5167 static void
5168 move_to_cb (ModestMailOperation *mail_op,
5169             gpointer user_data)
5170 {
5171         MoveToHelper *helper = (MoveToHelper *) user_data;
5172         GObject *object = modest_mail_operation_get_source (mail_op);
5173
5174         /* Note that the operation could have failed, in that case do
5175            nothing */
5176         if (modest_mail_operation_get_status (mail_op) !=
5177             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5178                 goto frees;
5179
5180         if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
5181                 ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
5182
5183                 if (!modest_msg_view_window_select_next_message (self) &&
5184                     !modest_msg_view_window_select_previous_message (self)) {
5185                         /* No more messages to view, so close this window */
5186                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
5187                 }
5188         } else if (MODEST_IS_MAIN_WINDOW (object) &&
5189                    gtk_tree_row_reference_valid (helper->reference)) {
5190                 GtkWidget *header_view;
5191                 GtkTreePath *path;
5192                 GtkTreeSelection *sel;
5193
5194                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5195                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5196                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
5197                 path = gtk_tree_row_reference_get_path (helper->reference);
5198                 /* We need to unselect the previous one
5199                    because we could be copying instead of
5200                    moving */
5201                 gtk_tree_selection_unselect_all (sel);
5202                 gtk_tree_selection_select_path (sel, path);
5203                 gtk_tree_path_free (path);
5204         }
5205         g_object_unref (object);
5206
5207  frees:
5208         /* Destroy the helper */
5209         move_to_helper_destroyer (helper);
5210 }
5211
5212 static void
5213 folder_move_to_cb (ModestMailOperation *mail_op,
5214                    TnyFolder *new_folder,
5215                    gpointer user_data)
5216 {
5217         GtkWidget *folder_view;
5218         GObject *object;
5219
5220         object = modest_mail_operation_get_source (mail_op);
5221         if (MODEST_IS_MAIN_WINDOW (object)) {
5222                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5223                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5224                 g_object_ref (folder_view);
5225                 g_object_unref (object);
5226                 move_to_cb (mail_op, user_data);
5227                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
5228                 g_object_unref (folder_view);
5229         } else {
5230                 move_to_cb (mail_op, user_data);
5231         }
5232 }
5233
5234 static void
5235 msgs_move_to_cb (ModestMailOperation *mail_op,
5236                  gpointer user_data)
5237 {
5238         move_to_cb (mail_op, user_data);
5239 }
5240
5241 void
5242 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
5243                                              gpointer user_data)
5244 {
5245         GObject *win = NULL;
5246
5247 #ifndef MODEST_TOOLKIT_HILDON2
5248         ModestWindow *main_window = NULL;
5249
5250         /* Disable next automatic folder selection */
5251         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5252                                                          FALSE); /* don't create */
5253         if (main_window) {
5254                 GtkWidget *folder_view = NULL;
5255
5256                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
5257                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5258                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
5259
5260                 if (user_data && TNY_IS_FOLDER (user_data)) {
5261                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
5262                                                           TNY_FOLDER (user_data), FALSE);
5263                 }
5264         }
5265 #endif
5266         /* Show notification dialog only if the main window exists */
5267         win = modest_mail_operation_get_source (mail_op);
5268         modest_platform_run_information_dialog ((GtkWindow *) win,
5269                                                 _("mail_in_ui_folder_move_target_error"),
5270                                                 FALSE);
5271         if (win)
5272                 g_object_unref (win);
5273 }
5274
5275 static void
5276 open_msg_for_purge_cb (ModestMailOperation *mail_op,
5277                        TnyHeader *header,
5278                        gboolean canceled,
5279                        TnyMsg *msg,
5280                        GError *err,
5281                        gpointer user_data)
5282 {
5283         TnyList *parts;
5284         TnyIterator *iter;
5285         gint pending_purges = 0;
5286         gboolean some_purged = FALSE;
5287         ModestWindow *win = MODEST_WINDOW (user_data);
5288         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
5289
5290         /* If there was any error */
5291         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
5292                 modest_window_mgr_unregister_header (mgr, header);
5293                 return;
5294         }
5295
5296         /* Once the message has been retrieved for purging, we check if
5297          * it's all ok for purging */
5298
5299         parts = tny_simple_list_new ();
5300         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
5301         iter = tny_list_create_iterator (parts);
5302
5303         while (!tny_iterator_is_done (iter)) {
5304                 TnyMimePart *part;
5305                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5306                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
5307                         if (tny_mime_part_is_purged (part))
5308                                 some_purged = TRUE;
5309                         else
5310                                 pending_purges++;
5311                 }
5312
5313                 if (part)
5314                         g_object_unref (part);
5315
5316                 tny_iterator_next (iter);
5317         }
5318         g_object_unref (iter);
5319
5320
5321         if (pending_purges>0) {
5322                 gint response;
5323                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
5324
5325                 if (response == GTK_RESPONSE_OK) {
5326                         GtkWidget *info;
5327                         info =
5328                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_me_inbox_remove_attachments"));
5329                         iter = tny_list_create_iterator (parts);
5330                         while (!tny_iterator_is_done (iter)) {
5331                                 TnyMimePart *part;
5332
5333                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5334                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
5335                                         tny_mime_part_set_purged (part);
5336
5337                                 if (part)
5338                                         g_object_unref (part);
5339
5340                                 tny_iterator_next (iter);
5341                         }
5342                         g_object_unref (iter);
5343
5344                         tny_msg_rewrite_cache (msg);
5345
5346                         gtk_widget_destroy (info);
5347                 }
5348         }
5349
5350         modest_window_mgr_unregister_header (mgr, header);
5351
5352         g_object_unref (parts);
5353 }
5354
5355 static void
5356 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
5357                                                      ModestMainWindow *win)
5358 {
5359         GtkWidget *header_view;
5360         TnyList *header_list;
5361         TnyHeader *header;
5362         TnyHeaderFlags flags;
5363         ModestWindow *msg_view_window =  NULL;
5364         gboolean found;
5365
5366         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5367
5368         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5369                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5370
5371         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5372         if (!header_list) {
5373                 g_warning ("%s: no header selected", __FUNCTION__);
5374                 return;
5375         }
5376
5377         if (tny_list_get_length (header_list) == 1) {
5378                 TnyIterator *iter = tny_list_create_iterator (header_list);
5379                 header = TNY_HEADER (tny_iterator_get_current (iter));
5380                 g_object_unref (iter);
5381         } else
5382                 return;
5383
5384         if (!header || !TNY_IS_HEADER(header)) {
5385                 g_warning ("%s: header is not valid", __FUNCTION__);
5386                 return;
5387         }
5388
5389         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
5390                                                           header, &msg_view_window);
5391         flags = tny_header_get_flags (header);
5392         if (!(flags & TNY_HEADER_FLAG_CACHED))
5393                 return;
5394         if (found) {
5395                 if (msg_view_window != NULL)
5396                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
5397                 else {
5398                         /* do nothing; uid was registered before, so window is probably on it's way */
5399                         g_warning ("debug: header %p has already been registered", header);
5400                 }
5401         } else {
5402                 ModestMailOperation *mail_op = NULL;
5403                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
5404                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
5405                                                                          modest_ui_actions_disk_operations_error_handler,
5406                                                                          NULL, NULL);
5407                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5408                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
5409
5410                 g_object_unref (mail_op);
5411         }
5412         if (header)
5413                 g_object_unref (header);
5414         if (header_list)
5415                 g_object_unref (header_list);
5416 }
5417
5418 /*
5419  * Checks if we need a connection to do the transfer and if the user
5420  * wants to connect to complete it
5421  */
5422 static void
5423 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5424                                        TnyFolderStore *src_folder,
5425                                        TnyList *headers,
5426                                        TnyFolder *dst_folder,
5427                                        gboolean delete_originals,
5428                                        gboolean *need_connection,
5429                                        gboolean *do_xfer)
5430 {
5431         TnyAccount *src_account;
5432         gint uncached_msgs = 0;
5433
5434         /* We don't need any further check if
5435          *
5436          * 1- the source folder is local OR
5437          * 2- the device is already online
5438          */
5439         if (!modest_tny_folder_store_is_remote (src_folder) ||
5440             tny_device_is_online (modest_runtime_get_device())) {
5441                 *need_connection = FALSE;
5442                 *do_xfer = TRUE;
5443                 return;
5444         }
5445
5446         /* We must ask for a connection when
5447          *
5448          *   - the message(s) is not already cached   OR
5449          *   - the message(s) is cached but the leave_on_server setting
5450          * is FALSE (because we need to sync the source folder to
5451          * delete the message from the server (for IMAP we could do it
5452          * offline, it'll take place the next time we get a
5453          * connection)
5454          */
5455         uncached_msgs = header_list_count_uncached_msgs (headers);
5456         src_account = get_account_from_folder_store (src_folder);
5457         if (uncached_msgs > 0) {
5458                 guint num_headers;
5459                 const gchar *msg;
5460
5461                 *need_connection = TRUE;
5462                 num_headers = tny_list_get_length (headers);
5463                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
5464
5465                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
5466                     GTK_RESPONSE_CANCEL) {
5467                         *do_xfer = FALSE;
5468                 } else {
5469                         *do_xfer = TRUE;
5470                 }
5471         } else {
5472                 /* The transfer is possible and the user wants to */
5473                 *do_xfer = TRUE;
5474
5475                 if (remote_folder_has_leave_on_server (src_folder) && delete_originals) {
5476                         const gchar *account_name;
5477                         gboolean leave_on_server;
5478
5479                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
5480                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
5481                                                                                   account_name);
5482
5483                         if (leave_on_server == TRUE) {
5484                                 *need_connection = FALSE;
5485                         } else {
5486                                 *need_connection = TRUE;
5487                         }
5488                 } else {
5489                         *need_connection = FALSE;
5490                 }
5491         }
5492
5493         /* Frees */
5494         g_object_unref (src_account);
5495 }
5496
5497 static void
5498 xfer_messages_error_handler (ModestMailOperation *mail_op,
5499                              gpointer user_data)
5500 {
5501         GObject *win;
5502         const GError *error;
5503
5504         win = modest_mail_operation_get_source (mail_op);
5505         error = modest_mail_operation_get_error (mail_op);
5506
5507         if (error && is_memory_full_error ((GError *) error, mail_op)) {
5508                 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
5509                 modest_platform_information_banner ((GtkWidget *) win, NULL, msg);
5510                 g_free (msg);
5511         } else {
5512                 modest_platform_run_information_dialog ((GtkWindow *) win,
5513                                                         _("mail_in_ui_folder_move_target_error"),
5514                                                         FALSE);
5515         }
5516         if (win)
5517                 g_object_unref (win);
5518 }
5519
5520 typedef struct {
5521         TnyFolderStore *dst_folder;
5522         TnyList *headers;
5523 } XferMsgsHelper;
5524
5525 /**
5526  * Utility function that transfer messages from both the main window
5527  * and the msg view window when using the "Move to" dialog
5528  */
5529 static void
5530 xfer_messages_performer  (gboolean canceled,
5531                           GError *err,
5532                           GtkWindow *parent_window,
5533                           TnyAccount *account,
5534                           gpointer user_data)
5535 {
5536         ModestWindow *win = MODEST_WINDOW (parent_window);
5537         TnyAccount *dst_account = NULL;
5538         gboolean dst_forbids_message_add = FALSE;
5539         XferMsgsHelper *helper;
5540         MoveToHelper *movehelper;
5541         ModestMailOperation *mail_op;
5542
5543         helper = (XferMsgsHelper *) user_data;
5544
5545         if (canceled || err) {
5546                 if (!check_memory_full_error ((GtkWidget *) parent_window, err)) {
5547                         /* Show the proper error message */
5548                         modest_ui_actions_on_account_connection_error (parent_window, account);
5549                 }
5550                 goto end;
5551         }
5552
5553         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
5554
5555         /* tinymail will return NULL for local folders it seems */
5556         dst_forbids_message_add = modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5557                                                                                   modest_tny_account_get_protocol_type (dst_account),
5558                                                                                   MODEST_PROTOCOL_REGISTRY_STORE_FORBID_MESSAGE_ADD);
5559         g_object_unref (dst_account);
5560
5561         if (dst_forbids_message_add) {
5562                 modest_platform_information_banner (GTK_WIDGET (win),
5563                                                     NULL,
5564                                                     ngettext("mail_in_ui_folder_move_target_error",
5565                                                              "mail_in_ui_folder_move_targets_error",
5566                                                              tny_list_get_length (helper->headers)));
5567                 goto end;
5568         }
5569
5570         movehelper = g_new0 (MoveToHelper, 1);
5571
5572 #ifndef MODEST_TOOLKIT_HILDON2
5573         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
5574                                                                _CS("ckct_nw_pasting"));
5575         if (movehelper->banner != NULL)  {
5576                 g_object_ref (movehelper->banner);
5577                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
5578         }
5579 #endif
5580
5581         if (MODEST_IS_MAIN_WINDOW (win)) {
5582                 GtkWidget *header_view =
5583                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5584                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5585                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5586         }
5587
5588         /* Perform the mail operation */
5589         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5590                                                                  xfer_messages_error_handler,
5591                                                                  movehelper, NULL);
5592         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5593                                          mail_op);
5594
5595         modest_mail_operation_xfer_msgs (mail_op,
5596                                          helper->headers,
5597                                          TNY_FOLDER (helper->dst_folder),
5598                                          TRUE,
5599                                          msgs_move_to_cb,
5600                                          movehelper);
5601
5602         g_object_unref (G_OBJECT (mail_op));
5603  end:
5604         g_object_unref (helper->dst_folder);
5605         g_object_unref (helper->headers);
5606         g_slice_free (XferMsgsHelper, helper);
5607 }
5608
5609 typedef struct {
5610         TnyFolder *src_folder;
5611         TnyFolderStore *dst_folder;
5612         gboolean delete_original;
5613         GtkWidget *folder_view;
5614 } MoveFolderInfo;
5615
5616 static void
5617 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window,
5618                 TnyAccount *account, gpointer user_data)
5619 {
5620         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5621         GtkTreeSelection *sel;
5622         ModestMailOperation *mail_op = NULL;
5623
5624         if (canceled || err || !MODEST_IS_WINDOW (parent_window)) {
5625                 g_object_unref (G_OBJECT (info->src_folder));
5626                 g_object_unref (G_OBJECT (info->dst_folder));
5627                 g_free (info);
5628                 return;
5629         }
5630
5631         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5632 #ifndef MODEST_TOOLKIT_HILDON2
5633         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5634                         _CS("ckct_nw_pasting"));
5635         if (helper->banner != NULL)  {
5636                 g_object_ref (helper->banner);
5637                 gtk_widget_show (GTK_WIDGET(helper->banner));
5638         }
5639 #endif
5640         /* Clean folder on header view before moving it */
5641         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5642         gtk_tree_selection_unselect_all (sel);
5643
5644         /* Let gtk events run. We need that the folder
5645            view frees its reference to the source
5646            folder *before* issuing the mail operation
5647            so we need the signal handler of selection
5648            changed to happen before the mail
5649            operation
5650         while (gtk_events_pending ())
5651                 gtk_main_iteration ();   */
5652
5653         mail_op =
5654                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5655                                 modest_ui_actions_move_folder_error_handler,
5656                                 info->src_folder, NULL);
5657         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5658                         mail_op);
5659
5660         /* Select *after* the changes */
5661         /* TODO: this function hangs UI after transfer */
5662         /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
5663         /*                                                        TNY_FOLDER (src_folder), TRUE); */
5664
5665         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
5666                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5667                                                   TNY_FOLDER (info->dst_folder), TRUE);
5668         }
5669         modest_mail_operation_xfer_folder (mail_op,
5670                         TNY_FOLDER (info->src_folder),
5671                         info->dst_folder,
5672                         info->delete_original,
5673                         folder_move_to_cb,
5674                         helper);
5675         g_object_unref (G_OBJECT (info->src_folder));
5676
5677         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
5678         /* } */
5679
5680         /* Unref mail operation */
5681         g_object_unref (G_OBJECT (mail_op));
5682         g_object_unref (G_OBJECT (info->dst_folder));
5683         g_free (user_data);
5684 }
5685
5686 static TnyAccount *
5687 get_account_from_folder_store (TnyFolderStore *folder_store)
5688 {
5689         if (TNY_IS_ACCOUNT (folder_store))
5690                 return g_object_ref (folder_store);
5691         else
5692                 return tny_folder_get_account (TNY_FOLDER (folder_store));
5693 }
5694
5695 /*
5696  * UI handler for the "Move to" action when invoked from the
5697  * ModestMainWindow
5698  */
5699 static void
5700 modest_ui_actions_on_main_window_move_to (GtkAction *action,
5701                                           GtkWidget *folder_view,
5702                                           TnyFolderStore *dst_folder,
5703                                           ModestMainWindow *win)
5704 {
5705         ModestHeaderView *header_view = NULL;
5706         TnyFolderStore *src_folder = NULL;
5707
5708         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5709
5710         /* Get the source folder */
5711         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5712
5713         /* Get header view */
5714         header_view = (ModestHeaderView *)
5715                 modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5716
5717         /* Get folder or messages to transfer */
5718         if (gtk_widget_is_focus (folder_view)) {
5719                 gboolean do_xfer = TRUE;
5720
5721                 /* Allow only to transfer folders to the local root folder */
5722                 if (TNY_IS_ACCOUNT (dst_folder) &&
5723                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5724                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5725                         do_xfer = FALSE;
5726                 } else if (!TNY_IS_FOLDER (src_folder)) {
5727                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5728                         do_xfer = FALSE;
5729                 }
5730
5731                 if (do_xfer) {
5732                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5733                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5734
5735                         info->src_folder = g_object_ref (src_folder);
5736                         info->dst_folder = g_object_ref (dst_folder);
5737                         info->delete_original = TRUE;
5738                         info->folder_view = folder_view;
5739
5740                         connect_info->callback = on_move_folder_cb;
5741                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5742                         connect_info->data = info;
5743
5744                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5745                                                                    TNY_FOLDER_STORE (src_folder),
5746                                                                    connect_info);
5747                 }
5748         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5749                 TnyList *headers;
5750
5751                 headers = modest_header_view_get_selected_headers(header_view);
5752
5753                 /* Transfer the messages */
5754                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder),
5755                                                             headers, TNY_FOLDER (dst_folder));
5756
5757                 g_object_unref (headers);
5758         }
5759
5760         /* Frees */
5761         g_object_unref (src_folder);
5762 }
5763
5764 #ifdef MODEST_TOOLKIT_HILDON2
5765 /*
5766  * UI handler for the "Move to" action when invoked from the
5767  * ModestFolderWindow
5768  */
5769 static void
5770 modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
5771                                             TnyFolderStore *dst_folder,
5772                                             TnyList *selection,
5773                                             GtkWindow *win)
5774 {
5775         TnyFolderStore *src_folder = NULL;
5776         TnyIterator *iterator;
5777
5778         if (tny_list_get_length (selection) != 1)
5779                 return;
5780
5781         iterator = tny_list_create_iterator (selection);
5782         src_folder = TNY_FOLDER_STORE (tny_iterator_get_current (iterator));
5783         g_object_unref (iterator);
5784
5785
5786         gboolean do_xfer = TRUE;
5787
5788         /* Allow only to transfer folders to the local root folder */
5789         if (TNY_IS_ACCOUNT (dst_folder) &&
5790             !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5791             !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5792                 do_xfer = FALSE;
5793                 /* Show an error */
5794                 modest_platform_run_information_dialog (win,
5795                                                         _("mail_in_ui_folder_move_target_error"),
5796                                                         FALSE);
5797         } else if (!TNY_IS_FOLDER (src_folder)) {
5798                 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5799                 do_xfer = FALSE;
5800         }
5801
5802         if (do_xfer) {
5803                 MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5804                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5805
5806                 info->src_folder = g_object_ref (src_folder);
5807                 info->dst_folder = g_object_ref (dst_folder);
5808                 info->delete_original = TRUE;
5809                 info->folder_view = folder_view;
5810
5811                 connect_info->callback = on_move_folder_cb;
5812                 connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5813                 connect_info->data = info;
5814
5815                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5816                                                            TNY_FOLDER_STORE (src_folder),
5817                                                            connect_info);
5818         }
5819
5820         /* Frees */
5821         g_object_unref (src_folder);
5822 }
5823 #endif
5824
5825
5826 void
5827 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
5828                                             TnyFolder *src_folder,
5829                                             TnyList *headers,
5830                                             TnyFolder *dst_folder)
5831 {
5832         gboolean need_connection = TRUE;
5833         gboolean do_xfer = TRUE;
5834         XferMsgsHelper *helper;
5835
5836         g_return_if_fail (TNY_IS_FOLDER (src_folder));
5837         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5838         g_return_if_fail (TNY_IS_LIST (headers));
5839
5840         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder),
5841                                                headers, TNY_FOLDER (dst_folder),
5842                                                TRUE, &need_connection,
5843                                                &do_xfer);
5844
5845         /* If we don't want to transfer just return */
5846         if (!do_xfer)
5847                 return;
5848
5849         /* Create the helper */
5850         helper = g_slice_new (XferMsgsHelper);
5851         helper->dst_folder = g_object_ref (dst_folder);
5852         helper->headers = g_object_ref (headers);
5853
5854         if (need_connection) {
5855                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5856                 connect_info->callback = xfer_messages_performer;
5857                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
5858                 connect_info->data = helper;
5859
5860                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5861                                                            TNY_FOLDER_STORE (src_folder),
5862                                                            connect_info);
5863         } else {
5864                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
5865                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
5866                                          src_account, helper);
5867                 g_object_unref (src_account);
5868         }
5869 }
5870
5871 /*
5872  * UI handler for the "Move to" action when invoked from the
5873  * ModestMsgViewWindow
5874  */
5875 static void
5876 modest_ui_actions_on_window_move_to (GtkAction *action,
5877                                      TnyList *headers,
5878                                      TnyFolderStore *dst_folder,
5879                                      ModestWindow *win)
5880 {
5881         TnyFolder *src_folder = NULL;
5882
5883         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5884
5885         if (headers) {
5886                 TnyHeader *header = NULL;
5887                 TnyIterator *iter;
5888
5889                 iter = tny_list_create_iterator (headers);
5890                 header = (TnyHeader *) tny_iterator_get_current (iter);
5891                 src_folder = tny_header_get_folder (header);
5892
5893                 /* Transfer the messages */
5894                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder,
5895                                                             headers,
5896                                                             TNY_FOLDER (dst_folder));
5897
5898                 /* Frees */
5899                 g_object_unref (header);
5900                 g_object_unref (iter);
5901                 g_object_unref (src_folder);
5902         }
5903 }
5904
5905 void
5906 modest_ui_actions_on_move_to (GtkAction *action,
5907                               ModestWindow *win)
5908 {
5909         modest_ui_actions_on_edit_mode_move_to (win);
5910 }
5911
5912 gboolean
5913 modest_ui_actions_on_edit_mode_move_to (ModestWindow *win)
5914 {
5915         GtkWidget *dialog = NULL;
5916         MoveToInfo *helper = NULL;
5917         TnyList *list_to_move;
5918
5919         g_return_val_if_fail (MODEST_IS_WINDOW (win), FALSE);
5920
5921 #ifndef MODEST_TOOLKIT_HILDON2
5922         /* Get the main window if exists */
5923         ModestMainWindow *main_window;
5924         if (MODEST_IS_MAIN_WINDOW (win))
5925                 main_window = MODEST_MAIN_WINDOW (win);
5926         else
5927                 main_window =
5928                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5929                                                                                FALSE)); /* don't create */
5930 #endif
5931
5932         list_to_move = modest_platform_get_list_to_move (MODEST_WINDOW (win));
5933
5934         if (!list_to_move)
5935                 return FALSE;
5936
5937         if (tny_list_get_length (list_to_move) < 1) {
5938                 g_object_unref (list_to_move);
5939                 return FALSE;
5940         }
5941
5942         /* Create and run the dialog */
5943         dialog = create_move_to_dialog (GTK_WINDOW (win), NULL, list_to_move);
5944         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
5945                                      GTK_WINDOW (dialog),
5946                                      (GtkWindow *) win);
5947
5948         /* Create helper */
5949         helper = g_slice_new0 (MoveToInfo);
5950         helper->list = list_to_move;
5951         helper->win = win;
5952
5953         /* Listen to response signal */
5954         g_signal_connect (dialog, "response", G_CALLBACK (on_move_to_dialog_response), helper);
5955
5956         /* Show the dialog */
5957         gtk_widget_show (dialog);
5958
5959         return TRUE;
5960 }
5961
5962 /*
5963  * Calls #HeadersFunc for each header already selected in the main
5964  * window or the message currently being shown in the msg view window
5965  */
5966 static void
5967 do_headers_action (ModestWindow *win,
5968                    HeadersFunc func,
5969                    gpointer user_data)
5970 {
5971         TnyList *headers_list = NULL;
5972         TnyIterator *iter = NULL;
5973         TnyHeader *header = NULL;
5974         TnyFolder *folder = NULL;
5975
5976         /* Get headers */
5977         headers_list = get_selected_headers (win);
5978         if (!headers_list)
5979                 return;
5980
5981         /* Get the folder */
5982         iter = tny_list_create_iterator (headers_list);
5983         header = TNY_HEADER (tny_iterator_get_current (iter));
5984         if (header) {
5985                 folder = tny_header_get_folder (header);
5986                 g_object_unref (header);
5987         }
5988
5989         /* Call the function for each header */
5990         while (!tny_iterator_is_done (iter)) {
5991                 header = TNY_HEADER (tny_iterator_get_current (iter));
5992                 func (header, win, user_data);
5993                 g_object_unref (header);
5994                 tny_iterator_next (iter);
5995         }
5996
5997         /* Trick: do a poke status in order to speed up the signaling
5998            of observers */
5999         if (folder) {
6000                 tny_folder_poke_status (folder);
6001                 g_object_unref (folder);
6002         }
6003
6004         /* Frees */
6005         g_object_unref (iter);
6006         g_object_unref (headers_list);
6007 }
6008
6009 void
6010 modest_ui_actions_view_attachment (GtkAction *action,
6011                                    ModestWindow *window)
6012 {
6013         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6014                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
6015         } else {
6016                 /* not supported window for this action */
6017                 g_return_if_reached ();
6018         }
6019 }
6020
6021 void
6022 modest_ui_actions_save_attachments (GtkAction *action,
6023                                     ModestWindow *window)
6024 {
6025         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6026
6027                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
6028                         return;
6029
6030                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
6031         } else {
6032                 /* not supported window for this action */
6033                 g_return_if_reached ();
6034         }
6035 }
6036
6037 void
6038 modest_ui_actions_remove_attachments (GtkAction *action,
6039                                       ModestWindow *window)
6040 {
6041         if (MODEST_IS_MAIN_WINDOW (window)) {
6042                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
6043         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6044                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
6045         } else {
6046                 /* not supported window for this action */
6047                 g_return_if_reached ();
6048         }
6049 }
6050
6051 void
6052 modest_ui_actions_on_settings (GtkAction *action,
6053                                ModestWindow *win)
6054 {
6055         GtkWidget *dialog;
6056
6057         dialog = modest_platform_get_global_settings_dialog ();
6058         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
6059         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
6060         gtk_widget_show_all (dialog);
6061
6062         gtk_dialog_run (GTK_DIALOG (dialog));
6063
6064         gtk_widget_destroy (dialog);
6065 }
6066
6067 void
6068 modest_ui_actions_on_help (GtkAction *action,
6069                            GtkWindow *win)
6070 {
6071         /* Help app is not available at all in fremantle */
6072 #ifndef MODEST_TOOLKIT_HILDON2
6073         const gchar *help_id;
6074
6075         g_return_if_fail (win && GTK_IS_WINDOW(win));
6076
6077         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
6078
6079         if (help_id)
6080                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6081 #endif
6082 }
6083
6084 void
6085 modest_ui_actions_on_csm_help (GtkAction *action,
6086                                GtkWindow *win)
6087 {
6088         /* Help app is not available at all in fremantle */
6089 #ifndef MODEST_TOOLKIT_HILDON2
6090
6091         const gchar* help_id = NULL;
6092         GtkWidget *folder_view;
6093         TnyFolderStore *folder_store;
6094
6095         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
6096
6097         /* Get selected folder */
6098         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
6099                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6100         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6101
6102         /* Switch help_id */
6103         if (folder_store && TNY_IS_FOLDER (folder_store))
6104                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
6105
6106         if (folder_store)
6107                 g_object_unref (folder_store);
6108
6109         if (help_id)
6110                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6111         else
6112                 modest_ui_actions_on_help (action, win);
6113 #endif
6114 }
6115
6116 static void
6117 retrieve_contents_cb (ModestMailOperation *mail_op,
6118                       TnyHeader *header,
6119                       gboolean canceled,
6120                       TnyMsg *msg,
6121                       GError *err,
6122                       gpointer user_data)
6123 {
6124         /* We only need this callback to show an error in case of
6125            memory low condition */
6126         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
6127                 g_debug ("%s: message failed to retrieve. Memory low?", __FUNCTION__);
6128         }
6129 }
6130
6131 static void
6132 retrieve_msg_contents_performer (gboolean canceled,
6133                                  GError *err,
6134                                  GtkWindow *parent_window,
6135                                  TnyAccount *account,
6136                                  gpointer user_data)
6137 {
6138         ModestMailOperation *mail_op;
6139         TnyList *headers = TNY_LIST (user_data);
6140
6141         if (err || canceled) {
6142                 check_memory_full_error ((GtkWidget *) parent_window, err);
6143                 goto out;
6144         }
6145
6146         /* Create mail operation */
6147         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
6148                                                                  modest_ui_actions_disk_operations_error_handler,
6149                                                                  NULL, NULL);
6150         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
6151         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
6152
6153         /* Frees */
6154         g_object_unref (mail_op);
6155  out:
6156         g_object_unref (headers);
6157         g_object_unref (account);
6158 }
6159
6160 void
6161 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
6162                                             ModestWindow *window)
6163 {
6164         TnyList *headers = NULL;
6165         TnyAccount *account = NULL;
6166         TnyIterator *iter = NULL;
6167         TnyHeader *header = NULL;
6168         TnyFolder *folder = NULL;
6169
6170         /* Get headers */
6171         headers = get_selected_headers (window);
6172         if (!headers)
6173                 return;
6174
6175         /* Pick the account */
6176         iter = tny_list_create_iterator (headers);
6177         header = TNY_HEADER (tny_iterator_get_current (iter));
6178         folder = tny_header_get_folder (header);
6179         account = tny_folder_get_account (folder);
6180         g_object_unref (folder);
6181         g_object_unref (header);
6182         g_object_unref (iter);
6183
6184         /* Connect and perform the message retrieval */
6185         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
6186                                              g_object_ref (account),
6187                                              retrieve_msg_contents_performer,
6188                                              g_object_ref (headers));
6189
6190         /* Frees */
6191         g_object_unref (account);
6192         g_object_unref (headers);
6193 }
6194
6195 void
6196 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
6197 {
6198         g_return_if_fail (MODEST_IS_WINDOW (window));
6199
6200         /* Update dimmed */
6201         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
6202 }
6203
6204 void
6205 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
6206 {
6207         g_return_if_fail (MODEST_IS_WINDOW (window));
6208
6209         /* Update dimmed */
6210         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
6211 }
6212
6213 void
6214 modest_ui_actions_on_email_menu_activated (GtkAction *action,
6215                                           ModestWindow *window)
6216 {
6217         g_return_if_fail (MODEST_IS_WINDOW (window));
6218
6219         /* Update dimmed */
6220         modest_ui_actions_check_menu_dimming_rules (window);
6221 }
6222
6223 void
6224 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
6225                                           ModestWindow *window)
6226 {
6227         g_return_if_fail (MODEST_IS_WINDOW (window));
6228
6229         /* Update dimmed */
6230         modest_ui_actions_check_menu_dimming_rules (window);
6231 }
6232
6233 void
6234 modest_ui_actions_on_view_menu_activated (GtkAction *action,
6235                                           ModestWindow *window)
6236 {
6237         g_return_if_fail (MODEST_IS_WINDOW (window));
6238
6239         /* Update dimmed */
6240         modest_ui_actions_check_menu_dimming_rules (window);
6241 }
6242
6243 void
6244 modest_ui_actions_on_format_menu_activated (GtkAction *action,
6245                                             ModestWindow *window)
6246 {
6247         g_return_if_fail (MODEST_IS_WINDOW (window));
6248
6249         /* Update dimmed */
6250         modest_ui_actions_check_menu_dimming_rules (window);
6251 }
6252
6253 void
6254 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
6255                                           ModestWindow *window)
6256 {
6257         g_return_if_fail (MODEST_IS_WINDOW (window));
6258
6259         /* Update dimmed */
6260         modest_ui_actions_check_menu_dimming_rules (window);
6261 }
6262
6263 void
6264 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
6265                                           ModestWindow *window)
6266 {
6267         g_return_if_fail (MODEST_IS_WINDOW (window));
6268
6269         /* Update dimmed */
6270         modest_ui_actions_check_menu_dimming_rules (window);
6271 }
6272
6273 void
6274 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
6275                                                  ModestWindow *window)
6276 {
6277         g_return_if_fail (MODEST_IS_WINDOW (window));
6278
6279         /* Update dimmed */
6280         modest_ui_actions_check_menu_dimming_rules (window);
6281 }
6282
6283 void
6284 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
6285                                                      ModestWindow *window)
6286 {
6287         g_return_if_fail (MODEST_IS_WINDOW (window));
6288
6289         /* Update dimmed */
6290         modest_ui_actions_check_menu_dimming_rules (window);
6291 }
6292
6293 void
6294 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
6295                                                      ModestWindow *window)
6296 {
6297         g_return_if_fail (MODEST_IS_WINDOW (window));
6298
6299         /* Update dimmed */
6300         modest_ui_actions_check_menu_dimming_rules (window);
6301 }
6302
6303 void
6304 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
6305 {
6306         g_return_if_fail (MODEST_IS_WINDOW (window));
6307
6308         /* we check for low-mem; in that case, show a warning, and don't allow
6309          * searching
6310          */
6311         if (modest_platform_check_memory_low (window, TRUE))
6312                 return;
6313
6314         modest_platform_show_search_messages (GTK_WINDOW (window));
6315 }
6316
6317 void
6318 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
6319 {
6320         g_return_if_fail (MODEST_IS_WINDOW (win));
6321
6322
6323         /* we check for low-mem; in that case, show a warning, and don't allow
6324          * for the addressbook
6325          */
6326         if (modest_platform_check_memory_low (win, TRUE))
6327                 return;
6328
6329
6330         modest_platform_show_addressbook (GTK_WINDOW (win));
6331 }
6332
6333
6334 void
6335 modest_ui_actions_on_toggle_find_in_page (GtkAction *action,
6336                                           ModestWindow *window)
6337 {
6338         gboolean active;
6339         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
6340
6341         if (GTK_IS_TOGGLE_ACTION (action))
6342                 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
6343         else
6344                 active = TRUE;
6345
6346         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window),
6347                                                     active);
6348 }
6349
6350 static void
6351 on_send_receive_finished (ModestMailOperation  *mail_op,
6352                            gpointer user_data)
6353 {
6354         GtkWidget *header_view, *folder_view;
6355         TnyFolderStore *folder_store;
6356         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
6357
6358         /* Set send/receive operation finished */
6359         modest_main_window_notify_send_receive_completed (main_win);
6360
6361         /* Don't refresh the current folder if there were any errors */
6362         if (modest_mail_operation_get_status (mail_op) !=
6363             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
6364                 return;
6365
6366         /* Refresh the current folder if we're viewing a window. We do
6367            this because the user won't be able to see the new mails in
6368            the selected folder after a Send&Receive because it only
6369            performs a poke_status, i.e, only the number of read/unread
6370            messages is updated, but the new headers are not
6371            downloaded */
6372         folder_view = modest_main_window_get_child_widget (main_win,
6373                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6374         if (!folder_view)
6375                 return;
6376
6377         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6378
6379         /* Do not need to refresh INBOX again because the
6380            update_account does it always automatically */
6381         if (folder_store && TNY_IS_FOLDER (folder_store) &&
6382             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
6383                 ModestMailOperation *refresh_op;
6384
6385                 header_view = modest_main_window_get_child_widget (main_win,
6386                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6387
6388                 /* We do not need to set the contents style
6389                    because it hasn't changed. We also do not
6390                    need to save the widget status. Just force
6391                    a refresh */
6392                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
6393                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
6394                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
6395                                                       folder_refreshed_cb, main_win);
6396                 g_object_unref (refresh_op);
6397         }
6398
6399         if (folder_store)
6400                 g_object_unref (folder_store);
6401 }
6402
6403
6404 void
6405 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self,
6406                                                 TnyHeader *header,
6407                                                 TnyMsg *msg,
6408                                                 GError *err,
6409                                                 gpointer user_data)
6410 {
6411         const gchar* server_name = NULL;
6412         TnyTransportAccount *transport;
6413         gchar *message = NULL;
6414         ModestProtocol *protocol;
6415
6416         /* Don't show anything if the user cancelled something or the
6417          * send receive request is not interactive. Authentication
6418          * errors are managed by the account store so no need to show
6419          * a dialog here again */
6420         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
6421             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
6422             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
6423                 return;
6424
6425
6426         /* Get the server name. Note that we could be using a
6427            connection specific transport account */
6428         transport = (TnyTransportAccount *)
6429                 tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self));
6430         if (transport) {
6431                 ModestTnyAccountStore *acc_store;
6432                 const gchar *acc_name;
6433                 TnyTransportAccount *conn_specific;
6434
6435                 acc_store = modest_runtime_get_account_store();
6436                 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT (transport));
6437                 conn_specific = (TnyTransportAccount *)
6438                         modest_tny_account_store_get_transport_account_for_open_connection (acc_store, acc_name);
6439                 if (conn_specific) {
6440                         server_name = tny_account_get_hostname (TNY_ACCOUNT (conn_specific));
6441                         g_object_unref (conn_specific);
6442                 } else {
6443                         server_name = tny_account_get_hostname (TNY_ACCOUNT (transport));
6444                 }
6445                 g_object_unref (transport);
6446         }
6447
6448         /* Get protocol */
6449         protocol = modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
6450                                                                   MODEST_PROTOCOL_REGISTRY_TRANSPORT_STORE_PROTOCOLS,
6451                                                                   tny_account_get_proto (TNY_ACCOUNT (transport)));
6452         if (!protocol) {
6453                 g_warning ("%s: Account with no proto", __FUNCTION__);
6454                 return;
6455         }
6456
6457         /* Show the appropriate message text for the GError: */
6458         switch (err->code) {
6459         case TNY_SERVICE_ERROR_CONNECT:
6460                 message = modest_protocol_get_translation (protocol,
6461                                                            MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR,
6462                                                            server_name);
6463                 break;
6464         case TNY_SERVICE_ERROR_SEND:
6465                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6466                 break;
6467         case TNY_SERVICE_ERROR_UNAVAILABLE:
6468                 message = modest_protocol_get_translation (protocol,
6469                                                            MODEST_PROTOCOL_TRANSLATION_CONNECT_ERROR,
6470                                                            server_name);
6471                 break;
6472         default:
6473                 g_warning ("%s: unexpected ERROR %d",
6474                            __FUNCTION__, err->code);
6475                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6476                 break;
6477         }
6478
6479         modest_platform_run_information_dialog (NULL, message, FALSE);
6480         g_free (message);
6481 }
6482
6483 void
6484 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
6485                                                 gchar *msg_id,
6486                                                 guint status,
6487                                                 gpointer user_data)
6488 {
6489         ModestWindow *top_window = NULL;
6490         ModestWindowMgr *mgr = NULL;
6491         GtkWidget *header_view = NULL;
6492         TnyFolder *selected_folder = NULL;
6493         TnyFolderType folder_type;
6494
6495         mgr = modest_runtime_get_window_mgr ();
6496         top_window = modest_window_mgr_get_current_top (mgr);
6497
6498         if (!top_window)
6499                 return;
6500
6501 #ifndef MODEST_TOOLKIT_HILDON2
6502         if (MODEST_IS_MAIN_WINDOW (top_window)) {
6503                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (top_window),
6504                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6505         }
6506 #else
6507         if (MODEST_IS_HEADER_WINDOW (top_window)) {
6508                 header_view = (GtkWidget *)
6509                         modest_header_window_get_header_view (MODEST_HEADER_WINDOW (top_window));
6510         }
6511 #endif
6512
6513         /* Get selected folder */
6514         if (header_view)
6515                 selected_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
6516         if (!selected_folder)
6517                 return;
6518
6519         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
6520 #if GTK_CHECK_VERSION(2, 8, 0)
6521         folder_type = modest_tny_folder_guess_folder_type (selected_folder);
6522         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {
6523                 GtkTreeViewColumn *tree_column;
6524
6525                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view),
6526                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
6527                 if (tree_column)
6528                         gtk_tree_view_column_queue_resize (tree_column);
6529                 }
6530 #else /* #if GTK_CHECK_VERSION(2, 8, 0) */
6531         gtk_widget_queue_draw (header_view);
6532 #endif
6533
6534 #ifndef MODEST_TOOLKIT_HILDON2
6535         /* Rerun dimming rules, because the message could become deletable for example */
6536         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6537                                                  MODEST_DIMMING_RULES_TOOLBAR);
6538         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6539                                                  MODEST_DIMMING_RULES_MENU);
6540 #endif
6541
6542         /* Free */
6543         g_object_unref (selected_folder);
6544 }
6545
6546 void
6547 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
6548                                                TnyAccount *account)
6549 {
6550         ModestProtocolType protocol_type;
6551         ModestProtocol *protocol;
6552         gchar *error_note = NULL;
6553
6554         protocol_type = modest_tny_account_get_protocol_type (account);
6555         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6556                                                                   protocol_type);
6557
6558         error_note = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR, tny_account_get_hostname (account));
6559         if (error_note == NULL) {
6560                 g_warning ("%s: This should not be reached", __FUNCTION__);
6561         } else {
6562                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
6563                 g_free (error_note);
6564         }
6565 }
6566
6567 gchar *
6568 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
6569 {
6570         gchar *msg = NULL;
6571         gchar *subject;
6572         TnyFolderStore *folder = NULL;
6573         TnyAccount *account = NULL;
6574         ModestProtocolType proto;
6575         ModestProtocol *protocol;
6576         TnyHeader *header = NULL;
6577
6578         if (MODEST_IS_MAIN_WINDOW (win)) {
6579                 GtkWidget *header_view;
6580                 TnyList* headers = NULL;
6581                 TnyIterator *iter;
6582                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
6583                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6584                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6585                 if (!headers || tny_list_get_length (headers) == 0) {
6586                         if (headers)
6587                                 g_object_unref (headers);
6588                         return NULL;
6589                 }
6590                 iter = tny_list_create_iterator (headers);
6591                 header = TNY_HEADER (tny_iterator_get_current (iter));
6592                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6593                 g_object_unref (iter);
6594                 g_object_unref (headers);
6595 #ifdef MODEST_TOOLKIT_HILDON2
6596         } else if (MODEST_IS_HEADER_WINDOW (win)) {
6597                 GtkWidget *header_view;
6598                 TnyList* headers = NULL;
6599                 TnyIterator *iter;
6600                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
6601                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6602                 if (!headers || tny_list_get_length (headers) == 0) {
6603                         if (headers)
6604                                 g_object_unref (headers);
6605                         return NULL;
6606                 }
6607                 iter = tny_list_create_iterator (headers);
6608                 header = TNY_HEADER (tny_iterator_get_current (iter));
6609                 if (header) {
6610                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6611                 } else {
6612                         g_warning ("List should contain headers");
6613                 }
6614                 g_object_unref (iter);
6615                 g_object_unref (headers);
6616 #endif
6617         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
6618                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
6619                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6620         }
6621
6622         if (!header || !folder)
6623                 goto frees;
6624
6625         /* Get the account type */
6626         account = tny_folder_get_account (TNY_FOLDER (folder));
6627         proto = modest_tny_account_get_protocol_type (account);
6628         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6629                                                                   proto);
6630
6631         subject = tny_header_dup_subject (header);
6632         msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
6633         if (subject)
6634                 g_free (subject);
6635         if (msg == NULL) {
6636                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
6637         }
6638
6639  frees:
6640         /* Frees */
6641         if (account)
6642                 g_object_unref (account);
6643         if (folder)
6644                 g_object_unref (folder);
6645         if (header)
6646                 g_object_unref (header);
6647
6648         return msg;
6649 }
6650
6651 gboolean
6652 modest_ui_actions_on_delete_account (GtkWindow *parent_window,
6653                                      const gchar *account_name,
6654                                      const gchar *account_title)
6655 {
6656         ModestAccountMgr *account_mgr;
6657         gchar *txt = NULL;
6658         gint response;
6659         ModestProtocol *protocol;
6660         gboolean removed = FALSE;
6661
6662         g_return_val_if_fail (account_name, FALSE);
6663         g_return_val_if_fail (account_title, FALSE);
6664
6665         account_mgr = modest_runtime_get_account_mgr();
6666
6667         /* The warning text depends on the account type: */
6668         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6669                                                                   modest_account_mgr_get_store_protocol (account_mgr,
6670                                                                                                          account_name));
6671         txt = modest_protocol_get_translation (protocol,
6672                                                MODEST_PROTOCOL_TRANSLATION_DELETE_MAILBOX,
6673                                                account_title);
6674         if (txt == NULL)
6675                 txt = g_strdup_printf (_("emev_nc_delete_mailbox"), account_title);
6676
6677         response = modest_platform_run_confirmation_dialog (parent_window, txt);
6678         g_free (txt);
6679         txt = NULL;
6680
6681         if (response == GTK_RESPONSE_OK) {
6682                 /* Remove account. If it succeeds then it also removes
6683                    the account from the ModestAccountView: */
6684                 gboolean is_default = FALSE;
6685                 gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr);
6686                 if (default_account_name && (strcmp (default_account_name, account_name) == 0))
6687                         is_default = TRUE;
6688                 g_free (default_account_name);
6689
6690                 removed = modest_account_mgr_remove_account (account_mgr, account_name);
6691                 if (!removed)
6692                         g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__);
6693         }
6694         return removed;
6695 }
6696
6697 void 
6698 modest_ui_actions_on_fetch_images (GtkAction *action,
6699                                    ModestWindow *window)
6700 {
6701         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
6702
6703         modest_msg_view_window_fetch_images (MODEST_MSG_VIEW_WINDOW (window));
6704
6705 }