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