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