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