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