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