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