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