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