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