Properly handle POP folders in move to dialog (fixes NB#109418)
[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 (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3464             error->code == MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS) {
3465                 message = _CS("ckdg_ib_folder_already_exists");
3466         } else if (error->domain == TNY_ERROR_DOMAIN &&
3467                    error->code == TNY_SERVICE_ERROR_STATE) {
3468                 /* This means that the folder is already in use (a
3469                    message is opened for example */
3470                 message = _("emev_ni_internal_error");
3471         } else {
3472                 message = _CS("ckdg_ib_unable_to_rename");
3473         }
3474
3475         /* We don't set a parent for the dialog because the dialog
3476            will be destroyed so the banner won't appear */
3477         modest_platform_information_banner (NULL, NULL, message);
3478 }
3479
3480 typedef struct {
3481         TnyFolderStore *folder;
3482         gchar *new_name;
3483 } RenameFolderInfo;
3484
3485 static void
3486 on_rename_folder_cb (ModestMailOperation *mail_op,
3487                      TnyFolder *new_folder,
3488                      gpointer user_data)
3489 {
3490         ModestFolderView *folder_view;
3491
3492         /* If the window was closed when renaming a folder, or if
3493          * it's not a main window this will happen */
3494         if (!MODEST_IS_FOLDER_VIEW (user_data))
3495                 return;
3496
3497         folder_view = MODEST_FOLDER_VIEW (user_data);
3498         /* Note that if the rename fails new_folder will be NULL */
3499         if (new_folder) {
3500                 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
3501         } else {
3502                 modest_folder_view_select_first_inbox_or_local (folder_view);
3503         }
3504         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
3505 }
3506
3507 static void
3508 on_rename_folder_performer (gboolean canceled,
3509                             GError *err,
3510                             GtkWindow *parent_window,
3511                             TnyAccount *account,
3512                             gpointer user_data)
3513 {
3514         ModestMailOperation *mail_op = NULL;
3515         GtkTreeSelection *sel = NULL;
3516         GtkWidget *folder_view = NULL;
3517         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
3518
3519         if (canceled || err) {
3520                 /* In memory full conditions we could get this error here */
3521                 check_memory_full_error ((GtkWidget *) parent_window, err);
3522         } else {
3523
3524                 mail_op =
3525                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3526                                         modest_ui_actions_rename_folder_error_handler,
3527                                         parent_window, NULL);
3528
3529                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3530                                 mail_op);
3531
3532                 if (MODEST_IS_MAIN_WINDOW(parent_window)) {
3533
3534                         folder_view = modest_main_window_get_child_widget (
3535                                 MODEST_MAIN_WINDOW (parent_window),
3536                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3537                 }
3538 #ifdef MODEST_TOOLKIT_HILDON2
3539                 else if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3540                         ModestFolderWindow *folder_window = (ModestFolderWindow *) parent_window;
3541                         folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (folder_window));
3542                 }
3543 #endif
3544
3545                 /* Clear the folders view */
3546                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3547                 gtk_tree_selection_unselect_all (sel);
3548
3549                 /* Actually rename the folder */
3550                 modest_mail_operation_rename_folder (mail_op,
3551                                                      TNY_FOLDER (data->folder),
3552                                                      (const gchar *) (data->new_name),
3553                                                      on_rename_folder_cb,
3554                                                      folder_view);
3555                 g_object_unref (mail_op);
3556         }
3557
3558         g_object_unref (data->folder);
3559         g_free (data->new_name);
3560         g_free (data);
3561 }
3562
3563 void
3564 modest_ui_actions_on_rename_folder (GtkAction *action,
3565                                      ModestWindow *window)
3566 {
3567         modest_ui_actions_on_edit_mode_rename_folder (window);
3568 }
3569
3570 gboolean
3571 modest_ui_actions_on_edit_mode_rename_folder (ModestWindow *window)
3572 {
3573         TnyFolderStore *folder;
3574         GtkWidget *folder_view;
3575         gboolean do_rename = TRUE;
3576
3577         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3578
3579         if (MODEST_IS_MAIN_WINDOW (window)) {
3580                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3581                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3582                 if (!folder_view)
3583                         return FALSE;
3584
3585 #ifdef MODEST_TOOLKIT_HILDON2
3586         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3587                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3588 #endif
3589         } else {
3590                 return FALSE;
3591         }
3592
3593         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3594
3595         if (!folder)
3596                 return FALSE;
3597
3598         if (TNY_IS_FOLDER (folder)) {
3599                 gchar *folder_name = NULL;
3600                 gint response;
3601                 const gchar *current_name;
3602                 TnyFolderStore *parent;
3603
3604                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
3605                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
3606                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (window),
3607                                                                      parent, current_name,
3608                                                                      &folder_name);
3609                 g_object_unref (parent);
3610
3611                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
3612                         do_rename = FALSE;
3613                 } else {
3614                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
3615                         rename_folder_data->folder = g_object_ref (folder);
3616                         rename_folder_data->new_name = folder_name;
3617                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(window), TRUE,
3618                                         folder, on_rename_folder_performer, rename_folder_data);
3619                 }
3620         }
3621         g_object_unref (folder);
3622         return do_rename;
3623 }
3624
3625 static void
3626 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3627                                                gpointer user_data)
3628 {
3629         GObject *win = modest_mail_operation_get_source (mail_op);
3630
3631         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3632                                                 _("mail_in_ui_folder_delete_error"),
3633                                                 FALSE);
3634         g_object_unref (win);
3635 }
3636
3637 typedef struct {
3638         TnyFolderStore *folder;
3639         gboolean move_to_trash;
3640 } DeleteFolderInfo;
3641
3642 static void
3643 on_delete_folder_cb (gboolean canceled,
3644                   GError *err,
3645                   GtkWindow *parent_window,
3646                   TnyAccount *account,
3647                   gpointer user_data)
3648 {
3649         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3650         GtkWidget *folder_view;
3651         ModestMailOperation *mail_op;
3652         GtkTreeSelection *sel;
3653
3654         if (!MODEST_IS_WINDOW(parent_window) || canceled || (err!=NULL)) {
3655                 g_object_unref (G_OBJECT (info->folder));
3656                 g_free (info);
3657                 return;
3658         }
3659
3660         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
3661                 folder_view = modest_main_window_get_child_widget (
3662                         MODEST_MAIN_WINDOW (parent_window),
3663                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3664 #ifdef MODEST_TOOLKIT_HILDON2
3665         } else if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3666                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (parent_window)));
3667 #endif
3668         } else {
3669                 g_object_unref (G_OBJECT (info->folder));
3670                 g_free (info);
3671                 return;
3672         }
3673
3674         /* Unselect the folder before deleting it to free the headers */
3675         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3676         gtk_tree_selection_unselect_all (sel);
3677
3678         /* Create the mail operation */
3679         mail_op =
3680                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3681                                 modest_ui_actions_delete_folder_error_handler,
3682                                 NULL, NULL);
3683
3684         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3685                         mail_op);
3686         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3687
3688         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3689
3690         g_object_unref (G_OBJECT (mail_op));
3691         g_object_unref (G_OBJECT (info->folder));
3692         g_free (info);
3693 }
3694
3695 static gboolean
3696 delete_folder (ModestWindow *window, gboolean move_to_trash)
3697 {
3698         TnyFolderStore *folder;
3699         GtkWidget *folder_view;
3700         gint response;
3701         gchar *message;
3702
3703         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3704
3705         if (MODEST_IS_MAIN_WINDOW (window)) {
3706
3707                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3708                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3709 #ifdef MODEST_TOOLKIT_HILDON2
3710         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3711                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3712 #endif
3713         } else {
3714                 return FALSE;
3715         }
3716         if (!folder_view)
3717                 return FALSE;
3718
3719         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3720
3721         if (!folder)
3722                 return FALSE;
3723
3724         /* Show an error if it's an account */
3725         if (!TNY_IS_FOLDER (folder)) {
3726                 modest_platform_run_information_dialog (GTK_WINDOW (window),
3727                                                         _("mail_in_ui_folder_delete_error"),
3728                                                         FALSE);
3729                 g_object_unref (G_OBJECT (folder));
3730                 return FALSE;
3731         }
3732
3733         /* Ask the user */
3734         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"),
3735                                     tny_folder_get_name (TNY_FOLDER (folder)));
3736         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
3737                                                             (const gchar *) message);
3738         g_free (message);
3739
3740         if (response == GTK_RESPONSE_OK) {
3741                 DeleteFolderInfo *info;
3742                 info = g_new0(DeleteFolderInfo, 1);
3743                 info->folder = folder;
3744                 info->move_to_trash = move_to_trash;
3745                 g_object_ref (G_OBJECT (info->folder));
3746                 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder));
3747                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (window),
3748                                                                TRUE,
3749                                                                TNY_FOLDER_STORE (account),
3750                                                                on_delete_folder_cb, info);
3751                 g_object_unref (account);
3752                 return TRUE;
3753         } else {
3754                 return FALSE;
3755         }
3756         g_object_unref (G_OBJECT (folder));
3757 }
3758
3759 void
3760 modest_ui_actions_on_delete_folder (GtkAction *action,
3761                                     ModestWindow *window)
3762 {
3763         modest_ui_actions_on_edit_mode_delete_folder (window);
3764 }
3765
3766 gboolean
3767 modest_ui_actions_on_edit_mode_delete_folder (ModestWindow *window)
3768 {
3769         g_return_val_if_fail (MODEST_IS_WINDOW(window), TRUE);
3770
3771         return delete_folder (window, FALSE);
3772 }
3773
3774 void
3775 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
3776 {
3777         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3778
3779         delete_folder (MODEST_WINDOW (main_window), TRUE);
3780 }
3781
3782
3783 typedef struct _PasswordDialogFields {
3784         GtkWidget *username;
3785         GtkWidget *password;
3786         GtkWidget *dialog;
3787 } PasswordDialogFields;
3788
3789 static void
3790 password_dialog_check_field (GtkEditable *editable,
3791                              PasswordDialogFields *fields)
3792 {
3793         const gchar *value;
3794         gboolean any_value_empty = FALSE;
3795
3796 #ifdef MODEST_TOOLKIT_HILDON2
3797         value = hildon_entry_get_text (HILDON_ENTRY (fields->username));
3798 #else
3799         value = gtk_entry_get_text (GTK_ENTRY (fields->username));
3800 #endif
3801         if ((value == NULL) || value[0] == '\0') {
3802                 any_value_empty = TRUE;
3803         }
3804 #ifdef MODEST_TOOLKIT_HILDON2
3805         value = hildon_entry_get_text (HILDON_ENTRY (fields->password));
3806 #else
3807         value = gtk_entry_get_text (GTK_ENTRY (fields->password));
3808 #endif
3809         if ((value == NULL) || value[0] == '\0') {
3810                 any_value_empty = TRUE;
3811         }
3812         gtk_dialog_set_response_sensitive (GTK_DIALOG (fields->dialog), GTK_RESPONSE_ACCEPT, !any_value_empty);
3813 }
3814
3815 void
3816 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
3817                                          const gchar* server_account_name,
3818                                          gchar **username,
3819                                          gchar **password,
3820                                          gboolean *cancel,
3821                                          gboolean *remember,
3822                                          ModestMainWindow *main_window)
3823 {
3824         g_return_if_fail(server_account_name);
3825         gboolean completed = FALSE;
3826         PasswordDialogFields *fields = NULL;
3827
3828         /* Initalize output parameters: */
3829         if (cancel)
3830                 *cancel = FALSE;
3831
3832         if (remember)
3833                 *remember = TRUE;
3834
3835 #ifndef MODEST_TOOLKIT_GTK
3836         /* Maemo uses a different (awkward) button order,
3837          * It should probably just use gtk_alternative_dialog_button_order ().
3838          */
3839 #ifdef MODEST_TOOLKIT_HILDON2
3840         GtkWidget *dialog =
3841                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3842                                              NULL,
3843                                              GTK_DIALOG_MODAL,
3844                                              _HL("wdgt_bd_done"),
3845                                              GTK_RESPONSE_ACCEPT,
3846                                              NULL);
3847         gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
3848                                         HILDON_MARGIN_DOUBLE);
3849 #else
3850         GtkWidget *dialog =
3851                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3852                                              NULL,
3853                                              GTK_DIALOG_MODAL,
3854                                              _("mcen_bd_dialog_ok"),
3855                                              GTK_RESPONSE_ACCEPT,
3856                                              _("mcen_bd_dialog_cancel"),
3857                                              GTK_RESPONSE_REJECT,
3858                                              NULL);
3859 #endif /* MODEST_TOOLKIT_HILDON2 */
3860 #else
3861         GtkWidget *dialog =
3862                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3863                                              NULL,
3864                                              GTK_DIALOG_MODAL,
3865                                              GTK_STOCK_CANCEL,
3866                                              GTK_RESPONSE_REJECT,
3867                                              GTK_STOCK_OK,
3868                                              GTK_RESPONSE_ACCEPT,
3869                                              NULL);
3870 #endif /* MODEST_TOOLKIT_GTK */
3871
3872         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog), NULL);
3873
3874         gchar *server_name = modest_account_mgr_get_server_account_hostname (
3875                 modest_runtime_get_account_mgr(), server_account_name);
3876         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3877                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3878                 if (cancel)
3879                         *cancel = TRUE;
3880                 gtk_widget_destroy (dialog);
3881                 return;
3882         }
3883
3884         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
3885         GtkWidget *label = gtk_label_new (txt);
3886         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3887         g_free (txt);
3888         g_free (server_name);
3889         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label,
3890                             FALSE, FALSE, 0);
3891         server_name = NULL;
3892
3893         /* username: */
3894         gchar *initial_username = modest_account_mgr_get_server_account_username (
3895                 modest_runtime_get_account_mgr(), server_account_name);
3896
3897 #ifdef MODEST_TOOLKIT_HILDON2
3898         GtkWidget *entry_username = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
3899         if (initial_username)
3900                 hildon_entry_set_text (HILDON_ENTRY (entry_username), initial_username);
3901 #else
3902         GtkWidget *entry_username = gtk_entry_new ();
3903         if (initial_username)
3904                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
3905 #endif
3906         /* Dim this if a connection has ever succeeded with this username,
3907          * as per the UI spec: */
3908         /* const gboolean username_known =  */
3909         /*      modest_account_mgr_get_server_account_username_has_succeeded( */
3910         /*              modest_runtime_get_account_mgr(), server_account_name); */
3911         /* gtk_widget_set_sensitive (entry_username, !username_known); */
3912
3913         /* We drop the username sensitive code and disallow changing it here
3914          * as tinymail does not support really changing the username in the callback
3915          */
3916         gtk_widget_set_sensitive (entry_username, FALSE);
3917
3918 #ifndef MODEST_TOOLKIT_GTK
3919         /* Auto-capitalization is the default, so let's turn it off: */
3920         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
3921
3922         /* Create a size group to be used by all captions.
3923          * Note that HildonCaption does not create a default size group if we do not specify one.
3924          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
3925         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3926
3927 #ifdef MODEST_TOOLKIT_HILDON2
3928         GtkWidget *caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
3929                                                                   _("mail_fi_username"), FALSE,
3930                                                                   entry_username);
3931 #else
3932         GtkWidget *caption = hildon_caption_new (sizegroup,
3933                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
3934 #endif
3935         gtk_widget_show (entry_username);
3936         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
3937                 FALSE, FALSE, MODEST_MARGIN_HALF);
3938         gtk_widget_show (caption);
3939 #else
3940         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
3941                             TRUE, FALSE, 0);
3942 #endif /* !MODEST_TOOLKIT_GTK */
3943
3944         /* password: */
3945 #ifdef MODEST_TOOLKIT_HILDON2
3946         GtkWidget *entry_password = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
3947 #else
3948         GtkWidget *entry_password = gtk_entry_new ();
3949 #endif
3950         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
3951         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
3952
3953 #ifndef MODEST_TOOLKIT_GTK
3954         /* Auto-capitalization is the default, so let's turn it off: */
3955         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
3956                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
3957
3958 #ifdef MODEST_TOOLKIT_HILDON2
3959         caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
3960                                                        _("mail_fi_password"), FALSE,
3961                                                        entry_password);
3962 #else
3963         caption = hildon_caption_new (sizegroup,
3964                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
3965 #endif
3966         gtk_widget_show (entry_password);
3967         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
3968                 FALSE, FALSE, MODEST_MARGIN_HALF);
3969         gtk_widget_show (caption);
3970         g_object_unref (sizegroup);
3971 #else
3972         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
3973                             TRUE, FALSE, 0);
3974 #endif /* !MODEST_TOOLKIT_GTK */
3975
3976         if (initial_username != NULL)
3977                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
3978
3979 /* This is not in the Maemo UI spec:
3980         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
3981         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
3982                             TRUE, FALSE, 0);
3983 */
3984
3985         fields = g_slice_new0 (PasswordDialogFields);
3986         fields->username = entry_username;
3987         fields->password = entry_password;
3988         fields->dialog = dialog;
3989
3990         g_signal_connect (entry_username, "changed", G_CALLBACK (password_dialog_check_field), fields);
3991         g_signal_connect (entry_password, "changed", G_CALLBACK (password_dialog_check_field), fields);
3992         password_dialog_check_field (NULL, fields);
3993
3994         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3995
3996         while (!completed) {
3997
3998                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
3999                         if (username) {
4000 #ifdef MODEST_TOOLKIT_HILDON2
4001                                 *username = g_strdup (hildon_entry_get_text (HILDON_ENTRY(entry_username)));
4002 #else
4003                                 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
4004 #endif
4005
4006                                 /* Note that an empty field becomes the "" string */
4007                                 if (*username && strlen (*username) > 0) {
4008                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(),
4009                                                                                         server_account_name,
4010                                                                                         *username);
4011                                         completed = TRUE;
4012
4013                                         const gboolean username_was_changed =
4014                                                 (strcmp (*username, initial_username) != 0);
4015                                         if (username_was_changed) {
4016                                                 g_warning ("%s: tinymail does not yet support changing the "
4017                                                            "username in the get_password() callback.\n", __FUNCTION__);
4018                                         }
4019                                 } else {
4020                                         g_free (*username);
4021                                         *username = NULL;
4022                                         /* Show error */
4023                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL,
4024                                                                             _("mcen_ib_username_pw_incorrect"));
4025                                         completed = FALSE;
4026                                 }
4027                         }
4028
4029                         if (password) {
4030 #ifdef MODEST_TOOLKIT_HILDON2
4031                                 *password = g_strdup (hildon_entry_get_text (HILDON_ENTRY(entry_password)));
4032 #else
4033                                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
4034 #endif
4035
4036                                 /* We do not save the password in the configuration,
4037                                  * because this function is only called for passwords that should
4038                                  * not be remembered:
4039                                  modest_server_account_set_password (
4040                                  modest_runtime_get_account_mgr(), server_account_name,
4041                                  *password);
4042                                  */
4043                         }
4044                         if (cancel)
4045                                 *cancel   = FALSE;
4046                 } else {
4047 #ifndef MODEST_TOOLKIT_HILDON2
4048                         /* Set parent to NULL or the banner will disappear with its parent dialog */
4049                         modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
4050 #endif
4051                         completed = TRUE;
4052                         if (username)
4053                                 *username = NULL;
4054                         if (password)
4055                                 *password = NULL;
4056                         if (cancel)
4057                                 *cancel   = TRUE;
4058                 }
4059         }
4060
4061 /* This is not in the Maemo UI spec:
4062         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
4063                 *remember = TRUE;
4064         else
4065                 *remember = FALSE;
4066 */
4067
4068         g_free (initial_username);
4069         gtk_widget_destroy (dialog);
4070         g_slice_free (PasswordDialogFields, fields);
4071
4072         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
4073 }
4074
4075 void
4076 modest_ui_actions_on_cut (GtkAction *action,
4077                           ModestWindow *window)
4078 {
4079         GtkWidget *focused_widget;
4080         GtkClipboard *clipboard;
4081
4082         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4083         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4084         if (GTK_IS_EDITABLE (focused_widget)) {
4085                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
4086                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4087                 gtk_clipboard_store (clipboard);
4088         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4089                 GtkTextBuffer *buffer;
4090
4091                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4092                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4093                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
4094                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4095                         gtk_clipboard_store (clipboard);
4096                 }
4097         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4098                 TnyList *header_list = modest_header_view_get_selected_headers (
4099                                 MODEST_HEADER_VIEW (focused_widget));
4100                 gboolean continue_download = FALSE;
4101                 gint num_of_unc_msgs;
4102
4103                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4104
4105                 if (num_of_unc_msgs) {
4106                         TnyAccount *account = get_account_from_header_list (header_list);
4107                         if (account) {
4108                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4109                                 g_object_unref (account);
4110                         }
4111                 }
4112
4113                 if (num_of_unc_msgs == 0 || continue_download) {
4114 /*                      modest_platform_information_banner (
4115                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
4116                         modest_header_view_cut_selection (
4117                                         MODEST_HEADER_VIEW (focused_widget));
4118                 }
4119
4120                 g_object_unref (header_list);
4121         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4122                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
4123         }
4124 }
4125
4126 void
4127 modest_ui_actions_on_copy (GtkAction *action,
4128                            ModestWindow *window)
4129 {
4130         GtkClipboard *clipboard;
4131         GtkWidget *focused_widget;
4132         gboolean copied = TRUE;
4133
4134         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4135         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4136
4137         if (GTK_IS_LABEL (focused_widget)) {
4138                 gchar *selection;
4139                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
4140                 gtk_clipboard_set_text (clipboard, selection, -1);
4141                 g_free (selection);
4142                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4143                 gtk_clipboard_store (clipboard);
4144         } else if (GTK_IS_EDITABLE (focused_widget)) {
4145                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
4146                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4147                 gtk_clipboard_store (clipboard);
4148         } else if (GTK_IS_HTML (focused_widget)) {
4149                 const gchar *sel;
4150                 int len = -1;
4151                 sel = gtk_html_get_selection_html (GTK_HTML (focused_widget), &len);
4152                 if ((sel == NULL) || (sel[0] == '\0')) {
4153                         copied = FALSE;
4154                 } else {
4155                         gtk_html_copy (GTK_HTML (focused_widget));
4156                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4157                         gtk_clipboard_store (clipboard);
4158                 }
4159         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4160                 GtkTextBuffer *buffer;
4161                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4162                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4163                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
4164                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4165                         gtk_clipboard_store (clipboard);
4166                 }
4167         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4168                 TnyList *header_list = modest_header_view_get_selected_headers (
4169                                 MODEST_HEADER_VIEW (focused_widget));
4170                 gboolean continue_download = FALSE;
4171                 gint num_of_unc_msgs;
4172
4173                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4174
4175                 if (num_of_unc_msgs) {
4176                         TnyAccount *account = get_account_from_header_list (header_list);
4177                         if (account) {
4178                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4179                                 g_object_unref (account);
4180                         }
4181                 }
4182
4183                 if (num_of_unc_msgs == 0 || continue_download) {
4184                         modest_platform_information_banner (
4185                                         NULL, NULL, _CS("mcen_ib_getting_items"));
4186                         modest_header_view_copy_selection (
4187                                         MODEST_HEADER_VIEW (focused_widget));
4188                 } else
4189                         copied = FALSE;
4190
4191                 g_object_unref (header_list);
4192
4193         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4194                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
4195         }
4196
4197         /* Show information banner if there was a copy to clipboard */
4198         if(copied)
4199                 modest_platform_information_banner (
4200                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
4201 }
4202
4203 void
4204 modest_ui_actions_on_undo (GtkAction *action,
4205                            ModestWindow *window)
4206 {
4207         ModestEmailClipboard *clipboard = NULL;
4208
4209         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4210                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
4211         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4212                 /* Clear clipboard source */
4213                 clipboard = modest_runtime_get_email_clipboard ();
4214                 modest_email_clipboard_clear (clipboard);
4215         }
4216         else {
4217                 g_return_if_reached ();
4218         }
4219 }
4220
4221 void
4222 modest_ui_actions_on_redo (GtkAction *action,
4223                            ModestWindow *window)
4224 {
4225         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4226                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
4227         }
4228         else {
4229                 g_return_if_reached ();
4230         }
4231 }
4232
4233
4234 static void
4235 destroy_information_note (ModestMailOperation *mail_op,
4236                           gpointer user_data)
4237 {
4238         /* destroy information note */
4239         gtk_widget_destroy (GTK_WIDGET(user_data));
4240 }
4241
4242 static void
4243 destroy_folder_information_note (ModestMailOperation *mail_op,
4244                                  TnyFolder *new_folder,
4245                                  gpointer user_data)
4246 {
4247         /* destroy information note */
4248         gtk_widget_destroy (GTK_WIDGET(user_data));
4249 }
4250
4251
4252 static void
4253 paste_as_attachment_free (gpointer data)
4254 {
4255         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
4256
4257         if (helper->banner) {
4258                 gtk_widget_destroy (helper->banner);
4259                 g_object_unref (helper->banner);
4260         }
4261         g_free (helper);
4262 }
4263
4264 static void
4265 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
4266                             TnyHeader *header,
4267                             TnyMsg *msg,
4268                             gpointer userdata)
4269 {
4270         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
4271         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
4272
4273         if (msg == NULL)
4274                 return;
4275
4276         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
4277
4278 }
4279
4280 void
4281 modest_ui_actions_on_paste (GtkAction *action,
4282                             ModestWindow *window)
4283 {
4284         GtkWidget *focused_widget = NULL;
4285         GtkWidget *inf_note = NULL;
4286         ModestMailOperation *mail_op = NULL;
4287
4288         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4289         if (GTK_IS_EDITABLE (focused_widget)) {
4290                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
4291         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4292                 ModestEmailClipboard *e_clipboard = NULL;
4293                 e_clipboard = modest_runtime_get_email_clipboard ();
4294                 if (modest_email_clipboard_cleared (e_clipboard)) {
4295                         GtkTextBuffer *buffer;
4296                         GtkClipboard *clipboard;
4297
4298                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4299                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4300                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
4301                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4302                         ModestMailOperation *mail_op;
4303                         TnyFolder *src_folder = NULL;
4304                         TnyList *data = NULL;
4305                         gboolean delete;
4306                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
4307                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
4308                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4309                                                                            _CS("ckct_nw_pasting"));
4310                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
4311                         mail_op = modest_mail_operation_new (G_OBJECT (window));
4312                         if (helper->banner != NULL) {
4313                                 g_object_ref (G_OBJECT (helper->banner));
4314                                 gtk_widget_show (GTK_WIDGET (helper->banner));
4315                         }
4316
4317                         if (data != NULL) {
4318                                 modest_mail_operation_get_msgs_full (mail_op,
4319                                                                      data,
4320                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
4321                                                                      helper,
4322                                                                      paste_as_attachment_free);
4323                         }
4324                         /* Free */
4325                         if (data)
4326                                 g_object_unref (data);
4327                         if (src_folder)
4328                                 g_object_unref (src_folder);
4329
4330                 }
4331         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4332                 ModestEmailClipboard *clipboard = NULL;
4333                 TnyFolder *src_folder = NULL;
4334                 TnyFolderStore *folder_store = NULL;
4335                 TnyList *data = NULL;
4336                 gboolean delete = FALSE;
4337
4338                 /* Check clipboard source */
4339                 clipboard = modest_runtime_get_email_clipboard ();
4340                 if (modest_email_clipboard_cleared (clipboard))
4341                         return;
4342
4343                 /* Get elements to paste */
4344                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
4345
4346                 /* Create a new mail operation */
4347                 mail_op = modest_mail_operation_new (G_OBJECT(window));
4348
4349                 /* Get destination folder */
4350                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
4351
4352                 /* transfer messages  */
4353                 if (data != NULL) {
4354                         gint response = 0;
4355
4356                         /* Ask for user confirmation */
4357                         response =
4358                                 modest_ui_actions_msgs_move_to_confirmation (window,
4359                                                                              TNY_FOLDER (folder_store),
4360                                                                              delete,
4361                                                                              data);
4362
4363                         if (response == GTK_RESPONSE_OK) {
4364                                 /* Launch notification */
4365                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4366                                                                              _CS("ckct_nw_pasting"));
4367                                 if (inf_note != NULL)  {
4368                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4369                                         gtk_widget_show (GTK_WIDGET(inf_note));
4370                                 }
4371
4372                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4373                                 modest_mail_operation_xfer_msgs (mail_op,
4374                                                                  data,
4375                                                                  TNY_FOLDER (folder_store),
4376                                                                  delete,
4377                                                                  destroy_information_note,
4378                                                                  inf_note);
4379                         } else {
4380                                 g_object_unref (mail_op);
4381                         }
4382
4383                 } else if (src_folder != NULL) {
4384                         /* Launch notification */
4385                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4386                                                                      _CS("ckct_nw_pasting"));
4387                         if (inf_note != NULL)  {
4388                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4389                                 gtk_widget_show (GTK_WIDGET(inf_note));
4390                         }
4391
4392                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4393                         modest_mail_operation_xfer_folder (mail_op,
4394                                                            src_folder,
4395                                                            folder_store,
4396                                                            delete,
4397                                                            destroy_folder_information_note,
4398                                                            inf_note);
4399                 }
4400
4401                 /* Free */
4402                 if (data != NULL)
4403                         g_object_unref (data);
4404                 if (src_folder != NULL)
4405                         g_object_unref (src_folder);
4406                 if (folder_store != NULL)
4407                         g_object_unref (folder_store);
4408         }
4409 }
4410
4411
4412 void
4413 modest_ui_actions_on_select_all (GtkAction *action,
4414                                  ModestWindow *window)
4415 {
4416         GtkWidget *focused_widget;
4417
4418         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4419         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
4420                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
4421         } else if (GTK_IS_LABEL (focused_widget)) {
4422                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
4423         } else if (GTK_IS_EDITABLE (focused_widget)) {
4424                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
4425         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4426                 GtkTextBuffer *buffer;
4427                 GtkTextIter start, end;
4428
4429                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4430                 gtk_text_buffer_get_start_iter (buffer, &start);
4431                 gtk_text_buffer_get_end_iter (buffer, &end);
4432                 gtk_text_buffer_select_range (buffer, &start, &end);
4433         } else if (GTK_IS_HTML (focused_widget)) {
4434                 gtk_html_select_all (GTK_HTML (focused_widget));
4435         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4436                 GtkWidget *header_view = focused_widget;
4437                 GtkTreeSelection *selection = NULL;
4438
4439                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
4440                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4441                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4442                 }
4443
4444                 /* Disable window dimming management */
4445                 modest_window_disable_dimming (MODEST_WINDOW(window));
4446
4447                 /* Select all messages */
4448                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
4449                 gtk_tree_selection_select_all (selection);
4450
4451                 /* Set focuse on header view */
4452                 gtk_widget_grab_focus (header_view);
4453
4454                 /* Enable window dimming management */
4455                 modest_window_enable_dimming (MODEST_WINDOW(window));
4456                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
4457                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
4458         }
4459
4460 }
4461
4462 void
4463 modest_ui_actions_on_mark_as_read (GtkAction *action,
4464                                    ModestWindow *window)
4465 {
4466         g_return_if_fail (MODEST_IS_WINDOW(window));
4467
4468         /* Mark each header as read */
4469         do_headers_action (window, headers_action_mark_as_read, NULL);
4470 }
4471
4472 void
4473 modest_ui_actions_on_mark_as_unread (GtkAction *action,
4474                                      ModestWindow *window)
4475 {
4476         g_return_if_fail (MODEST_IS_WINDOW(window));
4477
4478         /* Mark each header as read */
4479         do_headers_action (window, headers_action_mark_as_unread, NULL);
4480 }
4481
4482 void
4483 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
4484                                   GtkRadioAction *selected,
4485                                   ModestWindow *window)
4486 {
4487         gint value;
4488
4489         value = gtk_radio_action_get_current_value (selected);
4490         if (MODEST_IS_WINDOW (window)) {
4491                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
4492         }
4493 }
4494
4495 void
4496 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
4497                                                GtkRadioAction *selected,
4498                                                ModestWindow *window)
4499 {
4500         TnyHeaderFlags flags;
4501         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4502
4503         flags = gtk_radio_action_get_current_value (selected);
4504         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
4505 }
4506
4507 void
4508 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
4509                                                   GtkRadioAction *selected,
4510                                                   ModestWindow *window)
4511 {
4512         gint file_format;
4513
4514         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4515
4516         file_format = gtk_radio_action_get_current_value (selected);
4517         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
4518 }
4519
4520
4521 void
4522 modest_ui_actions_on_zoom_plus (GtkAction *action,
4523                                 ModestWindow *window)
4524 {
4525         g_return_if_fail (MODEST_IS_WINDOW (window));
4526
4527         modest_window_zoom_plus (MODEST_WINDOW (window));
4528 }
4529
4530 void
4531 modest_ui_actions_on_zoom_minus (GtkAction *action,
4532                                  ModestWindow *window)
4533 {
4534         g_return_if_fail (MODEST_IS_WINDOW (window));
4535
4536         modest_window_zoom_minus (MODEST_WINDOW (window));
4537 }
4538
4539 void
4540 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
4541                                            ModestWindow *window)
4542 {
4543         ModestWindowMgr *mgr;
4544         gboolean fullscreen, active;
4545         g_return_if_fail (MODEST_IS_WINDOW (window));
4546
4547         mgr = modest_runtime_get_window_mgr ();
4548
4549         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4550         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4551
4552         if (active != fullscreen) {
4553                 modest_window_mgr_set_fullscreen_mode (mgr, active);
4554 #ifndef MODEST_TOOLKIT_HILDON2
4555                 gtk_window_present (GTK_WINDOW (window));
4556 #endif
4557         }
4558 }
4559
4560 void
4561 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4562                                         ModestWindow *window)
4563 {
4564         ModestWindowMgr *mgr;
4565         gboolean fullscreen;
4566
4567         g_return_if_fail (MODEST_IS_WINDOW (window));
4568
4569         mgr = modest_runtime_get_window_mgr ();
4570         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4571         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4572
4573 #ifndef MODEST_TOOLKIT_HILDON2
4574         gtk_window_present (GTK_WINDOW (window));
4575 #endif
4576 }
4577
4578 /*
4579  * Used by modest_ui_actions_on_details to call do_headers_action
4580  */
4581 static void
4582 headers_action_show_details (TnyHeader *header,
4583                              ModestWindow *window,
4584                              gpointer user_data)
4585
4586 {
4587         modest_platform_run_header_details_dialog (GTK_WINDOW (window), header);
4588 }
4589
4590 /*
4591  * Show the header details in a ModestDetailsDialog widget
4592  */
4593 void
4594 modest_ui_actions_on_details (GtkAction *action,
4595                               ModestWindow *win)
4596 {
4597         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4598                 TnyMsg *msg;
4599                 TnyHeader *header;
4600
4601                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4602                 if (!msg)
4603                         return;
4604
4605                 header = tny_msg_get_header (msg);
4606                 if (header) {
4607                         headers_action_show_details (header, win, NULL);
4608                         g_object_unref (header);
4609                 }
4610                 g_object_unref (msg);
4611
4612         } else if (MODEST_IS_MAIN_WINDOW (win)) {
4613                 GtkWidget *folder_view, *header_view;
4614
4615                 /* Check which widget has the focus */
4616                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4617                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4618                 if (gtk_widget_is_focus (folder_view)) {
4619                         TnyFolderStore *folder_store
4620                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4621                         if (!folder_store) {
4622                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4623                                 return;
4624                         }
4625                         /* Show only when it's a folder */
4626                         /* This function should not be called for account items,
4627                          * because we dim the menu item for them. */
4628                         if (TNY_IS_FOLDER (folder_store)) {
4629                                 modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4630                                                                            TNY_FOLDER (folder_store));
4631                         }
4632
4633                         g_object_unref (folder_store);
4634
4635                 } else {
4636                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4637                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4638                         /* Show details of each header */
4639                         do_headers_action (win, headers_action_show_details, header_view);
4640                 }
4641 #ifdef MODEST_TOOLKIT_HILDON2
4642         } else if (MODEST_IS_HEADER_WINDOW (win)) {
4643                 TnyFolder *folder;
4644                 GtkWidget *header_view;
4645
4646                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
4647                 folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
4648                 if (folder) {
4649                         modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4650                                                                    folder);
4651                         g_object_unref (folder);
4652                 }
4653 #endif
4654         }
4655 }
4656
4657 void
4658 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4659                                      ModestMsgEditWindow *window)
4660 {
4661         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4662
4663         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4664 }
4665
4666 void
4667 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4668                                       ModestMsgEditWindow *window)
4669 {
4670         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4671
4672         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4673 }
4674
4675 void
4676 modest_ui_actions_toggle_folders_view (GtkAction *action,
4677                                        ModestMainWindow *main_window)
4678 {
4679         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4680
4681         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4682                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4683         else
4684                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4685 }
4686
4687 void
4688 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
4689                                      ModestWindow *window)
4690 {
4691         gboolean active, fullscreen = FALSE;
4692         ModestWindowMgr *mgr;
4693
4694         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4695
4696         /* Check if we want to toggle the toolbar view in fullscreen
4697            or normal mode */
4698         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
4699                      "ViewShowToolbarFullScreen")) {
4700                 fullscreen = TRUE;
4701         }
4702
4703         /* Toggle toolbar */
4704         mgr = modest_runtime_get_window_mgr ();
4705         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4706 }
4707
4708 void
4709 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4710                                            ModestMsgEditWindow *window)
4711 {
4712         modest_msg_edit_window_select_font (window);
4713 }
4714
4715
4716 void
4717 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4718                                                   const gchar *display_name,
4719                                                   GtkWindow *window)
4720 {
4721         /* don't update the display name if it was already set;
4722          * updating the display name apparently is expensive */
4723         const gchar* old_name = gtk_window_get_title (window);
4724
4725         if (display_name == NULL)
4726                 display_name = " ";
4727
4728         if (old_name && display_name && strcmp (old_name, display_name) == 0)
4729                 return; /* don't do anything */
4730
4731         /* This is usually used to change the title of the main window, which
4732          * is the one that holds the folder view. Note that this change can
4733          * happen even when the widget doesn't have the focus. */
4734         gtk_window_set_title (window, display_name);
4735
4736 }
4737
4738 void
4739 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4740 {
4741         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4742         modest_msg_edit_window_select_contacts (window);
4743 }
4744
4745 void
4746 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4747 {
4748         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4749         modest_msg_edit_window_check_names (window, FALSE);
4750 }
4751
4752 #ifndef MODEST_TOOLKIT_HILDON2
4753 /*
4754  * This function is used to track changes in the selection of the
4755  * folder view that is inside the "move to" dialog to enable/disable
4756  * the OK button because we do not want the user to select a disallowed
4757  * destination for a folder.
4758  * The user also not desired to be able to use NEW button on items where
4759  * folder creation is not possibel.
4760  */
4761 static void
4762 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4763                                             TnyFolderStore *folder_store,
4764                                             gboolean selected,
4765                                             gpointer user_data)
4766 {
4767         GtkWidget *dialog = NULL;
4768         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4769         gboolean moving_folder = FALSE;
4770         gboolean is_local_account = TRUE;
4771         GtkWidget *folder_view = NULL;
4772         ModestTnyFolderRules rules;
4773
4774         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4775
4776         if (!selected)
4777                 return;
4778
4779         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4780         if (!dialog)
4781                 return;
4782
4783         /* check if folder_store is an remote account */
4784         if (TNY_IS_ACCOUNT (folder_store)) {
4785                 TnyAccount *local_account = NULL;
4786                 TnyAccount *mmc_account = NULL;
4787                 ModestTnyAccountStore *account_store = NULL;
4788
4789                 account_store = modest_runtime_get_account_store ();
4790                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4791                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4792
4793                 if ((gpointer) local_account != (gpointer) folder_store &&
4794                     (gpointer) mmc_account != (gpointer) folder_store) {
4795                         ModestProtocolType proto;
4796                         proto = modest_tny_account_get_protocol_type (TNY_ACCOUNT (folder_store));
4797                         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
4798                                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
4799                         }
4800                         is_local_account = FALSE;
4801                         /* New button should be dimmed on remote
4802                            POP account root */
4803                         new_sensitive = (modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
4804                                                                                          proto,
4805                                                                                          MODEST_PROTOCOL_REGISTRY_STORE_HAS_FOLDERS));
4806                 }
4807                 g_object_unref (local_account);
4808
4809                 /* It could not exist */
4810                 if (mmc_account)
4811                         g_object_unref (mmc_account);
4812         }
4813
4814         /* Check the target folder rules */
4815         if (TNY_IS_FOLDER (folder_store)) {
4816                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
4817                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
4818                         ok_sensitive = FALSE;
4819                         new_sensitive = FALSE;
4820                         goto end;
4821                 }
4822         }
4823
4824         /* Check if we're moving a folder */
4825         if (MODEST_IS_MAIN_WINDOW (user_data)) {
4826                 /* Get the widgets */
4827                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
4828                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4829                 if (gtk_widget_is_focus (folder_view))
4830                         moving_folder = TRUE;
4831         }
4832
4833         if (moving_folder) {
4834                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
4835
4836                 /* Get the folder to move */
4837                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4838
4839                 /* Check that we're not moving to the same folder */
4840                 if (TNY_IS_FOLDER (moved_folder)) {
4841                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
4842                         if (parent == folder_store)
4843                                 ok_sensitive = FALSE;
4844                         g_object_unref (parent);
4845                 }
4846
4847                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
4848                         /* Do not allow to move to an account unless it's the
4849                            local folders account */
4850                         if (!is_local_account)
4851                                 ok_sensitive = FALSE;
4852                 }
4853
4854                 if (ok_sensitive && (moved_folder == folder_store)) {
4855                         /* Do not allow to move to itself */
4856                         ok_sensitive = FALSE;
4857                 }
4858                 g_object_unref (moved_folder);
4859         } else {
4860                 TnyFolder *src_folder = NULL;
4861
4862                 /* Moving a message */
4863                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
4864
4865                         TnyHeader *header = NULL;
4866                         header = modest_msg_view_window_get_header
4867                                 (MODEST_MSG_VIEW_WINDOW (user_data));
4868                         if (!TNY_IS_HEADER(header))
4869                                 g_warning ("%s: could not get source header", __FUNCTION__);
4870                         else
4871                                 src_folder = tny_header_get_folder (header);
4872
4873                         if (header)
4874                                 g_object_unref (header);
4875                 } else {
4876                         src_folder =
4877                                 TNY_FOLDER (modest_folder_view_get_selected
4878                                             (MODEST_FOLDER_VIEW (folder_view)));
4879                 }
4880
4881                 if (TNY_IS_FOLDER(src_folder)) {
4882                         /* Do not allow to move the msg to the same folder */
4883                         /* Do not allow to move the msg to an account */
4884                         if ((gpointer) src_folder == (gpointer) folder_store ||
4885                             TNY_IS_ACCOUNT (folder_store))
4886                                 ok_sensitive = FALSE;
4887                         g_object_unref (src_folder);
4888                 } else
4889                         g_warning ("%s: could not get source folder", __FUNCTION__);
4890         }
4891
4892  end:
4893         /* Set sensitivity of the OK and NEW button */
4894         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, ok_sensitive);
4895         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), MODEST_GTK_RESPONSE_NEW_FOLDER, new_sensitive);
4896 }
4897 #endif
4898
4899 static void
4900 on_move_to_dialog_response (GtkDialog *dialog,
4901                             gint       response,
4902                             gpointer   user_data)
4903 {
4904         GtkWidget *parent_win;
4905         MoveToInfo *helper = NULL;
4906         ModestFolderView *folder_view;
4907
4908         helper = (MoveToInfo *) user_data;
4909
4910         parent_win = (GtkWidget *) helper->win;
4911         folder_view = MODEST_FOLDER_VIEW (g_object_get_data (G_OBJECT (dialog),
4912                                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4913
4914         switch (response) {
4915                 TnyFolderStore *dst_folder;
4916
4917         case MODEST_GTK_RESPONSE_NEW_FOLDER:
4918                 modest_ui_actions_create_folder (GTK_WIDGET (dialog), GTK_WIDGET (folder_view));
4919                 return;
4920         case GTK_RESPONSE_NONE:
4921         case GTK_RESPONSE_CANCEL:
4922         case GTK_RESPONSE_DELETE_EVENT:
4923                 break;
4924         case GTK_RESPONSE_OK:
4925                 dst_folder = modest_folder_view_get_selected (folder_view);
4926
4927                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
4928                         /* Clean list to move used for filtering */
4929                         modest_folder_view_set_list_to_move (folder_view, NULL);
4930
4931                         modest_ui_actions_on_main_window_move_to (NULL,
4932                                                                   GTK_WIDGET (folder_view),
4933                                                                   dst_folder,
4934                                                                   MODEST_MAIN_WINDOW (parent_win));
4935 #ifdef MODEST_TOOLKIT_HILDON2
4936                 } else if (MODEST_IS_FOLDER_WINDOW (parent_win)) {
4937                         /* Clean list to move used for filtering */
4938                         modest_folder_view_set_list_to_move (folder_view, NULL);
4939
4940                         modest_ui_actions_on_folder_window_move_to (GTK_WIDGET (folder_view),
4941                                                                     dst_folder,
4942                                                                     helper->list,
4943                                                                     GTK_WINDOW (parent_win));
4944 #endif
4945                 } else {
4946                         /* if the user selected a root folder
4947                            (account) then do not perform any action */
4948                         if (TNY_IS_ACCOUNT (dst_folder)) {
4949                                 g_signal_stop_emission_by_name (dialog, "response");
4950                                 return;
4951                         }
4952
4953                         /* Clean list to move used for filtering */
4954                         modest_folder_view_set_list_to_move (folder_view, NULL);
4955
4956                         /* Moving from headers window in edit mode */
4957                         modest_ui_actions_on_window_move_to (NULL, helper->list,
4958                                                              dst_folder,
4959                                                              MODEST_WINDOW (parent_win));
4960                 }
4961
4962                 if (dst_folder)
4963                         g_object_unref (dst_folder);
4964
4965                 break;
4966         default:
4967                 g_warning ("%s unexpected response id %d", __FUNCTION__, response);
4968         }
4969
4970         /* Free the helper and exit */
4971         if (helper->list)
4972                 g_object_unref (helper->list);
4973         g_slice_free (MoveToInfo, helper);
4974         gtk_widget_destroy (GTK_WIDGET (dialog));
4975 }
4976
4977 static GtkWidget*
4978 create_move_to_dialog (GtkWindow *win,
4979                        GtkWidget *folder_view,
4980                        TnyList *list_to_move)
4981 {
4982         GtkWidget *dialog, *tree_view = NULL;
4983
4984         dialog = modest_platform_create_move_to_dialog (win, &tree_view);
4985
4986 #ifndef MODEST_TOOLKIT_HILDON2
4987         /* Track changes in the selection to
4988          * disable the OK button whenever "Move to" is not possible
4989          * disbale NEW button whenever New is not possible */
4990         g_signal_connect (tree_view,
4991                           "folder_selection_changed",
4992                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
4993                           win);
4994 #endif
4995
4996         /* It could happen that we're trying to move a message from a
4997            window (msg window for example) after the main window was
4998            closed, so we can not just get the model of the folder
4999            view */
5000         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
5001                 const gchar *visible_id = NULL;
5002
5003                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5004                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5005                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
5006                                                MODEST_FOLDER_VIEW(tree_view));
5007
5008                 visible_id =
5009                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
5010
5011                 /* Show the same account than the one that is shown in the main window */
5012                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(tree_view),
5013                                                                              visible_id);
5014         } else {
5015                 const gchar *active_account_name = NULL;
5016                 ModestAccountMgr *mgr = NULL;
5017                 ModestAccountSettings *settings = NULL;
5018                 ModestServerAccountSettings *store_settings = NULL;
5019
5020                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5021                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5022                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (tree_view),
5023                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
5024
5025                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
5026                 mgr = modest_runtime_get_account_mgr ();
5027                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
5028
5029                 if (settings) {
5030                         const gchar *store_account_name;
5031                         store_settings = modest_account_settings_get_store_settings (settings);
5032                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
5033
5034                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (tree_view),
5035                                                                                      store_account_name);
5036                         g_object_unref (store_settings);
5037                         g_object_unref (settings);
5038                 }
5039         }
5040
5041         /* we keep a pointer to the embedded folder view, so we can
5042          *   retrieve it with get_folder_view_from_move_to_dialog (see
5043          *   above) later (needed for focus handling)
5044          */
5045         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, tree_view);
5046
5047         /* Hide special folders */
5048 #ifndef MODEST_TOOLKIT_HILDON2
5049         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (tree_view), FALSE);
5050 #endif
5051         if (list_to_move)
5052                 modest_folder_view_set_list_to_move (MODEST_FOLDER_VIEW (tree_view), list_to_move);
5053 #ifndef MODEST_TOOLKIT_HILDON2
5054         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5055 #endif
5056
5057         gtk_widget_show (GTK_WIDGET (tree_view));
5058
5059         return dialog;
5060 }
5061
5062 /*
5063  * Shows a confirmation dialog to the user when we're moving messages
5064  * from a remote server to the local storage. Returns the dialog
5065  * response. If it's other kind of movement then it always returns
5066  * GTK_RESPONSE_OK
5067  *
5068  * This one is used by the next functions:
5069  *      modest_ui_actions_on_paste                      - commented out
5070  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
5071  */
5072 gint
5073 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
5074                                              TnyFolder *dest_folder,
5075                                              gboolean delete,
5076                                              TnyList *headers)
5077 {
5078         gint response = GTK_RESPONSE_OK;
5079         TnyAccount *account = NULL;
5080         TnyFolder *src_folder = NULL;
5081         TnyIterator *iter = NULL;
5082         TnyHeader *header = NULL;
5083
5084         /* return with OK if the destination is a remote folder */
5085         if (modest_tny_folder_is_remote_folder (dest_folder))
5086                 return GTK_RESPONSE_OK;
5087
5088         /* Get source folder */
5089         iter = tny_list_create_iterator (headers);
5090         header = TNY_HEADER (tny_iterator_get_current (iter));
5091         if (header) {
5092                 src_folder = tny_header_get_folder (header);
5093                 g_object_unref (header);
5094         }
5095         g_object_unref (iter);
5096
5097         /* if no src_folder, message may be an attahcment */
5098         if (src_folder == NULL)
5099                 return GTK_RESPONSE_CANCEL;
5100
5101         /* If the source is a local or MMC folder */
5102         if (!modest_tny_folder_is_remote_folder (src_folder)) {
5103                 g_object_unref (src_folder);
5104                 return GTK_RESPONSE_OK;
5105         }
5106
5107         /* Get the account */
5108         account = tny_folder_get_account (src_folder);
5109
5110         /* now if offline we ask the user */
5111         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
5112                 response = GTK_RESPONSE_OK;
5113         else
5114                 response = GTK_RESPONSE_CANCEL;
5115
5116         /* Frees */
5117         g_object_unref (src_folder);
5118         g_object_unref (account);
5119
5120         return response;
5121 }
5122
5123 static void
5124 move_to_helper_destroyer (gpointer user_data)
5125 {
5126         MoveToHelper *helper = (MoveToHelper *) user_data;
5127
5128         /* Close the "Pasting" information banner */
5129         if (helper->banner) {
5130                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
5131                 g_object_unref (helper->banner);
5132         }
5133         if (gtk_tree_row_reference_valid (helper->reference)) {
5134                 gtk_tree_row_reference_free (helper->reference);
5135                 helper->reference = NULL;
5136         }
5137         g_free (helper);
5138 }
5139
5140 static void
5141 move_to_cb (ModestMailOperation *mail_op,
5142             gpointer user_data)
5143 {
5144         MoveToHelper *helper = (MoveToHelper *) user_data;
5145         GObject *object = modest_mail_operation_get_source (mail_op);
5146
5147         /* Note that the operation could have failed, in that case do
5148            nothing */
5149         if (modest_mail_operation_get_status (mail_op) !=
5150             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5151                 goto frees;
5152
5153         if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
5154                 ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
5155
5156                 if (!modest_msg_view_window_select_next_message (self) &&
5157                     !modest_msg_view_window_select_previous_message (self)) {
5158                         /* No more messages to view, so close this window */
5159                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
5160                 }
5161         } else if (MODEST_IS_MAIN_WINDOW (object) &&
5162                    gtk_tree_row_reference_valid (helper->reference)) {
5163                 GtkWidget *header_view;
5164                 GtkTreePath *path;
5165                 GtkTreeSelection *sel;
5166
5167                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5168                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5169                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
5170                 path = gtk_tree_row_reference_get_path (helper->reference);
5171                 /* We need to unselect the previous one
5172                    because we could be copying instead of
5173                    moving */
5174                 gtk_tree_selection_unselect_all (sel);
5175                 gtk_tree_selection_select_path (sel, path);
5176                 gtk_tree_path_free (path);
5177         }
5178         g_object_unref (object);
5179
5180  frees:
5181         /* Destroy the helper */
5182         move_to_helper_destroyer (helper);
5183 }
5184
5185 static void
5186 folder_move_to_cb (ModestMailOperation *mail_op,
5187                    TnyFolder *new_folder,
5188                    gpointer user_data)
5189 {
5190         GtkWidget *folder_view;
5191         GObject *object;
5192
5193         object = modest_mail_operation_get_source (mail_op);
5194         if (MODEST_IS_MAIN_WINDOW (object)) {
5195                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5196                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5197                 g_object_ref (folder_view);
5198                 g_object_unref (object);
5199                 move_to_cb (mail_op, user_data);
5200                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
5201                 g_object_unref (folder_view);
5202         } else {
5203                 move_to_cb (mail_op, user_data);
5204         }
5205 }
5206
5207 static void
5208 msgs_move_to_cb (ModestMailOperation *mail_op,
5209                  gpointer user_data)
5210 {
5211         move_to_cb (mail_op, user_data);
5212 }
5213
5214 void
5215 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
5216                                              gpointer user_data)
5217 {
5218         GObject *win = NULL;
5219
5220 #ifndef MODEST_TOOLKIT_HILDON2
5221         ModestWindow *main_window = NULL;
5222
5223         /* Disable next automatic folder selection */
5224         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5225                                                          FALSE); /* don't create */
5226         if (main_window) {
5227                 GtkWidget *folder_view = NULL;
5228
5229                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
5230                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5231                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
5232
5233                 if (user_data && TNY_IS_FOLDER (user_data)) {
5234                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
5235                                                           TNY_FOLDER (user_data), FALSE);
5236                 }
5237         }
5238 #endif
5239         /* Show notification dialog only if the main window exists */
5240         win = modest_mail_operation_get_source (mail_op);
5241         modest_platform_run_information_dialog ((GtkWindow *) win,
5242                                                 _("mail_in_ui_folder_move_target_error"),
5243                                                 FALSE);
5244         if (win)
5245                 g_object_unref (win);
5246 }
5247
5248 static void
5249 open_msg_for_purge_cb (ModestMailOperation *mail_op,
5250                        TnyHeader *header,
5251                        gboolean canceled,
5252                        TnyMsg *msg,
5253                        GError *err,
5254                        gpointer user_data)
5255 {
5256         TnyList *parts;
5257         TnyIterator *iter;
5258         gint pending_purges = 0;
5259         gboolean some_purged = FALSE;
5260         ModestWindow *win = MODEST_WINDOW (user_data);
5261         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
5262
5263         /* If there was any error */
5264         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
5265                 modest_window_mgr_unregister_header (mgr, header);
5266                 return;
5267         }
5268
5269         /* Once the message has been retrieved for purging, we check if
5270          * it's all ok for purging */
5271
5272         parts = tny_simple_list_new ();
5273         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
5274         iter = tny_list_create_iterator (parts);
5275
5276         while (!tny_iterator_is_done (iter)) {
5277                 TnyMimePart *part;
5278                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5279                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
5280                         if (tny_mime_part_is_purged (part))
5281                                 some_purged = TRUE;
5282                         else
5283                                 pending_purges++;
5284                 }
5285
5286                 if (part)
5287                         g_object_unref (part);
5288
5289                 tny_iterator_next (iter);
5290         }
5291         g_object_unref (iter);
5292
5293
5294         if (pending_purges>0) {
5295                 gint response;
5296                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
5297
5298                 if (response == GTK_RESPONSE_OK) {
5299                         GtkWidget *info;
5300                         info =
5301                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_me_inbox_remove_attachments"));
5302                         iter = tny_list_create_iterator (parts);
5303                         while (!tny_iterator_is_done (iter)) {
5304                                 TnyMimePart *part;
5305
5306                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5307                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
5308                                         tny_mime_part_set_purged (part);
5309
5310                                 if (part)
5311                                         g_object_unref (part);
5312
5313                                 tny_iterator_next (iter);
5314                         }
5315                         g_object_unref (iter);
5316
5317                         tny_msg_rewrite_cache (msg);
5318
5319                         gtk_widget_destroy (info);
5320                 }
5321         }
5322
5323         modest_window_mgr_unregister_header (mgr, header);
5324
5325         g_object_unref (parts);
5326 }
5327
5328 static void
5329 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
5330                                                      ModestMainWindow *win)
5331 {
5332         GtkWidget *header_view;
5333         TnyList *header_list;
5334         TnyHeader *header;
5335         TnyHeaderFlags flags;
5336         ModestWindow *msg_view_window =  NULL;
5337         gboolean found;
5338
5339         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5340
5341         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5342                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5343
5344         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5345         if (!header_list) {
5346                 g_warning ("%s: no header selected", __FUNCTION__);
5347                 return;
5348         }
5349
5350         if (tny_list_get_length (header_list) == 1) {
5351                 TnyIterator *iter = tny_list_create_iterator (header_list);
5352                 header = TNY_HEADER (tny_iterator_get_current (iter));
5353                 g_object_unref (iter);
5354         } else
5355                 return;
5356
5357         if (!header || !TNY_IS_HEADER(header)) {
5358                 g_warning ("%s: header is not valid", __FUNCTION__);
5359                 return;
5360         }
5361
5362         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
5363                                                           header, &msg_view_window);
5364         flags = tny_header_get_flags (header);
5365         if (!(flags & TNY_HEADER_FLAG_CACHED))
5366                 return;
5367         if (found) {
5368                 if (msg_view_window != NULL)
5369                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
5370                 else {
5371                         /* do nothing; uid was registered before, so window is probably on it's way */
5372                         g_warning ("debug: header %p has already been registered", header);
5373                 }
5374         } else {
5375                 ModestMailOperation *mail_op = NULL;
5376                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
5377                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
5378                                                                          modest_ui_actions_disk_operations_error_handler,
5379                                                                          NULL, NULL);
5380                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5381                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
5382
5383                 g_object_unref (mail_op);
5384         }
5385         if (header)
5386                 g_object_unref (header);
5387         if (header_list)
5388                 g_object_unref (header_list);
5389 }
5390
5391 /*
5392  * Checks if we need a connection to do the transfer and if the user
5393  * wants to connect to complete it
5394  */
5395 static void
5396 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5397                                        TnyFolderStore *src_folder,
5398                                        TnyList *headers,
5399                                        TnyFolder *dst_folder,
5400                                        gboolean delete_originals,
5401                                        gboolean *need_connection,
5402                                        gboolean *do_xfer)
5403 {
5404         TnyAccount *src_account;
5405         gint uncached_msgs = 0;
5406
5407         /* We don't need any further check if
5408          *
5409          * 1- the source folder is local OR
5410          * 2- the device is already online
5411          */
5412         if (!modest_tny_folder_store_is_remote (src_folder) ||
5413             tny_device_is_online (modest_runtime_get_device())) {
5414                 *need_connection = FALSE;
5415                 *do_xfer = TRUE;
5416                 return;
5417         }
5418
5419         /* We must ask for a connection when
5420          *
5421          *   - the message(s) is not already cached   OR
5422          *   - the message(s) is cached but the leave_on_server setting
5423          * is FALSE (because we need to sync the source folder to
5424          * delete the message from the server (for IMAP we could do it
5425          * offline, it'll take place the next time we get a
5426          * connection)
5427          */
5428         uncached_msgs = header_list_count_uncached_msgs (headers);
5429         src_account = get_account_from_folder_store (src_folder);
5430         if (uncached_msgs > 0) {
5431                 guint num_headers;
5432                 const gchar *msg;
5433
5434                 *need_connection = TRUE;
5435                 num_headers = tny_list_get_length (headers);
5436                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
5437
5438                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
5439                     GTK_RESPONSE_CANCEL) {
5440                         *do_xfer = FALSE;
5441                 } else {
5442                         *do_xfer = TRUE;
5443                 }
5444         } else {
5445                 /* The transfer is possible and the user wants to */
5446                 *do_xfer = TRUE;
5447
5448                 if (remote_folder_has_leave_on_server (src_folder) && delete_originals) {
5449                         const gchar *account_name;
5450                         gboolean leave_on_server;
5451
5452                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
5453                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
5454                                                                                   account_name);
5455
5456                         if (leave_on_server == TRUE) {
5457                                 *need_connection = FALSE;
5458                         } else {
5459                                 *need_connection = TRUE;
5460                         }
5461                 } else {
5462                         *need_connection = FALSE;
5463                 }
5464         }
5465
5466         /* Frees */
5467         g_object_unref (src_account);
5468 }
5469
5470 static void
5471 xfer_messages_error_handler (ModestMailOperation *mail_op,
5472                              gpointer user_data)
5473 {
5474         GObject *win;
5475         const GError *error;
5476
5477         win = modest_mail_operation_get_source (mail_op);
5478         error = modest_mail_operation_get_error (mail_op);
5479
5480         if (error && is_memory_full_error ((GError *) error, mail_op))
5481                 modest_platform_information_banner ((GtkWidget *) win,
5482                                                     NULL, _KR("cerm_device_memory_full"));
5483         else
5484                 modest_platform_run_information_dialog ((GtkWindow *) win,
5485                                                         _("mail_in_ui_folder_move_target_error"),
5486                                                         FALSE);
5487         if (win)
5488                 g_object_unref (win);
5489 }
5490
5491 typedef struct {
5492         TnyFolderStore *dst_folder;
5493         TnyList *headers;
5494 } XferMsgsHelper;
5495
5496 /**
5497  * Utility function that transfer messages from both the main window
5498  * and the msg view window when using the "Move to" dialog
5499  */
5500 static void
5501 xfer_messages_performer  (gboolean canceled,
5502                           GError *err,
5503                           GtkWindow *parent_window,
5504                           TnyAccount *account,
5505                           gpointer user_data)
5506 {
5507         ModestWindow *win = MODEST_WINDOW (parent_window);
5508         TnyAccount *dst_account = NULL;
5509         gboolean dst_forbids_message_add = FALSE;
5510         XferMsgsHelper *helper;
5511         MoveToHelper *movehelper;
5512         ModestMailOperation *mail_op;
5513
5514         helper = (XferMsgsHelper *) user_data;
5515
5516         if (canceled || err) {
5517                 if (!check_memory_full_error ((GtkWidget *) parent_window, err)) {
5518                         /* Show the proper error message */
5519                         modest_ui_actions_on_account_connection_error (parent_window, account);
5520                 }
5521                 goto end;
5522         }
5523
5524         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
5525
5526         /* tinymail will return NULL for local folders it seems */
5527         dst_forbids_message_add = modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5528                                                                                   modest_tny_account_get_protocol_type (dst_account),
5529                                                                                   MODEST_PROTOCOL_REGISTRY_STORE_FORBID_MESSAGE_ADD);
5530         g_object_unref (dst_account);
5531
5532         if (dst_forbids_message_add) {
5533                 modest_platform_information_banner (GTK_WIDGET (win),
5534                                                     NULL,
5535                                                     ngettext("mail_in_ui_folder_move_target_error",
5536                                                              "mail_in_ui_folder_move_targets_error",
5537                                                              tny_list_get_length (helper->headers)));
5538                 goto end;
5539         }
5540
5541         movehelper = g_new0 (MoveToHelper, 1);
5542
5543 #ifndef MODEST_TOOLKIT_HILDON2
5544         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
5545                                                                _CS("ckct_nw_pasting"));
5546         if (movehelper->banner != NULL)  {
5547                 g_object_ref (movehelper->banner);
5548                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
5549         }
5550 #endif
5551
5552         if (MODEST_IS_MAIN_WINDOW (win)) {
5553                 GtkWidget *header_view =
5554                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5555                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5556                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5557         }
5558
5559         /* Perform the mail operation */
5560         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5561                                                                  xfer_messages_error_handler,
5562                                                                  movehelper, NULL);
5563         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5564                                          mail_op);
5565
5566         modest_mail_operation_xfer_msgs (mail_op,
5567                                          helper->headers,
5568                                          TNY_FOLDER (helper->dst_folder),
5569                                          TRUE,
5570                                          msgs_move_to_cb,
5571                                          movehelper);
5572
5573         g_object_unref (G_OBJECT (mail_op));
5574  end:
5575         g_object_unref (helper->dst_folder);
5576         g_object_unref (helper->headers);
5577         g_slice_free (XferMsgsHelper, helper);
5578 }
5579
5580 typedef struct {
5581         TnyFolder *src_folder;
5582         TnyFolderStore *dst_folder;
5583         gboolean delete_original;
5584         GtkWidget *folder_view;
5585 } MoveFolderInfo;
5586
5587 static void
5588 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window,
5589                 TnyAccount *account, gpointer user_data)
5590 {
5591         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5592         GtkTreeSelection *sel;
5593         ModestMailOperation *mail_op = NULL;
5594
5595         if (canceled || err || !MODEST_IS_WINDOW (parent_window)) {
5596                 g_object_unref (G_OBJECT (info->src_folder));
5597                 g_object_unref (G_OBJECT (info->dst_folder));
5598                 g_free (info);
5599                 return;
5600         }
5601
5602         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5603 #ifndef MODEST_TOOLKIT_HILDON2
5604         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5605                         _CS("ckct_nw_pasting"));
5606         if (helper->banner != NULL)  {
5607                 g_object_ref (helper->banner);
5608                 gtk_widget_show (GTK_WIDGET(helper->banner));
5609         }
5610 #endif
5611         /* Clean folder on header view before moving it */
5612         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5613         gtk_tree_selection_unselect_all (sel);
5614
5615         /* Let gtk events run. We need that the folder
5616            view frees its reference to the source
5617            folder *before* issuing the mail operation
5618            so we need the signal handler of selection
5619            changed to happen before the mail
5620            operation
5621         while (gtk_events_pending ())
5622                 gtk_main_iteration ();   */
5623
5624         mail_op =
5625                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5626                                 modest_ui_actions_move_folder_error_handler,
5627                                 info->src_folder, NULL);
5628         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5629                         mail_op);
5630
5631         /* Select *after* the changes */
5632         /* TODO: this function hangs UI after transfer */
5633         /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
5634         /*                                                        TNY_FOLDER (src_folder), TRUE); */
5635
5636         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
5637                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5638                                                   TNY_FOLDER (info->dst_folder), TRUE);
5639         }
5640         modest_mail_operation_xfer_folder (mail_op,
5641                         TNY_FOLDER (info->src_folder),
5642                         info->dst_folder,
5643                         info->delete_original,
5644                         folder_move_to_cb,
5645                         helper);
5646         g_object_unref (G_OBJECT (info->src_folder));
5647
5648         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
5649         /* } */
5650
5651         /* Unref mail operation */
5652         g_object_unref (G_OBJECT (mail_op));
5653         g_object_unref (G_OBJECT (info->dst_folder));
5654         g_free (user_data);
5655 }
5656
5657 static TnyAccount *
5658 get_account_from_folder_store (TnyFolderStore *folder_store)
5659 {
5660         if (TNY_IS_ACCOUNT (folder_store))
5661                 return g_object_ref (folder_store);
5662         else
5663                 return tny_folder_get_account (TNY_FOLDER (folder_store));
5664 }
5665
5666 /*
5667  * UI handler for the "Move to" action when invoked from the
5668  * ModestMainWindow
5669  */
5670 static void
5671 modest_ui_actions_on_main_window_move_to (GtkAction *action,
5672                                           GtkWidget *folder_view,
5673                                           TnyFolderStore *dst_folder,
5674                                           ModestMainWindow *win)
5675 {
5676         ModestHeaderView *header_view = NULL;
5677         TnyFolderStore *src_folder = NULL;
5678
5679         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5680
5681         /* Get the source folder */
5682         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5683
5684         /* Get header view */
5685         header_view = (ModestHeaderView *)
5686                 modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5687
5688         /* Get folder or messages to transfer */
5689         if (gtk_widget_is_focus (folder_view)) {
5690                 gboolean do_xfer = TRUE;
5691
5692                 /* Allow only to transfer folders to the local root folder */
5693                 if (TNY_IS_ACCOUNT (dst_folder) &&
5694                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5695                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5696                         do_xfer = FALSE;
5697                 } else if (!TNY_IS_FOLDER (src_folder)) {
5698                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5699                         do_xfer = FALSE;
5700                 }
5701
5702                 if (do_xfer) {
5703                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5704                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5705
5706                         info->src_folder = g_object_ref (src_folder);
5707                         info->dst_folder = g_object_ref (dst_folder);
5708                         info->delete_original = TRUE;
5709                         info->folder_view = folder_view;
5710
5711                         connect_info->callback = on_move_folder_cb;
5712                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5713                         connect_info->data = info;
5714
5715                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5716                                                                    TNY_FOLDER_STORE (src_folder),
5717                                                                    connect_info);
5718                 }
5719         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5720                 TnyList *headers;
5721
5722                 headers = modest_header_view_get_selected_headers(header_view);
5723
5724                 /* Transfer the messages */
5725                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder),
5726                                                             headers, TNY_FOLDER (dst_folder));
5727
5728                 g_object_unref (headers);
5729         }
5730
5731         /* Frees */
5732         g_object_unref (src_folder);
5733 }
5734
5735 #ifdef MODEST_TOOLKIT_HILDON2
5736 /*
5737  * UI handler for the "Move to" action when invoked from the
5738  * ModestFolderWindow
5739  */
5740 static void
5741 modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
5742                                             TnyFolderStore *dst_folder,
5743                                             TnyList *selection,
5744                                             GtkWindow *win)
5745 {
5746         TnyFolderStore *src_folder = NULL;
5747         TnyIterator *iterator;
5748
5749         if (tny_list_get_length (selection) != 1)
5750                 return;
5751
5752         iterator = tny_list_create_iterator (selection);
5753         src_folder = TNY_FOLDER_STORE (tny_iterator_get_current (iterator));
5754         g_object_unref (iterator);
5755
5756
5757         gboolean do_xfer = TRUE;
5758
5759         /* Allow only to transfer folders to the local root folder */
5760         if (TNY_IS_ACCOUNT (dst_folder) &&
5761             !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5762             !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5763                 do_xfer = FALSE;
5764                 /* Show an error */
5765                 modest_platform_run_information_dialog (win,
5766                                                         _("mail_in_ui_folder_move_target_error"),
5767                                                         FALSE);
5768         } else if (!TNY_IS_FOLDER (src_folder)) {
5769                 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5770                 do_xfer = FALSE;
5771         }
5772
5773         if (do_xfer) {
5774                 MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5775                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5776
5777                 info->src_folder = g_object_ref (src_folder);
5778                 info->dst_folder = g_object_ref (dst_folder);
5779                 info->delete_original = TRUE;
5780                 info->folder_view = folder_view;
5781
5782                 connect_info->callback = on_move_folder_cb;
5783                 connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5784                 connect_info->data = info;
5785
5786                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5787                                                            TNY_FOLDER_STORE (src_folder),
5788                                                            connect_info);
5789         }
5790
5791         /* Frees */
5792         g_object_unref (src_folder);
5793 }
5794 #endif
5795
5796
5797 void
5798 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
5799                                             TnyFolder *src_folder,
5800                                             TnyList *headers,
5801                                             TnyFolder *dst_folder)
5802 {
5803         gboolean need_connection = TRUE;
5804         gboolean do_xfer = TRUE;
5805         XferMsgsHelper *helper;
5806
5807         g_return_if_fail (TNY_IS_FOLDER (src_folder));
5808         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5809         g_return_if_fail (TNY_IS_LIST (headers));
5810
5811         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder),
5812                                                headers, TNY_FOLDER (dst_folder),
5813                                                TRUE, &need_connection,
5814                                                &do_xfer);
5815
5816         /* If we don't want to transfer just return */
5817         if (!do_xfer)
5818                 return;
5819
5820         /* Create the helper */
5821         helper = g_slice_new (XferMsgsHelper);
5822         helper->dst_folder = g_object_ref (dst_folder);
5823         helper->headers = g_object_ref (headers);
5824
5825         if (need_connection) {
5826                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5827                 connect_info->callback = xfer_messages_performer;
5828                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
5829                 connect_info->data = helper;
5830
5831                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5832                                                            TNY_FOLDER_STORE (src_folder),
5833                                                            connect_info);
5834         } else {
5835                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
5836                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
5837                                          src_account, helper);
5838                 g_object_unref (src_account);
5839         }
5840 }
5841
5842 /*
5843  * UI handler for the "Move to" action when invoked from the
5844  * ModestMsgViewWindow
5845  */
5846 static void
5847 modest_ui_actions_on_window_move_to (GtkAction *action,
5848                                      TnyList *headers,
5849                                      TnyFolderStore *dst_folder,
5850                                      ModestWindow *win)
5851 {
5852         TnyFolder *src_folder = NULL;
5853
5854         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5855
5856         if (headers) {
5857                 TnyHeader *header = NULL;
5858                 TnyIterator *iter;
5859
5860                 iter = tny_list_create_iterator (headers);
5861                 header = (TnyHeader *) tny_iterator_get_current (iter);
5862                 src_folder = tny_header_get_folder (header);
5863
5864                 /* Transfer the messages */
5865                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder,
5866                                                             headers,
5867                                                             TNY_FOLDER (dst_folder));
5868
5869                 /* Frees */
5870                 g_object_unref (header);
5871                 g_object_unref (iter);
5872                 g_object_unref (src_folder);
5873         }
5874 }
5875
5876 void
5877 modest_ui_actions_on_move_to (GtkAction *action,
5878                               ModestWindow *win)
5879 {
5880         modest_ui_actions_on_edit_mode_move_to (win);
5881 }
5882
5883 gboolean
5884 modest_ui_actions_on_edit_mode_move_to (ModestWindow *win)
5885 {
5886         GtkWidget *dialog = NULL;
5887         MoveToInfo *helper = NULL;
5888         TnyList *list_to_move;
5889
5890         g_return_val_if_fail (MODEST_IS_WINDOW (win), FALSE);
5891
5892 #ifndef MODEST_TOOLKIT_HILDON2
5893         /* Get the main window if exists */
5894         ModestMainWindow *main_window;
5895         if (MODEST_IS_MAIN_WINDOW (win))
5896                 main_window = MODEST_MAIN_WINDOW (win);
5897         else
5898                 main_window =
5899                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5900                                                                                FALSE)); /* don't create */
5901 #endif
5902
5903         list_to_move = modest_platform_get_list_to_move (MODEST_WINDOW (win));
5904
5905         if (!list_to_move)
5906                 return FALSE;
5907
5908         if (tny_list_get_length (list_to_move) < 1) {
5909                 g_object_unref (list_to_move);
5910                 return FALSE;
5911         }
5912
5913         /* Create and run the dialog */
5914         dialog = create_move_to_dialog (GTK_WINDOW (win), NULL, list_to_move);
5915         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
5916                                      GTK_WINDOW (dialog),
5917                                      (GtkWindow *) win);
5918
5919         /* Create helper */
5920         helper = g_slice_new0 (MoveToInfo);
5921         helper->list = list_to_move;
5922         helper->win = win;
5923
5924         /* Listen to response signal */
5925         g_signal_connect (dialog, "response", G_CALLBACK (on_move_to_dialog_response), helper);
5926
5927         /* Show the dialog */
5928         gtk_widget_show (dialog);
5929
5930         return TRUE;
5931 }
5932
5933 /*
5934  * Calls #HeadersFunc for each header already selected in the main
5935  * window or the message currently being shown in the msg view window
5936  */
5937 static void
5938 do_headers_action (ModestWindow *win,
5939                    HeadersFunc func,
5940                    gpointer user_data)
5941 {
5942         TnyList *headers_list = NULL;
5943         TnyIterator *iter = NULL;
5944         TnyHeader *header = NULL;
5945         TnyFolder *folder = NULL;
5946
5947         /* Get headers */
5948         headers_list = get_selected_headers (win);
5949         if (!headers_list)
5950                 return;
5951
5952         /* Get the folder */
5953         iter = tny_list_create_iterator (headers_list);
5954         header = TNY_HEADER (tny_iterator_get_current (iter));
5955         if (header) {
5956                 folder = tny_header_get_folder (header);
5957                 g_object_unref (header);
5958         }
5959
5960         /* Call the function for each header */
5961         while (!tny_iterator_is_done (iter)) {
5962                 header = TNY_HEADER (tny_iterator_get_current (iter));
5963                 func (header, win, user_data);
5964                 g_object_unref (header);
5965                 tny_iterator_next (iter);
5966         }
5967
5968         /* Trick: do a poke status in order to speed up the signaling
5969            of observers */
5970         if (folder) {
5971                 tny_folder_poke_status (folder);
5972                 g_object_unref (folder);
5973         }
5974
5975         /* Frees */
5976         g_object_unref (iter);
5977         g_object_unref (headers_list);
5978 }
5979
5980 void
5981 modest_ui_actions_view_attachment (GtkAction *action,
5982                                    ModestWindow *window)
5983 {
5984         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5985                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
5986         } else {
5987                 /* not supported window for this action */
5988                 g_return_if_reached ();
5989         }
5990 }
5991
5992 void
5993 modest_ui_actions_save_attachments (GtkAction *action,
5994                                     ModestWindow *window)
5995 {
5996         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5997
5998                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
5999                         return;
6000
6001                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
6002         } else {
6003                 /* not supported window for this action */
6004                 g_return_if_reached ();
6005         }
6006 }
6007
6008 void
6009 modest_ui_actions_remove_attachments (GtkAction *action,
6010                                       ModestWindow *window)
6011 {
6012         if (MODEST_IS_MAIN_WINDOW (window)) {
6013                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
6014         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6015                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
6016         } else {
6017                 /* not supported window for this action */
6018                 g_return_if_reached ();
6019         }
6020 }
6021
6022 void
6023 modest_ui_actions_on_settings (GtkAction *action,
6024                                ModestWindow *win)
6025 {
6026         GtkWidget *dialog;
6027
6028         dialog = modest_platform_get_global_settings_dialog ();
6029         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
6030         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
6031         gtk_widget_show_all (dialog);
6032
6033         gtk_dialog_run (GTK_DIALOG (dialog));
6034
6035         gtk_widget_destroy (dialog);
6036 }
6037
6038 void
6039 modest_ui_actions_on_help (GtkAction *action,
6040                            GtkWindow *win)
6041 {
6042         /* Help app is not available at all in fremantle */
6043 #ifndef MODEST_TOOLKIT_HILDON2
6044         const gchar *help_id;
6045
6046         g_return_if_fail (win && GTK_IS_WINDOW(win));
6047
6048         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
6049
6050         if (help_id)
6051                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6052 #endif
6053 }
6054
6055 void
6056 modest_ui_actions_on_csm_help (GtkAction *action,
6057                                GtkWindow *win)
6058 {
6059         /* Help app is not available at all in fremantle */
6060 #ifndef MODEST_TOOLKIT_HILDON2
6061
6062         const gchar* help_id = NULL;
6063         GtkWidget *folder_view;
6064         TnyFolderStore *folder_store;
6065
6066         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
6067
6068         /* Get selected folder */
6069         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
6070                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6071         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6072
6073         /* Switch help_id */
6074         if (folder_store && TNY_IS_FOLDER (folder_store))
6075                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
6076
6077         if (folder_store)
6078                 g_object_unref (folder_store);
6079
6080         if (help_id)
6081                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6082         else
6083                 modest_ui_actions_on_help (action, win);
6084 #endif
6085 }
6086
6087 static void
6088 retrieve_contents_cb (ModestMailOperation *mail_op,
6089                       TnyHeader *header,
6090                       gboolean canceled,
6091                       TnyMsg *msg,
6092                       GError *err,
6093                       gpointer user_data)
6094 {
6095         /* We only need this callback to show an error in case of
6096            memory low condition */
6097         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
6098                 g_debug ("%s: message failed to retrieve. Memory low?", __FUNCTION__);
6099         }
6100 }
6101
6102 static void
6103 retrieve_msg_contents_performer (gboolean canceled,
6104                                  GError *err,
6105                                  GtkWindow *parent_window,
6106                                  TnyAccount *account,
6107                                  gpointer user_data)
6108 {
6109         ModestMailOperation *mail_op;
6110         TnyList *headers = TNY_LIST (user_data);
6111
6112         if (err || canceled) {
6113                 check_memory_full_error ((GtkWidget *) parent_window, err);
6114                 goto out;
6115         }
6116
6117         /* Create mail operation */
6118         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
6119                                                                  modest_ui_actions_disk_operations_error_handler,
6120                                                                  NULL, NULL);
6121         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
6122         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
6123
6124         /* Frees */
6125         g_object_unref (mail_op);
6126  out:
6127         g_object_unref (headers);
6128         g_object_unref (account);
6129 }
6130
6131 void
6132 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
6133                                             ModestWindow *window)
6134 {
6135         TnyList *headers = NULL;
6136         TnyAccount *account = NULL;
6137         TnyIterator *iter = NULL;
6138         TnyHeader *header = NULL;
6139         TnyFolder *folder = NULL;
6140
6141         /* Get headers */
6142         headers = get_selected_headers (window);
6143         if (!headers)
6144                 return;
6145
6146         /* Pick the account */
6147         iter = tny_list_create_iterator (headers);
6148         header = TNY_HEADER (tny_iterator_get_current (iter));
6149         folder = tny_header_get_folder (header);
6150         account = tny_folder_get_account (folder);
6151         g_object_unref (folder);
6152         g_object_unref (header);
6153         g_object_unref (iter);
6154
6155         /* Connect and perform the message retrieval */
6156         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
6157                                              g_object_ref (account),
6158                                              retrieve_msg_contents_performer,
6159                                              g_object_ref (headers));
6160
6161         /* Frees */
6162         g_object_unref (account);
6163         g_object_unref (headers);
6164 }
6165
6166 void
6167 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
6168 {
6169         g_return_if_fail (MODEST_IS_WINDOW (window));
6170
6171         /* Update dimmed */
6172         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
6173 }
6174
6175 void
6176 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
6177 {
6178         g_return_if_fail (MODEST_IS_WINDOW (window));
6179
6180         /* Update dimmed */
6181         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
6182 }
6183
6184 void
6185 modest_ui_actions_on_email_menu_activated (GtkAction *action,
6186                                           ModestWindow *window)
6187 {
6188         g_return_if_fail (MODEST_IS_WINDOW (window));
6189
6190         /* Update dimmed */
6191         modest_ui_actions_check_menu_dimming_rules (window);
6192 }
6193
6194 void
6195 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
6196                                           ModestWindow *window)
6197 {
6198         g_return_if_fail (MODEST_IS_WINDOW (window));
6199
6200         /* Update dimmed */
6201         modest_ui_actions_check_menu_dimming_rules (window);
6202 }
6203
6204 void
6205 modest_ui_actions_on_view_menu_activated (GtkAction *action,
6206                                           ModestWindow *window)
6207 {
6208         g_return_if_fail (MODEST_IS_WINDOW (window));
6209
6210         /* Update dimmed */
6211         modest_ui_actions_check_menu_dimming_rules (window);
6212 }
6213
6214 void
6215 modest_ui_actions_on_format_menu_activated (GtkAction *action,
6216                                             ModestWindow *window)
6217 {
6218         g_return_if_fail (MODEST_IS_WINDOW (window));
6219
6220         /* Update dimmed */
6221         modest_ui_actions_check_menu_dimming_rules (window);
6222 }
6223
6224 void
6225 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
6226                                           ModestWindow *window)
6227 {
6228         g_return_if_fail (MODEST_IS_WINDOW (window));
6229
6230         /* Update dimmed */
6231         modest_ui_actions_check_menu_dimming_rules (window);
6232 }
6233
6234 void
6235 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
6236                                           ModestWindow *window)
6237 {
6238         g_return_if_fail (MODEST_IS_WINDOW (window));
6239
6240         /* Update dimmed */
6241         modest_ui_actions_check_menu_dimming_rules (window);
6242 }
6243
6244 void
6245 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
6246                                                  ModestWindow *window)
6247 {
6248         g_return_if_fail (MODEST_IS_WINDOW (window));
6249
6250         /* Update dimmed */
6251         modest_ui_actions_check_menu_dimming_rules (window);
6252 }
6253
6254 void
6255 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
6256                                                      ModestWindow *window)
6257 {
6258         g_return_if_fail (MODEST_IS_WINDOW (window));
6259
6260         /* Update dimmed */
6261         modest_ui_actions_check_menu_dimming_rules (window);
6262 }
6263
6264 void
6265 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
6266                                                      ModestWindow *window)
6267 {
6268         g_return_if_fail (MODEST_IS_WINDOW (window));
6269
6270         /* Update dimmed */
6271         modest_ui_actions_check_menu_dimming_rules (window);
6272 }
6273
6274 void
6275 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
6276 {
6277         g_return_if_fail (MODEST_IS_WINDOW (window));
6278
6279         /* we check for low-mem; in that case, show a warning, and don't allow
6280          * searching
6281          */
6282         if (modest_platform_check_memory_low (window, TRUE))
6283                 return;
6284
6285         modest_platform_show_search_messages (GTK_WINDOW (window));
6286 }
6287
6288 void
6289 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
6290 {
6291         g_return_if_fail (MODEST_IS_WINDOW (win));
6292
6293
6294         /* we check for low-mem; in that case, show a warning, and don't allow
6295          * for the addressbook
6296          */
6297         if (modest_platform_check_memory_low (win, TRUE))
6298                 return;
6299
6300
6301         modest_platform_show_addressbook (GTK_WINDOW (win));
6302 }
6303
6304
6305 void
6306 modest_ui_actions_on_toggle_find_in_page (GtkAction *action,
6307                                           ModestWindow *window)
6308 {
6309         gboolean active;
6310         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
6311
6312         if (GTK_IS_TOGGLE_ACTION (action))
6313                 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
6314         else
6315                 active = TRUE;
6316
6317         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window),
6318                                                     active);
6319 }
6320
6321 static void
6322 on_send_receive_finished (ModestMailOperation  *mail_op,
6323                            gpointer user_data)
6324 {
6325         GtkWidget *header_view, *folder_view;
6326         TnyFolderStore *folder_store;
6327         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
6328
6329         /* Set send/receive operation finished */
6330         modest_main_window_notify_send_receive_completed (main_win);
6331
6332         /* Don't refresh the current folder if there were any errors */
6333         if (modest_mail_operation_get_status (mail_op) !=
6334             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
6335                 return;
6336
6337         /* Refresh the current folder if we're viewing a window. We do
6338            this because the user won't be able to see the new mails in
6339            the selected folder after a Send&Receive because it only
6340            performs a poke_status, i.e, only the number of read/unread
6341            messages is updated, but the new headers are not
6342            downloaded */
6343         folder_view = modest_main_window_get_child_widget (main_win,
6344                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6345         if (!folder_view)
6346                 return;
6347
6348         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6349
6350         /* Do not need to refresh INBOX again because the
6351            update_account does it always automatically */
6352         if (folder_store && TNY_IS_FOLDER (folder_store) &&
6353             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
6354                 ModestMailOperation *refresh_op;
6355
6356                 header_view = modest_main_window_get_child_widget (main_win,
6357                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6358
6359                 /* We do not need to set the contents style
6360                    because it hasn't changed. We also do not
6361                    need to save the widget status. Just force
6362                    a refresh */
6363                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
6364                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
6365                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
6366                                                       folder_refreshed_cb, main_win);
6367                 g_object_unref (refresh_op);
6368         }
6369
6370         if (folder_store)
6371                 g_object_unref (folder_store);
6372 }
6373
6374
6375 void
6376 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self,
6377                                                 TnyHeader *header,
6378                                                 TnyMsg *msg,
6379                                                 GError *err,
6380                                                 gpointer user_data)
6381 {
6382         const gchar* server_name = NULL;
6383         TnyTransportAccount *transport;
6384         gchar *message = NULL;
6385         ModestProtocol *protocol;
6386
6387         /* Don't show anything if the user cancelled something or the
6388          * send receive request is not interactive. Authentication
6389          * errors are managed by the account store so no need to show
6390          * a dialog here again */
6391         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
6392             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
6393             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
6394                 return;
6395
6396
6397         /* Get the server name. Note that we could be using a
6398            connection specific transport account */
6399         transport = (TnyTransportAccount *)
6400                 tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self));
6401         if (transport) {
6402                 ModestTnyAccountStore *acc_store;
6403                 const gchar *acc_name;
6404                 TnyTransportAccount *conn_specific;
6405
6406                 acc_store = modest_runtime_get_account_store();
6407                 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT (transport));
6408                 conn_specific = (TnyTransportAccount *)
6409                         modest_tny_account_store_get_transport_account_for_open_connection (acc_store, acc_name);
6410                 if (conn_specific) {
6411                         server_name = tny_account_get_hostname (TNY_ACCOUNT (conn_specific));
6412                         g_object_unref (conn_specific);
6413                 } else {
6414                         server_name = tny_account_get_hostname (TNY_ACCOUNT (transport));
6415                 }
6416                 g_object_unref (transport);
6417         }
6418
6419         /* Get protocol */
6420         protocol = modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
6421                                                                   MODEST_PROTOCOL_REGISTRY_TRANSPORT_STORE_PROTOCOLS,
6422                                                                   tny_account_get_proto (TNY_ACCOUNT (transport)));
6423         if (!protocol) {
6424                 g_warning ("%s: Account with no proto", __FUNCTION__);
6425                 return;
6426         }
6427
6428         /* Show the appropriate message text for the GError: */
6429         switch (err->code) {
6430         case TNY_SERVICE_ERROR_CONNECT:
6431                 message = modest_protocol_get_translation (protocol,
6432                                                            MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR,
6433                                                            server_name);
6434                 break;
6435         case TNY_SERVICE_ERROR_SEND:
6436                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6437                 break;
6438         case TNY_SERVICE_ERROR_UNAVAILABLE:
6439                 message = modest_protocol_get_translation (protocol,
6440                                                            MODEST_PROTOCOL_TRANSLATION_CONNECT_ERROR,
6441                                                            server_name);
6442                 break;
6443         default:
6444                 g_warning ("%s: unexpected ERROR %d",
6445                            __FUNCTION__, err->code);
6446                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6447                 break;
6448         }
6449
6450         modest_platform_run_information_dialog (NULL, message, FALSE);
6451         g_free (message);
6452 }
6453
6454 void
6455 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
6456                                                 gchar *msg_id,
6457                                                 guint status,
6458                                                 gpointer user_data)
6459 {
6460         ModestWindow *top_window = NULL;
6461         ModestWindowMgr *mgr = NULL;
6462         GtkWidget *header_view = NULL;
6463         TnyFolder *selected_folder = NULL;
6464         TnyFolderType folder_type;
6465
6466         mgr = modest_runtime_get_window_mgr ();
6467         top_window = modest_window_mgr_get_current_top (mgr);
6468
6469         if (!top_window)
6470                 return;
6471
6472 #ifndef MODEST_TOOLKIT_HILDON2
6473         if (MODEST_IS_MAIN_WINDOW (top_window)) {
6474                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (top_window),
6475                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6476         }
6477 #else
6478         if (MODEST_IS_HEADER_WINDOW (top_window)) {
6479                 header_view = (GtkWidget *)
6480                         modest_header_window_get_header_view (MODEST_HEADER_WINDOW (top_window));
6481         }
6482 #endif
6483
6484         /* Get selected folder */
6485         if (header_view)
6486                 selected_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
6487         if (!selected_folder)
6488                 return;
6489
6490         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
6491 #if GTK_CHECK_VERSION(2, 8, 0)
6492         folder_type = modest_tny_folder_guess_folder_type (selected_folder);
6493         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {
6494                 GtkTreeViewColumn *tree_column;
6495
6496                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view),
6497                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
6498                 if (tree_column)
6499                         gtk_tree_view_column_queue_resize (tree_column);
6500                 }
6501 #else /* #if GTK_CHECK_VERSION(2, 8, 0) */
6502         gtk_widget_queue_draw (header_view);
6503 #endif
6504
6505 #ifndef MODEST_TOOLKIT_HILDON2
6506         /* Rerun dimming rules, because the message could become deletable for example */
6507         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6508                                                  MODEST_DIMMING_RULES_TOOLBAR);
6509         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6510                                                  MODEST_DIMMING_RULES_MENU);
6511 #endif
6512
6513         /* Free */
6514         g_object_unref (selected_folder);
6515 }
6516
6517 void
6518 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
6519                                                TnyAccount *account)
6520 {
6521         ModestProtocolType protocol_type;
6522         ModestProtocol *protocol;
6523         gchar *error_note = NULL;
6524
6525         protocol_type = modest_tny_account_get_protocol_type (account);
6526         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6527                                                                   protocol_type);
6528
6529         error_note = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR, tny_account_get_hostname (account));
6530         if (error_note == NULL) {
6531                 g_warning ("%s: This should not be reached", __FUNCTION__);
6532         } else {
6533                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
6534                 g_free (error_note);
6535         }
6536 }
6537
6538 gchar *
6539 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
6540 {
6541         gchar *msg = NULL;
6542         gchar *subject;
6543         TnyFolderStore *folder = NULL;
6544         TnyAccount *account = NULL;
6545         ModestProtocolType proto;
6546         ModestProtocol *protocol;
6547         TnyHeader *header = NULL;
6548
6549         if (MODEST_IS_MAIN_WINDOW (win)) {
6550                 GtkWidget *header_view;
6551                 TnyList* headers = NULL;
6552                 TnyIterator *iter;
6553                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
6554                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6555                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6556                 if (!headers || tny_list_get_length (headers) == 0) {
6557                         if (headers)
6558                                 g_object_unref (headers);
6559                         return NULL;
6560                 }
6561                 iter = tny_list_create_iterator (headers);
6562                 header = TNY_HEADER (tny_iterator_get_current (iter));
6563                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6564                 g_object_unref (iter);
6565                 g_object_unref (headers);
6566 #ifdef MODEST_TOOLKIT_HILDON2
6567         } else if (MODEST_IS_HEADER_WINDOW (win)) {
6568                 GtkWidget *header_view;
6569                 TnyList* headers = NULL;
6570                 TnyIterator *iter;
6571                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
6572                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6573                 if (!headers || tny_list_get_length (headers) == 0) {
6574                         if (headers)
6575                                 g_object_unref (headers);
6576                         return NULL;
6577                 }
6578                 iter = tny_list_create_iterator (headers);
6579                 header = TNY_HEADER (tny_iterator_get_current (iter));
6580                 if (header) {
6581                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6582                 } else {
6583                         g_warning ("List should contain headers");
6584                 }
6585                 g_object_unref (iter);
6586                 g_object_unref (headers);
6587 #endif
6588         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
6589                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
6590                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6591         }
6592
6593         if (!header || !folder)
6594                 goto frees;
6595
6596         /* Get the account type */
6597         account = tny_folder_get_account (TNY_FOLDER (folder));
6598         proto = modest_tny_account_get_protocol_type (account);
6599         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6600                                                                   proto);
6601
6602         subject = tny_header_dup_subject (header);
6603         msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
6604         if (subject)
6605                 g_free (subject);
6606         if (msg == NULL) {
6607                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
6608         }
6609
6610  frees:
6611         /* Frees */
6612         if (account)
6613                 g_object_unref (account);
6614         if (folder)
6615                 g_object_unref (folder);
6616         if (header)
6617                 g_object_unref (header);
6618
6619         return msg;
6620 }
6621
6622 gboolean
6623 modest_ui_actions_on_delete_account (GtkWindow *parent_window,
6624                                      const gchar *account_name,
6625                                      const gchar *account_title)
6626 {
6627         ModestAccountMgr *account_mgr;
6628         gchar *txt = NULL;
6629         gint response;
6630         ModestProtocol *protocol;
6631         gboolean removed = FALSE;
6632
6633         g_return_val_if_fail (account_name, FALSE);
6634         g_return_val_if_fail (account_title, FALSE);
6635
6636         account_mgr = modest_runtime_get_account_mgr();
6637
6638         /* The warning text depends on the account type: */
6639         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6640                                                                   modest_account_mgr_get_store_protocol (account_mgr,
6641                                                                                                          account_name));
6642         txt = modest_protocol_get_translation (protocol,
6643                                                MODEST_PROTOCOL_TRANSLATION_DELETE_MAILBOX,
6644                                                account_title);
6645         if (txt == NULL)
6646                 txt = g_strdup_printf (_("emev_nc_delete_mailbox"), account_title);
6647
6648         response = modest_platform_run_confirmation_dialog (parent_window, txt);
6649         g_free (txt);
6650         txt = NULL;
6651
6652         if (response == GTK_RESPONSE_OK) {
6653                 /* Remove account. If it succeeds then it also removes
6654                    the account from the ModestAccountView: */
6655                 gboolean is_default = FALSE;
6656                 gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr);
6657                 if (default_account_name && (strcmp (default_account_name, account_name) == 0))
6658                         is_default = TRUE;
6659                 g_free (default_account_name);
6660
6661                 removed = modest_account_mgr_remove_account (account_mgr, account_name);
6662                 if (!removed)
6663                         g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__);
6664         }
6665         return removed;
6666 }