Fixes NB#119629, show "device memory full..." notification when moving a folder to...
[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                         _FM("sfil_ib_opening_not_allowed"),
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                         _FM("sfil_ib_opening_not_allowed"),
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                 /* Note that the connection process can fail due to
3835                    memory low conditions as it can not successfully
3836                    store the summary */
3837                 if (!check_memory_full_error ((GtkWidget*) parent_window, err, NULL))
3838                         g_debug ("Error connecting when trying to delete a folder");
3839                 g_object_unref (G_OBJECT (info->folder));
3840                 g_free (info);
3841                 return;
3842         }
3843
3844         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
3845                 folder_view = modest_main_window_get_child_widget (
3846                         MODEST_MAIN_WINDOW (parent_window),
3847                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3848 #ifdef MODEST_TOOLKIT_HILDON2
3849         } else if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3850                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (parent_window)));
3851 #endif
3852         } else {
3853                 g_object_unref (G_OBJECT (info->folder));
3854                 g_free (info);
3855                 return;
3856         }
3857
3858         /* Unselect the folder before deleting it to free the headers */
3859         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3860         gtk_tree_selection_unselect_all (sel);
3861
3862         /* Create the mail operation */
3863         mail_op =
3864                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3865                                 modest_ui_actions_delete_folder_error_handler,
3866                                 NULL, NULL);
3867
3868         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3869                         mail_op);
3870         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3871
3872         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3873
3874         g_object_unref (G_OBJECT (mail_op));
3875         g_object_unref (G_OBJECT (info->folder));
3876         g_free (info);
3877 }
3878
3879 static gboolean
3880 delete_folder (ModestWindow *window, gboolean move_to_trash)
3881 {
3882         TnyFolderStore *folder;
3883         GtkWidget *folder_view;
3884         gint response;
3885         gchar *message;
3886
3887         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3888
3889         if (MODEST_IS_MAIN_WINDOW (window)) {
3890
3891                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3892                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3893 #ifdef MODEST_TOOLKIT_HILDON2
3894         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3895                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3896 #endif
3897         } else {
3898                 return FALSE;
3899         }
3900         if (!folder_view)
3901                 return FALSE;
3902
3903         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3904
3905         if (!folder)
3906                 return FALSE;
3907
3908         /* Show an error if it's an account */
3909         if (!TNY_IS_FOLDER (folder)) {
3910                 modest_platform_run_information_dialog (GTK_WINDOW (window),
3911                                                         _("mail_in_ui_folder_delete_error"),
3912                                                         FALSE);
3913                 g_object_unref (G_OBJECT (folder));
3914                 return FALSE;
3915         }
3916
3917         /* Ask the user */
3918         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"),
3919                                     tny_folder_get_name (TNY_FOLDER (folder)));
3920         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
3921                                                             (const gchar *) message);
3922         g_free (message);
3923
3924         if (response == GTK_RESPONSE_OK) {
3925                 DeleteFolderInfo *info;
3926                 info = g_new0(DeleteFolderInfo, 1);
3927                 info->folder = folder;
3928                 info->move_to_trash = move_to_trash;
3929                 g_object_ref (G_OBJECT (info->folder));
3930                 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder));
3931                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (window),
3932                                                                TRUE,
3933                                                                TNY_FOLDER_STORE (account),
3934                                                                on_delete_folder_cb, info);
3935                 g_object_unref (account);
3936                 return TRUE;
3937         } else {
3938                 return FALSE;
3939         }
3940         g_object_unref (G_OBJECT (folder));
3941 }
3942
3943 void
3944 modest_ui_actions_on_delete_folder (GtkAction *action,
3945                                     ModestWindow *window)
3946 {
3947         modest_ui_actions_on_edit_mode_delete_folder (window);
3948 }
3949
3950 gboolean
3951 modest_ui_actions_on_edit_mode_delete_folder (ModestWindow *window)
3952 {
3953         g_return_val_if_fail (MODEST_IS_WINDOW(window), TRUE);
3954
3955         return delete_folder (window, FALSE);
3956 }
3957
3958 void
3959 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
3960 {
3961         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3962
3963         delete_folder (MODEST_WINDOW (main_window), TRUE);
3964 }
3965
3966
3967 typedef struct _PasswordDialogFields {
3968         GtkWidget *username;
3969         GtkWidget *password;
3970         GtkWidget *dialog;
3971 } PasswordDialogFields;
3972
3973 static void
3974 password_dialog_check_field (GtkEditable *editable,
3975                              PasswordDialogFields *fields)
3976 {
3977         const gchar *value;
3978         gboolean any_value_empty = FALSE;
3979
3980 #ifdef MODEST_TOOLKIT_HILDON2
3981         value = hildon_entry_get_text (HILDON_ENTRY (fields->username));
3982 #else
3983         value = gtk_entry_get_text (GTK_ENTRY (fields->username));
3984 #endif
3985         if ((value == NULL) || value[0] == '\0') {
3986                 any_value_empty = TRUE;
3987         }
3988 #ifdef MODEST_TOOLKIT_HILDON2
3989         value = hildon_entry_get_text (HILDON_ENTRY (fields->password));
3990 #else
3991         value = gtk_entry_get_text (GTK_ENTRY (fields->password));
3992 #endif
3993         if ((value == NULL) || value[0] == '\0') {
3994                 any_value_empty = TRUE;
3995         }
3996         gtk_dialog_set_response_sensitive (GTK_DIALOG (fields->dialog), GTK_RESPONSE_ACCEPT, !any_value_empty);
3997 }
3998
3999 void
4000 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
4001                                          const gchar* server_account_name,
4002                                          gchar **username,
4003                                          gchar **password,
4004                                          gboolean *cancel,
4005                                          gboolean *remember,
4006                                          ModestMainWindow *main_window)
4007 {
4008         g_return_if_fail(server_account_name);
4009         gboolean completed = FALSE;
4010         PasswordDialogFields *fields = NULL;
4011
4012         /* Initalize output parameters: */
4013         if (cancel)
4014                 *cancel = FALSE;
4015
4016         if (remember)
4017                 *remember = TRUE;
4018
4019 #ifndef MODEST_TOOLKIT_GTK
4020         /* Maemo uses a different (awkward) button order,
4021          * It should probably just use gtk_alternative_dialog_button_order ().
4022          */
4023 #ifdef MODEST_TOOLKIT_HILDON2
4024         GtkWidget *dialog =
4025                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4026                                              NULL,
4027                                              GTK_DIALOG_MODAL,
4028                                              _HL("wdgt_bd_done"),
4029                                              GTK_RESPONSE_ACCEPT,
4030                                              NULL);
4031         gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
4032                                         HILDON_MARGIN_DOUBLE);
4033 #else
4034         GtkWidget *dialog =
4035                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4036                                              NULL,
4037                                              GTK_DIALOG_MODAL,
4038                                              _("mcen_bd_dialog_ok"),
4039                                              GTK_RESPONSE_ACCEPT,
4040                                              _("mcen_bd_dialog_cancel"),
4041                                              GTK_RESPONSE_REJECT,
4042                                              NULL);
4043 #endif /* MODEST_TOOLKIT_HILDON2 */
4044 #else
4045         GtkWidget *dialog =
4046                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4047                                              NULL,
4048                                              GTK_DIALOG_MODAL,
4049                                              GTK_STOCK_CANCEL,
4050                                              GTK_RESPONSE_REJECT,
4051                                              GTK_STOCK_OK,
4052                                              GTK_RESPONSE_ACCEPT,
4053                                              NULL);
4054 #endif /* MODEST_TOOLKIT_GTK */
4055
4056         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog), NULL);
4057
4058         gchar *server_name = modest_account_mgr_get_server_account_hostname (
4059                 modest_runtime_get_account_mgr(), server_account_name);
4060         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
4061                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
4062                 if (cancel)
4063                         *cancel = TRUE;
4064                 gtk_widget_destroy (dialog);
4065                 return;
4066         }
4067
4068         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
4069         GtkWidget *label = gtk_label_new (txt);
4070         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
4071         g_free (txt);
4072         g_free (server_name);
4073         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label,
4074                             FALSE, FALSE, 0);
4075         server_name = NULL;
4076
4077         /* username: */
4078         gchar *initial_username = modest_account_mgr_get_server_account_username (
4079                 modest_runtime_get_account_mgr(), server_account_name);
4080
4081 #ifdef MODEST_TOOLKIT_HILDON2
4082         GtkWidget *entry_username = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
4083         if (initial_username)
4084                 hildon_entry_set_text (HILDON_ENTRY (entry_username), initial_username);
4085 #else
4086         GtkWidget *entry_username = gtk_entry_new ();
4087         if (initial_username)
4088                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
4089 #endif
4090         /* Dim this if a connection has ever succeeded with this username,
4091          * as per the UI spec: */
4092         /* const gboolean username_known =  */
4093         /*      modest_account_mgr_get_server_account_username_has_succeeded( */
4094         /*              modest_runtime_get_account_mgr(), server_account_name); */
4095         /* gtk_widget_set_sensitive (entry_username, !username_known); */
4096
4097         /* We drop the username sensitive code and disallow changing it here
4098          * as tinymail does not support really changing the username in the callback
4099          */
4100         gtk_widget_set_sensitive (entry_username, FALSE);
4101
4102 #ifndef MODEST_TOOLKIT_GTK
4103         /* Auto-capitalization is the default, so let's turn it off: */
4104         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
4105
4106         /* Create a size group to be used by all captions.
4107          * Note that HildonCaption does not create a default size group if we do not specify one.
4108          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
4109         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
4110
4111 #ifdef MODEST_TOOLKIT_HILDON2
4112         GtkWidget *caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
4113                                                                   _("mail_fi_username"), FALSE,
4114                                                                   entry_username);
4115 #else
4116         GtkWidget *caption = hildon_caption_new (sizegroup,
4117                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
4118 #endif
4119         gtk_widget_show (entry_username);
4120         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
4121                 FALSE, FALSE, MODEST_MARGIN_HALF);
4122         gtk_widget_show (caption);
4123 #else
4124         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
4125                             TRUE, FALSE, 0);
4126 #endif /* !MODEST_TOOLKIT_GTK */
4127
4128         /* password: */
4129 #ifdef MODEST_TOOLKIT_HILDON2
4130         GtkWidget *entry_password = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
4131 #else
4132         GtkWidget *entry_password = gtk_entry_new ();
4133 #endif
4134         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
4135         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
4136
4137 #ifndef MODEST_TOOLKIT_GTK
4138         /* Auto-capitalization is the default, so let's turn it off: */
4139         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
4140                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
4141
4142 #ifdef MODEST_TOOLKIT_HILDON2
4143         caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
4144                                                        _("mail_fi_password"), FALSE,
4145                                                        entry_password);
4146 #else
4147         caption = hildon_caption_new (sizegroup,
4148                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
4149 #endif
4150         gtk_widget_show (entry_password);
4151         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
4152                 FALSE, FALSE, MODEST_MARGIN_HALF);
4153         gtk_widget_show (caption);
4154         g_object_unref (sizegroup);
4155 #else
4156         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
4157                             TRUE, FALSE, 0);
4158 #endif /* !MODEST_TOOLKIT_GTK */
4159
4160         if (initial_username != NULL)
4161                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
4162
4163 /* This is not in the Maemo UI spec:
4164         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
4165         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
4166                             TRUE, FALSE, 0);
4167 */
4168
4169         fields = g_slice_new0 (PasswordDialogFields);
4170         fields->username = entry_username;
4171         fields->password = entry_password;
4172         fields->dialog = dialog;
4173
4174         g_signal_connect (entry_username, "changed", G_CALLBACK (password_dialog_check_field), fields);
4175         g_signal_connect (entry_password, "changed", G_CALLBACK (password_dialog_check_field), fields);
4176         password_dialog_check_field (NULL, fields);
4177
4178         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4179
4180         while (!completed) {
4181
4182                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
4183                         if (username) {
4184 #ifdef MODEST_TOOLKIT_HILDON2
4185                                 *username = g_strdup (hildon_entry_get_text (HILDON_ENTRY(entry_username)));
4186 #else
4187                                 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
4188 #endif
4189
4190                                 /* Note that an empty field becomes the "" string */
4191                                 if (*username && strlen (*username) > 0) {
4192                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(),
4193                                                                                         server_account_name,
4194                                                                                         *username);
4195                                         completed = TRUE;
4196
4197                                         const gboolean username_was_changed =
4198                                                 (strcmp (*username, initial_username) != 0);
4199                                         if (username_was_changed) {
4200                                                 g_warning ("%s: tinymail does not yet support changing the "
4201                                                            "username in the get_password() callback.\n", __FUNCTION__);
4202                                         }
4203                                 } else {
4204                                         g_free (*username);
4205                                         *username = NULL;
4206                                         /* Show error */
4207                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL,
4208                                                                             _("mcen_ib_username_pw_incorrect"));
4209                                         completed = FALSE;
4210                                 }
4211                         }
4212
4213                         if (password) {
4214 #ifdef MODEST_TOOLKIT_HILDON2
4215                                 *password = g_strdup (hildon_entry_get_text (HILDON_ENTRY(entry_password)));
4216 #else
4217                                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
4218 #endif
4219
4220                                 /* We do not save the password in the configuration,
4221                                  * because this function is only called for passwords that should
4222                                  * not be remembered:
4223                                  modest_server_account_set_password (
4224                                  modest_runtime_get_account_mgr(), server_account_name,
4225                                  *password);
4226                                  */
4227                         }
4228                         if (cancel)
4229                                 *cancel   = FALSE;
4230                 } else {
4231 #ifndef MODEST_TOOLKIT_HILDON2
4232                         /* Set parent to NULL or the banner will disappear with its parent dialog */
4233                         modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
4234 #endif
4235                         completed = TRUE;
4236                         if (username)
4237                                 *username = NULL;
4238                         if (password)
4239                                 *password = NULL;
4240                         if (cancel)
4241                                 *cancel   = TRUE;
4242                 }
4243         }
4244
4245 /* This is not in the Maemo UI spec:
4246         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
4247                 *remember = TRUE;
4248         else
4249                 *remember = FALSE;
4250 */
4251
4252         g_free (initial_username);
4253         gtk_widget_destroy (dialog);
4254         g_slice_free (PasswordDialogFields, fields);
4255
4256         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
4257 }
4258
4259 void
4260 modest_ui_actions_on_cut (GtkAction *action,
4261                           ModestWindow *window)
4262 {
4263         GtkWidget *focused_widget;
4264         GtkClipboard *clipboard;
4265
4266         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4267         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4268         if (GTK_IS_EDITABLE (focused_widget)) {
4269                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
4270                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4271                 gtk_clipboard_store (clipboard);
4272         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4273                 GtkTextBuffer *buffer;
4274
4275                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4276                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4277                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
4278                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4279                         gtk_clipboard_store (clipboard);
4280                 }
4281         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4282                 TnyList *header_list = modest_header_view_get_selected_headers (
4283                                 MODEST_HEADER_VIEW (focused_widget));
4284                 gboolean continue_download = FALSE;
4285                 gint num_of_unc_msgs;
4286
4287                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4288
4289                 if (num_of_unc_msgs) {
4290                         TnyAccount *account = get_account_from_header_list (header_list);
4291                         if (account) {
4292                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4293                                 g_object_unref (account);
4294                         }
4295                 }
4296
4297                 if (num_of_unc_msgs == 0 || continue_download) {
4298 /*                      modest_platform_information_banner (
4299                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
4300                         modest_header_view_cut_selection (
4301                                         MODEST_HEADER_VIEW (focused_widget));
4302                 }
4303
4304                 g_object_unref (header_list);
4305         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4306                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
4307         }
4308 }
4309
4310 void
4311 modest_ui_actions_on_copy (GtkAction *action,
4312                            ModestWindow *window)
4313 {
4314         GtkClipboard *clipboard;
4315         GtkWidget *focused_widget;
4316         gboolean copied = TRUE;
4317
4318         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4319         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4320
4321         if (GTK_IS_LABEL (focused_widget)) {
4322                 gchar *selection;
4323                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
4324                 gtk_clipboard_set_text (clipboard, selection, -1);
4325                 g_free (selection);
4326                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4327                 gtk_clipboard_store (clipboard);
4328         } else if (GTK_IS_EDITABLE (focused_widget)) {
4329                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
4330                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4331                 gtk_clipboard_store (clipboard);
4332         } else if (GTK_IS_HTML (focused_widget)) {
4333                 const gchar *sel;
4334                 int len = -1;
4335                 sel = gtk_html_get_selection_html (GTK_HTML (focused_widget), &len);
4336                 if ((sel == NULL) || (sel[0] == '\0')) {
4337                         copied = FALSE;
4338                 } else {
4339                         gtk_html_copy (GTK_HTML (focused_widget));
4340                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4341                         gtk_clipboard_store (clipboard);
4342                 }
4343         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4344                 GtkTextBuffer *buffer;
4345                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4346                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4347                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
4348                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4349                         gtk_clipboard_store (clipboard);
4350                 }
4351         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4352                 TnyList *header_list = modest_header_view_get_selected_headers (
4353                                 MODEST_HEADER_VIEW (focused_widget));
4354                 gboolean continue_download = FALSE;
4355                 gint num_of_unc_msgs;
4356
4357                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4358
4359                 if (num_of_unc_msgs) {
4360                         TnyAccount *account = get_account_from_header_list (header_list);
4361                         if (account) {
4362                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4363                                 g_object_unref (account);
4364                         }
4365                 }
4366
4367                 if (num_of_unc_msgs == 0 || continue_download) {
4368                         modest_platform_information_banner (
4369                                         NULL, NULL, _CS("mcen_ib_getting_items"));
4370                         modest_header_view_copy_selection (
4371                                         MODEST_HEADER_VIEW (focused_widget));
4372                 } else
4373                         copied = FALSE;
4374
4375                 g_object_unref (header_list);
4376
4377         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4378                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
4379         }
4380
4381         /* Show information banner if there was a copy to clipboard */
4382         if(copied)
4383                 modest_platform_information_banner (
4384                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
4385 }
4386
4387 void
4388 modest_ui_actions_on_undo (GtkAction *action,
4389                            ModestWindow *window)
4390 {
4391         ModestEmailClipboard *clipboard = NULL;
4392
4393         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4394                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
4395         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4396                 /* Clear clipboard source */
4397                 clipboard = modest_runtime_get_email_clipboard ();
4398                 modest_email_clipboard_clear (clipboard);
4399         }
4400         else {
4401                 g_return_if_reached ();
4402         }
4403 }
4404
4405 void
4406 modest_ui_actions_on_redo (GtkAction *action,
4407                            ModestWindow *window)
4408 {
4409         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4410                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
4411         }
4412         else {
4413                 g_return_if_reached ();
4414         }
4415 }
4416
4417
4418 static void
4419 destroy_information_note (ModestMailOperation *mail_op,
4420                           gpointer user_data)
4421 {
4422         /* destroy information note */
4423         gtk_widget_destroy (GTK_WIDGET(user_data));
4424 }
4425
4426 static void
4427 destroy_folder_information_note (ModestMailOperation *mail_op,
4428                                  TnyFolder *new_folder,
4429                                  gpointer user_data)
4430 {
4431         /* destroy information note */
4432         gtk_widget_destroy (GTK_WIDGET(user_data));
4433 }
4434
4435
4436 static void
4437 paste_as_attachment_free (gpointer data)
4438 {
4439         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
4440
4441         if (helper->banner) {
4442                 gtk_widget_destroy (helper->banner);
4443                 g_object_unref (helper->banner);
4444         }
4445         g_free (helper);
4446 }
4447
4448 static void
4449 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
4450                             TnyHeader *header,
4451                             TnyMsg *msg,
4452                             gpointer userdata)
4453 {
4454         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
4455         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
4456
4457         if (msg == NULL)
4458                 return;
4459
4460         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
4461
4462 }
4463
4464 void
4465 modest_ui_actions_on_paste (GtkAction *action,
4466                             ModestWindow *window)
4467 {
4468         GtkWidget *focused_widget = NULL;
4469         GtkWidget *inf_note = NULL;
4470         ModestMailOperation *mail_op = NULL;
4471
4472         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4473         if (GTK_IS_EDITABLE (focused_widget)) {
4474                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
4475         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4476                 ModestEmailClipboard *e_clipboard = NULL;
4477                 e_clipboard = modest_runtime_get_email_clipboard ();
4478                 if (modest_email_clipboard_cleared (e_clipboard)) {
4479                         GtkTextBuffer *buffer;
4480                         GtkClipboard *clipboard;
4481
4482                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4483                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4484                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
4485                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4486                         ModestMailOperation *mail_op;
4487                         TnyFolder *src_folder = NULL;
4488                         TnyList *data = NULL;
4489                         gboolean delete;
4490                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
4491                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
4492                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4493                                                                            _CS("ckct_nw_pasting"));
4494                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
4495                         mail_op = modest_mail_operation_new (G_OBJECT (window));
4496                         if (helper->banner != NULL) {
4497                                 g_object_ref (G_OBJECT (helper->banner));
4498                                 gtk_widget_show (GTK_WIDGET (helper->banner));
4499                         }
4500
4501                         if (data != NULL) {
4502                                 modest_mail_operation_get_msgs_full (mail_op,
4503                                                                      data,
4504                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
4505                                                                      helper,
4506                                                                      paste_as_attachment_free);
4507                         }
4508                         /* Free */
4509                         if (data)
4510                                 g_object_unref (data);
4511                         if (src_folder)
4512                                 g_object_unref (src_folder);
4513
4514                 }
4515         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4516                 ModestEmailClipboard *clipboard = NULL;
4517                 TnyFolder *src_folder = NULL;
4518                 TnyFolderStore *folder_store = NULL;
4519                 TnyList *data = NULL;
4520                 gboolean delete = FALSE;
4521
4522                 /* Check clipboard source */
4523                 clipboard = modest_runtime_get_email_clipboard ();
4524                 if (modest_email_clipboard_cleared (clipboard))
4525                         return;
4526
4527                 /* Get elements to paste */
4528                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
4529
4530                 /* Create a new mail operation */
4531                 mail_op = modest_mail_operation_new (G_OBJECT(window));
4532
4533                 /* Get destination folder */
4534                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
4535
4536                 /* transfer messages  */
4537                 if (data != NULL) {
4538                         gint response = 0;
4539
4540                         /* Ask for user confirmation */
4541                         response =
4542                                 modest_ui_actions_msgs_move_to_confirmation (window,
4543                                                                              TNY_FOLDER (folder_store),
4544                                                                              delete,
4545                                                                              data);
4546
4547                         if (response == GTK_RESPONSE_OK) {
4548                                 /* Launch notification */
4549                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4550                                                                              _CS("ckct_nw_pasting"));
4551                                 if (inf_note != NULL)  {
4552                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4553                                         gtk_widget_show (GTK_WIDGET(inf_note));
4554                                 }
4555
4556                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4557                                 modest_mail_operation_xfer_msgs (mail_op,
4558                                                                  data,
4559                                                                  TNY_FOLDER (folder_store),
4560                                                                  delete,
4561                                                                  destroy_information_note,
4562                                                                  inf_note);
4563                         } else {
4564                                 g_object_unref (mail_op);
4565                         }
4566
4567                 } else if (src_folder != NULL) {
4568                         /* Launch notification */
4569                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4570                                                                      _CS("ckct_nw_pasting"));
4571                         if (inf_note != NULL)  {
4572                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4573                                 gtk_widget_show (GTK_WIDGET(inf_note));
4574                         }
4575
4576                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4577                         modest_mail_operation_xfer_folder (mail_op,
4578                                                            src_folder,
4579                                                            folder_store,
4580                                                            delete,
4581                                                            destroy_folder_information_note,
4582                                                            inf_note);
4583                 }
4584
4585                 /* Free */
4586                 if (data != NULL)
4587                         g_object_unref (data);
4588                 if (src_folder != NULL)
4589                         g_object_unref (src_folder);
4590                 if (folder_store != NULL)
4591                         g_object_unref (folder_store);
4592         }
4593 }
4594
4595
4596 void
4597 modest_ui_actions_on_select_all (GtkAction *action,
4598                                  ModestWindow *window)
4599 {
4600         GtkWidget *focused_widget;
4601
4602         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4603         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
4604                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
4605         } else if (GTK_IS_LABEL (focused_widget)) {
4606                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
4607         } else if (GTK_IS_EDITABLE (focused_widget)) {
4608                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
4609         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4610                 GtkTextBuffer *buffer;
4611                 GtkTextIter start, end;
4612
4613                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4614                 gtk_text_buffer_get_start_iter (buffer, &start);
4615                 gtk_text_buffer_get_end_iter (buffer, &end);
4616                 gtk_text_buffer_select_range (buffer, &start, &end);
4617         } else if (GTK_IS_HTML (focused_widget)) {
4618                 gtk_html_select_all (GTK_HTML (focused_widget));
4619         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4620                 GtkWidget *header_view = focused_widget;
4621                 GtkTreeSelection *selection = NULL;
4622
4623                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
4624                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4625                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4626                 }
4627
4628                 /* Disable window dimming management */
4629                 modest_window_disable_dimming (MODEST_WINDOW(window));
4630
4631                 /* Select all messages */
4632                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
4633                 gtk_tree_selection_select_all (selection);
4634
4635                 /* Set focuse on header view */
4636                 gtk_widget_grab_focus (header_view);
4637
4638                 /* Enable window dimming management */
4639                 modest_window_enable_dimming (MODEST_WINDOW(window));
4640                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
4641                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
4642         }
4643
4644 }
4645
4646 void
4647 modest_ui_actions_on_mark_as_read (GtkAction *action,
4648                                    ModestWindow *window)
4649 {
4650         g_return_if_fail (MODEST_IS_WINDOW(window));
4651
4652         /* Mark each header as read */
4653         do_headers_action (window, headers_action_mark_as_read, NULL);
4654 }
4655
4656 void
4657 modest_ui_actions_on_mark_as_unread (GtkAction *action,
4658                                      ModestWindow *window)
4659 {
4660         g_return_if_fail (MODEST_IS_WINDOW(window));
4661
4662         /* Mark each header as read */
4663         do_headers_action (window, headers_action_mark_as_unread, NULL);
4664 }
4665
4666 void
4667 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
4668                                   GtkRadioAction *selected,
4669                                   ModestWindow *window)
4670 {
4671         gint value;
4672
4673         value = gtk_radio_action_get_current_value (selected);
4674         if (MODEST_IS_WINDOW (window)) {
4675                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
4676         }
4677 }
4678
4679 void
4680 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
4681                                                GtkRadioAction *selected,
4682                                                ModestWindow *window)
4683 {
4684         TnyHeaderFlags flags;
4685         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4686
4687         flags = gtk_radio_action_get_current_value (selected);
4688         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
4689 }
4690
4691 void
4692 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
4693                                                   GtkRadioAction *selected,
4694                                                   ModestWindow *window)
4695 {
4696         gint file_format;
4697
4698         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4699
4700         file_format = gtk_radio_action_get_current_value (selected);
4701         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
4702 }
4703
4704
4705 void
4706 modest_ui_actions_on_zoom_plus (GtkAction *action,
4707                                 ModestWindow *window)
4708 {
4709         g_return_if_fail (MODEST_IS_WINDOW (window));
4710
4711         modest_window_zoom_plus (MODEST_WINDOW (window));
4712 }
4713
4714 void
4715 modest_ui_actions_on_zoom_minus (GtkAction *action,
4716                                  ModestWindow *window)
4717 {
4718         g_return_if_fail (MODEST_IS_WINDOW (window));
4719
4720         modest_window_zoom_minus (MODEST_WINDOW (window));
4721 }
4722
4723 void
4724 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
4725                                            ModestWindow *window)
4726 {
4727         ModestWindowMgr *mgr;
4728         gboolean fullscreen, active;
4729         g_return_if_fail (MODEST_IS_WINDOW (window));
4730
4731         mgr = modest_runtime_get_window_mgr ();
4732
4733         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4734         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4735
4736         if (active != fullscreen) {
4737                 modest_window_mgr_set_fullscreen_mode (mgr, active);
4738 #ifndef MODEST_TOOLKIT_HILDON2
4739                 gtk_window_present (GTK_WINDOW (window));
4740 #endif
4741         }
4742 }
4743
4744 void
4745 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4746                                         ModestWindow *window)
4747 {
4748         ModestWindowMgr *mgr;
4749         gboolean fullscreen;
4750
4751         g_return_if_fail (MODEST_IS_WINDOW (window));
4752
4753         mgr = modest_runtime_get_window_mgr ();
4754         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4755         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4756
4757 #ifndef MODEST_TOOLKIT_HILDON2
4758         gtk_window_present (GTK_WINDOW (window));
4759 #endif
4760 }
4761
4762 /*
4763  * Used by modest_ui_actions_on_details to call do_headers_action
4764  */
4765 static void
4766 headers_action_show_details (TnyHeader *header,
4767                              ModestWindow *window,
4768                              gpointer user_data)
4769
4770 {
4771         gboolean async_retrieval;
4772         TnyMsg *msg = NULL;
4773
4774         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4775                 async_retrieval = TRUE;
4776                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (window));
4777         } else {
4778                 async_retrieval = FALSE;
4779         }
4780         modest_platform_run_header_details_dialog (GTK_WINDOW (window), header, async_retrieval, msg);
4781         if (msg)
4782                 g_object_unref (msg);
4783 }
4784
4785 /*
4786  * Show the header details in a ModestDetailsDialog widget
4787  */
4788 void
4789 modest_ui_actions_on_details (GtkAction *action,
4790                               ModestWindow *win)
4791 {
4792         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4793                 TnyMsg *msg;
4794                 TnyHeader *header;
4795
4796                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4797                 if (!msg)
4798                         return;
4799
4800                 header = tny_msg_get_header (msg);
4801                 if (header) {
4802                         headers_action_show_details (header, win, NULL);
4803                         g_object_unref (header);
4804                 }
4805                 g_object_unref (msg);
4806
4807         } else if (MODEST_IS_MAIN_WINDOW (win)) {
4808                 GtkWidget *folder_view, *header_view;
4809
4810                 /* Check which widget has the focus */
4811                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4812                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4813                 if (gtk_widget_is_focus (folder_view)) {
4814                         TnyFolderStore *folder_store
4815                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4816                         if (!folder_store) {
4817                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4818                                 return;
4819                         }
4820                         /* Show only when it's a folder */
4821                         /* This function should not be called for account items,
4822                          * because we dim the menu item for them. */
4823                         if (TNY_IS_FOLDER (folder_store)) {
4824                                 modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4825                                                                            TNY_FOLDER (folder_store));
4826                         }
4827
4828                         g_object_unref (folder_store);
4829
4830                 } else {
4831                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4832                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4833                         /* Show details of each header */
4834                         do_headers_action (win, headers_action_show_details, header_view);
4835                 }
4836 #ifdef MODEST_TOOLKIT_HILDON2
4837         } else if (MODEST_IS_HEADER_WINDOW (win)) {
4838                 TnyFolder *folder;
4839                 GtkWidget *header_view;
4840
4841                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
4842                 folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
4843                 if (folder) {
4844                         modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4845                                                                    folder);
4846                         g_object_unref (folder);
4847                 }
4848 #endif
4849         }
4850 }
4851
4852 void
4853 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4854                                      ModestMsgEditWindow *window)
4855 {
4856         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4857
4858         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4859 }
4860
4861 void
4862 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4863                                       ModestMsgEditWindow *window)
4864 {
4865         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4866
4867         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4868 }
4869
4870 void
4871 modest_ui_actions_toggle_folders_view (GtkAction *action,
4872                                        ModestMainWindow *main_window)
4873 {
4874         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4875
4876         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4877                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4878         else
4879                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4880 }
4881
4882 void
4883 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
4884                                      ModestWindow *window)
4885 {
4886         gboolean active, fullscreen = FALSE;
4887         ModestWindowMgr *mgr;
4888
4889         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4890
4891         /* Check if we want to toggle the toolbar view in fullscreen
4892            or normal mode */
4893         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
4894                      "ViewShowToolbarFullScreen")) {
4895                 fullscreen = TRUE;
4896         }
4897
4898         /* Toggle toolbar */
4899         mgr = modest_runtime_get_window_mgr ();
4900         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4901 }
4902
4903 void
4904 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4905                                            ModestMsgEditWindow *window)
4906 {
4907         modest_msg_edit_window_select_font (window);
4908 }
4909
4910
4911 void
4912 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4913                                                   const gchar *display_name,
4914                                                   GtkWindow *window)
4915 {
4916         /* don't update the display name if it was already set;
4917          * updating the display name apparently is expensive */
4918         const gchar* old_name = gtk_window_get_title (window);
4919
4920         if (display_name == NULL)
4921                 display_name = " ";
4922
4923         if (old_name && display_name && strcmp (old_name, display_name) == 0)
4924                 return; /* don't do anything */
4925
4926         /* This is usually used to change the title of the main window, which
4927          * is the one that holds the folder view. Note that this change can
4928          * happen even when the widget doesn't have the focus. */
4929         gtk_window_set_title (window, display_name);
4930
4931 }
4932
4933 void
4934 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4935 {
4936         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4937         modest_msg_edit_window_select_contacts (window);
4938 }
4939
4940 void
4941 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4942 {
4943         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4944         modest_msg_edit_window_check_names (window, FALSE);
4945 }
4946
4947 #ifndef MODEST_TOOLKIT_HILDON2
4948 /*
4949  * This function is used to track changes in the selection of the
4950  * folder view that is inside the "move to" dialog to enable/disable
4951  * the OK button because we do not want the user to select a disallowed
4952  * destination for a folder.
4953  * The user also not desired to be able to use NEW button on items where
4954  * folder creation is not possibel.
4955  */
4956 static void
4957 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4958                                             TnyFolderStore *folder_store,
4959                                             gboolean selected,
4960                                             gpointer user_data)
4961 {
4962         GtkWidget *dialog = NULL;
4963         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4964         gboolean moving_folder = FALSE;
4965         gboolean is_local_account = TRUE;
4966         GtkWidget *folder_view = NULL;
4967         ModestTnyFolderRules rules;
4968
4969         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4970
4971         if (!selected)
4972                 return;
4973
4974         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4975         if (!dialog)
4976                 return;
4977
4978         /* check if folder_store is an remote account */
4979         if (TNY_IS_ACCOUNT (folder_store)) {
4980                 TnyAccount *local_account = NULL;
4981                 TnyAccount *mmc_account = NULL;
4982                 ModestTnyAccountStore *account_store = NULL;
4983
4984                 account_store = modest_runtime_get_account_store ();
4985                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4986                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4987
4988                 if ((gpointer) local_account != (gpointer) folder_store &&
4989                     (gpointer) mmc_account != (gpointer) folder_store) {
4990                         ModestProtocolType proto;
4991                         proto = modest_tny_account_get_protocol_type (TNY_ACCOUNT (folder_store));
4992                         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
4993                                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
4994                         }
4995                         is_local_account = FALSE;
4996                         /* New button should be dimmed on remote
4997                            POP account root */
4998                         new_sensitive = (modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
4999                                                                                          proto,
5000                                                                                          MODEST_PROTOCOL_REGISTRY_STORE_HAS_FOLDERS));
5001                 }
5002                 g_object_unref (local_account);
5003
5004                 /* It could not exist */
5005                 if (mmc_account)
5006                         g_object_unref (mmc_account);
5007         }
5008
5009         /* Check the target folder rules */
5010         if (TNY_IS_FOLDER (folder_store)) {
5011                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
5012                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
5013                         ok_sensitive = FALSE;
5014                         new_sensitive = FALSE;
5015                         goto end;
5016                 }
5017         }
5018
5019         /* Check if we're moving a folder */
5020         if (MODEST_IS_MAIN_WINDOW (user_data)) {
5021                 /* Get the widgets */
5022                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
5023                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5024                 if (gtk_widget_is_focus (folder_view))
5025                         moving_folder = TRUE;
5026         }
5027
5028         if (moving_folder) {
5029                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
5030
5031                 /* Get the folder to move */
5032                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5033
5034                 /* Check that we're not moving to the same folder */
5035                 if (TNY_IS_FOLDER (moved_folder)) {
5036                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
5037                         if (parent == folder_store)
5038                                 ok_sensitive = FALSE;
5039                         g_object_unref (parent);
5040                 }
5041
5042                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
5043                         /* Do not allow to move to an account unless it's the
5044                            local folders account */
5045                         if (!is_local_account)
5046                                 ok_sensitive = FALSE;
5047                 }
5048
5049                 if (ok_sensitive && (moved_folder == folder_store)) {
5050                         /* Do not allow to move to itself */
5051                         ok_sensitive = FALSE;
5052                 }
5053                 g_object_unref (moved_folder);
5054         } else {
5055                 TnyFolder *src_folder = NULL;
5056
5057                 /* Moving a message */
5058                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
5059
5060                         TnyHeader *header = NULL;
5061                         header = modest_msg_view_window_get_header
5062                                 (MODEST_MSG_VIEW_WINDOW (user_data));
5063                         if (!TNY_IS_HEADER(header))
5064                                 g_warning ("%s: could not get source header", __FUNCTION__);
5065                         else
5066                                 src_folder = tny_header_get_folder (header);
5067
5068                         if (header)
5069                                 g_object_unref (header);
5070                 } else {
5071                         src_folder =
5072                                 TNY_FOLDER (modest_folder_view_get_selected
5073                                             (MODEST_FOLDER_VIEW (folder_view)));
5074                 }
5075
5076                 if (TNY_IS_FOLDER(src_folder)) {
5077                         /* Do not allow to move the msg to the same folder */
5078                         /* Do not allow to move the msg to an account */
5079                         if ((gpointer) src_folder == (gpointer) folder_store ||
5080                             TNY_IS_ACCOUNT (folder_store))
5081                                 ok_sensitive = FALSE;
5082                         g_object_unref (src_folder);
5083                 } else
5084                         g_warning ("%s: could not get source folder", __FUNCTION__);
5085         }
5086
5087  end:
5088         /* Set sensitivity of the OK and NEW button */
5089         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, ok_sensitive);
5090         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), MODEST_GTK_RESPONSE_NEW_FOLDER, new_sensitive);
5091 }
5092 #endif
5093
5094 static void
5095 on_move_to_dialog_response (GtkDialog *dialog,
5096                             gint       response,
5097                             gpointer   user_data)
5098 {
5099         GtkWidget *parent_win;
5100         MoveToInfo *helper = NULL;
5101         ModestFolderView *folder_view;
5102         gboolean unset_edit_mode = FALSE;
5103
5104         helper = (MoveToInfo *) user_data;
5105
5106         parent_win = (GtkWidget *) helper->win;
5107         folder_view = MODEST_FOLDER_VIEW (g_object_get_data (G_OBJECT (dialog),
5108                                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
5109
5110         switch (response) {
5111                 TnyFolderStore *dst_folder;
5112                 TnyFolderStore *selected;
5113
5114         case MODEST_GTK_RESPONSE_NEW_FOLDER:
5115                 selected = modest_folder_view_get_selected (folder_view);
5116                 modest_ui_actions_create_folder (GTK_WIDGET (dialog), GTK_WIDGET (folder_view), selected);
5117                 g_object_unref (selected);
5118                 return;
5119         case GTK_RESPONSE_NONE:
5120         case GTK_RESPONSE_CANCEL:
5121         case GTK_RESPONSE_DELETE_EVENT:
5122                 break;
5123         case GTK_RESPONSE_OK:
5124                 dst_folder = modest_folder_view_get_selected (folder_view);
5125
5126                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
5127                         /* Clean list to move used for filtering */
5128                         modest_folder_view_set_list_to_move (folder_view, NULL);
5129
5130                         modest_ui_actions_on_main_window_move_to (NULL,
5131                                                                   GTK_WIDGET (folder_view),
5132                                                                   dst_folder,
5133                                                                   MODEST_MAIN_WINDOW (parent_win));
5134 #ifdef MODEST_TOOLKIT_HILDON2
5135                 } else if (MODEST_IS_FOLDER_WINDOW (parent_win)) {
5136                         /* Clean list to move used for filtering */
5137                         modest_folder_view_set_list_to_move (folder_view, NULL);
5138
5139                         modest_ui_actions_on_folder_window_move_to (GTK_WIDGET (folder_view),
5140                                                                     dst_folder,
5141                                                                     helper->list,
5142                                                                     GTK_WINDOW (parent_win));
5143 #endif
5144                 } else {
5145                         /* if the user selected a root folder
5146                            (account) then do not perform any action */
5147                         if (TNY_IS_ACCOUNT (dst_folder)) {
5148                                 g_signal_stop_emission_by_name (dialog, "response");
5149                                 return;
5150                         }
5151
5152                         /* Clean list to move used for filtering */
5153                         modest_folder_view_set_list_to_move (folder_view, NULL);
5154
5155                         /* Moving from headers window in edit mode */
5156                         modest_ui_actions_on_window_move_to (NULL, helper->list,
5157                                                              dst_folder,
5158                                                              MODEST_WINDOW (parent_win));
5159                 }
5160
5161                 if (dst_folder)
5162                         g_object_unref (dst_folder);
5163
5164                 unset_edit_mode = TRUE;
5165                 break;
5166         default:
5167                 g_warning ("%s unexpected response id %d", __FUNCTION__, response);
5168         }
5169
5170         /* Free the helper and exit */
5171         if (helper->list)
5172                 g_object_unref (helper->list);
5173         if (unset_edit_mode) {
5174 #ifdef MODEST_TOOLKIT_HILDON2
5175                 modest_hildon2_window_unset_edit_mode (MODEST_HILDON2_WINDOW (helper->win));
5176 #endif
5177         }
5178         g_slice_free (MoveToInfo, helper);
5179         gtk_widget_destroy (GTK_WIDGET (dialog));
5180 }
5181
5182 static GtkWidget*
5183 create_move_to_dialog (GtkWindow *win,
5184                        GtkWidget *folder_view,
5185                        TnyList *list_to_move)
5186 {
5187         GtkWidget *dialog, *tree_view = NULL;
5188
5189         dialog = modest_platform_create_move_to_dialog (win, &tree_view);
5190
5191 #ifndef MODEST_TOOLKIT_HILDON2
5192         /* Track changes in the selection to
5193          * disable the OK button whenever "Move to" is not possible
5194          * disbale NEW button whenever New is not possible */
5195         g_signal_connect (tree_view,
5196                           "folder_selection_changed",
5197                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
5198                           win);
5199 #endif
5200
5201         /* It could happen that we're trying to move a message from a
5202            window (msg window for example) after the main window was
5203            closed, so we can not just get the model of the folder
5204            view */
5205         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
5206                 const gchar *visible_id = NULL;
5207
5208                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5209                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5210                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
5211                                                MODEST_FOLDER_VIEW(tree_view));
5212
5213                 visible_id =
5214                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
5215
5216                 /* Show the same account than the one that is shown in the main window */
5217                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(tree_view),
5218                                                                              visible_id);
5219         } else {
5220                 const gchar *active_account_name = NULL;
5221                 ModestAccountMgr *mgr = NULL;
5222                 ModestAccountSettings *settings = NULL;
5223                 ModestServerAccountSettings *store_settings = NULL;
5224
5225                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5226                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5227                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (tree_view),
5228                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
5229
5230                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
5231                 mgr = modest_runtime_get_account_mgr ();
5232                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
5233
5234                 if (settings) {
5235                         const gchar *store_account_name;
5236                         store_settings = modest_account_settings_get_store_settings (settings);
5237                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
5238
5239                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (tree_view),
5240                                                                                      store_account_name);
5241                         g_object_unref (store_settings);
5242                         g_object_unref (settings);
5243                 }
5244         }
5245
5246         /* we keep a pointer to the embedded folder view, so we can
5247          *   retrieve it with get_folder_view_from_move_to_dialog (see
5248          *   above) later (needed for focus handling)
5249          */
5250         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, tree_view);
5251
5252         /* Hide special folders */
5253 #ifndef MODEST_TOOLKIT_HILDON2
5254         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (tree_view), FALSE);
5255 #endif
5256         if (list_to_move)
5257                 modest_folder_view_set_list_to_move (MODEST_FOLDER_VIEW (tree_view), list_to_move);
5258 #ifndef MODEST_TOOLKIT_HILDON2
5259         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5260 #endif
5261
5262         gtk_widget_show (GTK_WIDGET (tree_view));
5263
5264         return dialog;
5265 }
5266
5267 /*
5268  * Shows a confirmation dialog to the user when we're moving messages
5269  * from a remote server to the local storage. Returns the dialog
5270  * response. If it's other kind of movement then it always returns
5271  * GTK_RESPONSE_OK
5272  *
5273  * This one is used by the next functions:
5274  *      modest_ui_actions_on_paste                      - commented out
5275  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
5276  */
5277 gint
5278 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
5279                                              TnyFolder *dest_folder,
5280                                              gboolean delete,
5281                                              TnyList *headers)
5282 {
5283         gint response = GTK_RESPONSE_OK;
5284         TnyAccount *account = NULL;
5285         TnyFolder *src_folder = NULL;
5286         TnyIterator *iter = NULL;
5287         TnyHeader *header = NULL;
5288
5289         /* return with OK if the destination is a remote folder */
5290         if (modest_tny_folder_is_remote_folder (dest_folder))
5291                 return GTK_RESPONSE_OK;
5292
5293         /* Get source folder */
5294         iter = tny_list_create_iterator (headers);
5295         header = TNY_HEADER (tny_iterator_get_current (iter));
5296         if (header) {
5297                 src_folder = tny_header_get_folder (header);
5298                 g_object_unref (header);
5299         }
5300         g_object_unref (iter);
5301
5302         /* if no src_folder, message may be an attahcment */
5303         if (src_folder == NULL)
5304                 return GTK_RESPONSE_CANCEL;
5305
5306         /* If the source is a local or MMC folder */
5307         if (!modest_tny_folder_is_remote_folder (src_folder)) {
5308                 g_object_unref (src_folder);
5309                 return GTK_RESPONSE_OK;
5310         }
5311
5312         /* Get the account */
5313         account = tny_folder_get_account (src_folder);
5314
5315         /* now if offline we ask the user */
5316         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
5317                 response = GTK_RESPONSE_OK;
5318         else
5319                 response = GTK_RESPONSE_CANCEL;
5320
5321         /* Frees */
5322         g_object_unref (src_folder);
5323         g_object_unref (account);
5324
5325         return response;
5326 }
5327
5328 static void
5329 move_to_helper_destroyer (gpointer user_data)
5330 {
5331         MoveToHelper *helper = (MoveToHelper *) user_data;
5332
5333         /* Close the "Pasting" information banner */
5334         if (helper->banner) {
5335                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
5336                 g_object_unref (helper->banner);
5337         }
5338         if (gtk_tree_row_reference_valid (helper->reference)) {
5339                 gtk_tree_row_reference_free (helper->reference);
5340                 helper->reference = NULL;
5341         }
5342         g_free (helper);
5343 }
5344
5345 static void
5346 move_to_cb (ModestMailOperation *mail_op,
5347             gpointer user_data)
5348 {
5349         MoveToHelper *helper = (MoveToHelper *) user_data;
5350         GObject *object = modest_mail_operation_get_source (mail_op);
5351
5352         /* Note that the operation could have failed, in that case do
5353            nothing */
5354         if (modest_mail_operation_get_status (mail_op) !=
5355             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5356                 goto frees;
5357
5358         if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
5359                 ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
5360
5361                 if (!modest_msg_view_window_select_next_message (self) &&
5362                     !modest_msg_view_window_select_previous_message (self)) {
5363                         /* No more messages to view, so close this window */
5364                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
5365                 }
5366         } else if (MODEST_IS_MAIN_WINDOW (object) &&
5367                    gtk_tree_row_reference_valid (helper->reference)) {
5368                 GtkWidget *header_view;
5369                 GtkTreePath *path;
5370                 GtkTreeSelection *sel;
5371
5372                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5373                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5374                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
5375                 path = gtk_tree_row_reference_get_path (helper->reference);
5376                 /* We need to unselect the previous one
5377                    because we could be copying instead of
5378                    moving */
5379                 gtk_tree_selection_unselect_all (sel);
5380                 gtk_tree_selection_select_path (sel, path);
5381                 gtk_tree_path_free (path);
5382         }
5383         g_object_unref (object);
5384
5385  frees:
5386         /* Destroy the helper */
5387         move_to_helper_destroyer (helper);
5388 }
5389
5390 static void
5391 folder_move_to_cb (ModestMailOperation *mail_op,
5392                    TnyFolder *new_folder,
5393                    gpointer user_data)
5394 {
5395         GtkWidget *folder_view;
5396         GObject *object;
5397
5398         object = modest_mail_operation_get_source (mail_op);
5399         if (MODEST_IS_MAIN_WINDOW (object)) {
5400                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5401                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5402                 g_object_ref (folder_view);
5403                 g_object_unref (object);
5404                 move_to_cb (mail_op, user_data);
5405                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
5406                 g_object_unref (folder_view);
5407         } else {
5408                 move_to_cb (mail_op, user_data);
5409         }
5410 }
5411
5412 static void
5413 msgs_move_to_cb (ModestMailOperation *mail_op,
5414                  gpointer user_data)
5415 {
5416         move_to_cb (mail_op, user_data);
5417 }
5418
5419 void
5420 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
5421                                              gpointer user_data)
5422 {
5423         GObject *win = NULL;
5424         const GError *error;
5425
5426 #ifndef MODEST_TOOLKIT_HILDON2
5427         ModestWindow *main_window = NULL;
5428
5429         /* Disable next automatic folder selection */
5430         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5431                                                          FALSE); /* don't create */
5432
5433         /* Show notification dialog only if the main window exists */
5434         if (main_window) {
5435                 GtkWidget *folder_view = NULL;
5436
5437                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
5438                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5439                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
5440
5441                 if (user_data && TNY_IS_FOLDER (user_data)) {
5442                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
5443                                                           TNY_FOLDER (user_data), FALSE);
5444                 }
5445         }
5446 #endif
5447         win = modest_mail_operation_get_source (mail_op);
5448         error = modest_mail_operation_get_error (mail_op);
5449
5450         /* If it's not a memory full error then show a generic error */
5451         if (!check_memory_full_error ((GtkWidget *) win, (GError *) error, NULL))
5452                 modest_platform_run_information_dialog ((GtkWindow *) win,
5453                                                         _("mail_in_ui_folder_move_target_error"),
5454                                                         FALSE);
5455         if (win)
5456                 g_object_unref (win);
5457 }
5458
5459 static void
5460 open_msg_for_purge_cb (ModestMailOperation *mail_op,
5461                        TnyHeader *header,
5462                        gboolean canceled,
5463                        TnyMsg *msg,
5464                        GError *err,
5465                        gpointer user_data)
5466 {
5467         TnyList *parts;
5468         TnyIterator *iter;
5469         gint pending_purges = 0;
5470         gboolean some_purged = FALSE;
5471         ModestWindow *win = MODEST_WINDOW (user_data);
5472         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
5473
5474         /* If there was any error */
5475         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
5476                 modest_window_mgr_unregister_header (mgr, header);
5477                 return;
5478         }
5479
5480         /* Once the message has been retrieved for purging, we check if
5481          * it's all ok for purging */
5482
5483         parts = tny_simple_list_new ();
5484         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
5485         iter = tny_list_create_iterator (parts);
5486
5487         while (!tny_iterator_is_done (iter)) {
5488                 TnyMimePart *part;
5489                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5490                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
5491                         if (tny_mime_part_is_purged (part))
5492                                 some_purged = TRUE;
5493                         else
5494                                 pending_purges++;
5495                 }
5496
5497                 if (part)
5498                         g_object_unref (part);
5499
5500                 tny_iterator_next (iter);
5501         }
5502         g_object_unref (iter);
5503
5504
5505         if (pending_purges>0) {
5506                 gint response;
5507                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
5508
5509                 if (response == GTK_RESPONSE_OK) {
5510                         GtkWidget *info;
5511                         info =
5512                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_me_inbox_remove_attachments"));
5513                         iter = tny_list_create_iterator (parts);
5514                         while (!tny_iterator_is_done (iter)) {
5515                                 TnyMimePart *part;
5516
5517                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5518                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
5519                                         tny_mime_part_set_purged (part);
5520
5521                                 if (part)
5522                                         g_object_unref (part);
5523
5524                                 tny_iterator_next (iter);
5525                         }
5526                         g_object_unref (iter);
5527
5528                         tny_msg_rewrite_cache (msg);
5529
5530                         gtk_widget_destroy (info);
5531                 }
5532         }
5533
5534         modest_window_mgr_unregister_header (mgr, header);
5535
5536         g_object_unref (parts);
5537 }
5538
5539 static void
5540 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
5541                                                      ModestMainWindow *win)
5542 {
5543         GtkWidget *header_view;
5544         TnyList *header_list;
5545         TnyHeader *header;
5546         TnyHeaderFlags flags;
5547         ModestWindow *msg_view_window =  NULL;
5548         gboolean found;
5549
5550         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5551
5552         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5553                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5554
5555         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5556         if (!header_list) {
5557                 g_warning ("%s: no header selected", __FUNCTION__);
5558                 return;
5559         }
5560
5561         if (tny_list_get_length (header_list) == 1) {
5562                 TnyIterator *iter = tny_list_create_iterator (header_list);
5563                 header = TNY_HEADER (tny_iterator_get_current (iter));
5564                 g_object_unref (iter);
5565         } else
5566                 return;
5567
5568         if (!header || !TNY_IS_HEADER(header)) {
5569                 g_warning ("%s: header is not valid", __FUNCTION__);
5570                 return;
5571         }
5572
5573         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
5574                                                           header, &msg_view_window);
5575         flags = tny_header_get_flags (header);
5576         if (!(flags & TNY_HEADER_FLAG_CACHED))
5577                 return;
5578         if (found) {
5579                 if (msg_view_window != NULL)
5580                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
5581                 else {
5582                         /* do nothing; uid was registered before, so window is probably on it's way */
5583                         g_debug ("header %p has already been registered", header);
5584                 }
5585         } else {
5586                 ModestMailOperation *mail_op = NULL;
5587                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
5588                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
5589                                                                          modest_ui_actions_disk_operations_error_handler,
5590                                                                          NULL, NULL);
5591                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5592                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
5593
5594                 g_object_unref (mail_op);
5595         }
5596         if (header)
5597                 g_object_unref (header);
5598         if (header_list)
5599                 g_object_unref (header_list);
5600 }
5601
5602 /*
5603  * Checks if we need a connection to do the transfer and if the user
5604  * wants to connect to complete it
5605  */
5606 static void
5607 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5608                                        TnyFolderStore *src_folder,
5609                                        TnyList *headers,
5610                                        TnyFolder *dst_folder,
5611                                        gboolean delete_originals,
5612                                        gboolean *need_connection,
5613                                        gboolean *do_xfer)
5614 {
5615         TnyAccount *src_account;
5616         gint uncached_msgs = 0;
5617
5618         /* We don't need any further check if
5619          *
5620          * 1- the source folder is local OR
5621          * 2- the device is already online
5622          */
5623         if (!modest_tny_folder_store_is_remote (src_folder) ||
5624             tny_device_is_online (modest_runtime_get_device())) {
5625                 *need_connection = FALSE;
5626                 *do_xfer = TRUE;
5627                 return;
5628         }
5629
5630         /* We must ask for a connection when
5631          *
5632          *   - the message(s) is not already cached   OR
5633          *   - the message(s) is cached but the leave_on_server setting
5634          * is FALSE (because we need to sync the source folder to
5635          * delete the message from the server (for IMAP we could do it
5636          * offline, it'll take place the next time we get a
5637          * connection)
5638          */
5639         uncached_msgs = header_list_count_uncached_msgs (headers);
5640         src_account = get_account_from_folder_store (src_folder);
5641         if (uncached_msgs > 0) {
5642                 guint num_headers;
5643                 const gchar *msg;
5644
5645                 *need_connection = TRUE;
5646                 num_headers = tny_list_get_length (headers);
5647                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
5648
5649                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
5650                     GTK_RESPONSE_CANCEL) {
5651                         *do_xfer = FALSE;
5652                 } else {
5653                         *do_xfer = TRUE;
5654                 }
5655         } else {
5656                 /* The transfer is possible and the user wants to */
5657                 *do_xfer = TRUE;
5658
5659                 if (remote_folder_has_leave_on_server (src_folder) && delete_originals) {
5660                         const gchar *account_name;
5661                         gboolean leave_on_server;
5662
5663                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
5664                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
5665                                                                                   account_name);
5666
5667                         if (leave_on_server == TRUE) {
5668                                 *need_connection = FALSE;
5669                         } else {
5670                                 *need_connection = TRUE;
5671                         }
5672                 } else {
5673                         *need_connection = FALSE;
5674                 }
5675         }
5676
5677         /* Frees */
5678         g_object_unref (src_account);
5679 }
5680
5681 static void
5682 xfer_messages_error_handler (ModestMailOperation *mail_op,
5683                              gpointer user_data)
5684 {
5685         GObject *win;
5686         const GError *error;
5687
5688         win = modest_mail_operation_get_source (mail_op);
5689         error = modest_mail_operation_get_error (mail_op);
5690
5691         if (error && is_memory_full_error ((GError *) error, mail_op, NULL)) {
5692                 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
5693                 modest_platform_information_banner ((GtkWidget *) win, NULL, msg);
5694                 g_free (msg);
5695         } else {
5696                 modest_platform_run_information_dialog ((GtkWindow *) win,
5697                                                         _("mail_in_ui_folder_move_target_error"),
5698                                                         FALSE);
5699         }
5700         if (win)
5701                 g_object_unref (win);
5702 }
5703
5704 typedef struct {
5705         TnyFolderStore *dst_folder;
5706         TnyList *headers;
5707 } XferMsgsHelper;
5708
5709 /**
5710  * Utility function that transfer messages from both the main window
5711  * and the msg view window when using the "Move to" dialog
5712  */
5713 static void
5714 xfer_messages_performer  (gboolean canceled,
5715                           GError *err,
5716                           GtkWindow *parent_window,
5717                           TnyAccount *account,
5718                           gpointer user_data)
5719 {
5720         ModestWindow *win = MODEST_WINDOW (parent_window);
5721         TnyAccount *dst_account = NULL;
5722         gboolean dst_forbids_message_add = FALSE;
5723         XferMsgsHelper *helper;
5724         MoveToHelper *movehelper;
5725         ModestMailOperation *mail_op;
5726
5727         helper = (XferMsgsHelper *) user_data;
5728
5729         if (canceled || err) {
5730                 if (!check_memory_full_error ((GtkWidget *) parent_window, err, NULL)) {
5731                         /* Show the proper error message */
5732                         modest_ui_actions_on_account_connection_error (parent_window, account);
5733                 }
5734                 goto end;
5735         }
5736
5737         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
5738
5739         /* tinymail will return NULL for local folders it seems */
5740         dst_forbids_message_add = modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5741                                                                                   modest_tny_account_get_protocol_type (dst_account),
5742                                                                                   MODEST_PROTOCOL_REGISTRY_STORE_FORBID_MESSAGE_ADD);
5743         g_object_unref (dst_account);
5744
5745         if (dst_forbids_message_add) {
5746                 modest_platform_information_banner (GTK_WIDGET (win),
5747                                                     NULL,
5748                                                     ngettext("mail_in_ui_folder_move_target_error",
5749                                                              "mail_in_ui_folder_move_targets_error",
5750                                                              tny_list_get_length (helper->headers)));
5751                 goto end;
5752         }
5753
5754         movehelper = g_new0 (MoveToHelper, 1);
5755
5756 #ifndef MODEST_TOOLKIT_HILDON2
5757         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
5758                                                                _CS("ckct_nw_pasting"));
5759         if (movehelper->banner != NULL)  {
5760                 g_object_ref (movehelper->banner);
5761                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
5762         }
5763 #endif
5764
5765         if (MODEST_IS_MAIN_WINDOW (win)) {
5766                 GtkWidget *header_view =
5767                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5768                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5769                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5770         }
5771
5772         /* Perform the mail operation */
5773         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5774                                                                  xfer_messages_error_handler,
5775                                                                  movehelper, NULL);
5776         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5777                                          mail_op);
5778
5779         modest_mail_operation_xfer_msgs (mail_op,
5780                                          helper->headers,
5781                                          TNY_FOLDER (helper->dst_folder),
5782                                          TRUE,
5783                                          msgs_move_to_cb,
5784                                          movehelper);
5785
5786         g_object_unref (G_OBJECT (mail_op));
5787  end:
5788         g_object_unref (helper->dst_folder);
5789         g_object_unref (helper->headers);
5790         g_slice_free (XferMsgsHelper, helper);
5791 }
5792
5793 typedef struct {
5794         TnyFolder *src_folder;
5795         TnyFolderStore *dst_folder;
5796         gboolean delete_original;
5797         GtkWidget *folder_view;
5798 } MoveFolderInfo;
5799
5800 static void
5801 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window,
5802                 TnyAccount *account, gpointer user_data)
5803 {
5804         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5805         GtkTreeSelection *sel;
5806         ModestMailOperation *mail_op = NULL;
5807
5808         if (canceled || err || !MODEST_IS_WINDOW (parent_window)) {
5809                 /* Note that the connection process can fail due to
5810                    memory low conditions as it can not successfully
5811                    store the summary */
5812                 if (!check_memory_full_error ((GtkWidget*) parent_window, err, NULL))
5813                         g_debug ("Error connecting when trying to move a folder");
5814
5815                 g_object_unref (G_OBJECT (info->src_folder));
5816                 g_object_unref (G_OBJECT (info->dst_folder));
5817                 g_free (info);
5818                 return;
5819         }
5820
5821         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5822 #ifndef MODEST_TOOLKIT_HILDON2
5823         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5824                         _CS("ckct_nw_pasting"));
5825         if (helper->banner != NULL)  {
5826                 g_object_ref (helper->banner);
5827                 gtk_widget_show (GTK_WIDGET(helper->banner));
5828         }
5829 #endif
5830         /* Clean folder on header view before moving it */
5831         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5832         gtk_tree_selection_unselect_all (sel);
5833
5834         /* Let gtk events run. We need that the folder
5835            view frees its reference to the source
5836            folder *before* issuing the mail operation
5837            so we need the signal handler of selection
5838            changed to happen before the mail
5839            operation
5840         while (gtk_events_pending ())
5841                 gtk_main_iteration ();   */
5842
5843         mail_op =
5844                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5845                                 modest_ui_actions_move_folder_error_handler,
5846                                 info->src_folder, NULL);
5847         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5848                         mail_op);
5849
5850         /* Select *after* the changes */
5851         /* TODO: this function hangs UI after transfer */
5852         /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
5853         /*                                                        TNY_FOLDER (src_folder), TRUE); */
5854
5855         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
5856                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5857                                                   TNY_FOLDER (info->dst_folder), TRUE);
5858         }
5859         modest_mail_operation_xfer_folder (mail_op,
5860                         TNY_FOLDER (info->src_folder),
5861                         info->dst_folder,
5862                         info->delete_original,
5863                         folder_move_to_cb,
5864                         helper);
5865         g_object_unref (G_OBJECT (info->src_folder));
5866
5867         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
5868         /* } */
5869
5870         /* Unref mail operation */
5871         g_object_unref (G_OBJECT (mail_op));
5872         g_object_unref (G_OBJECT (info->dst_folder));
5873         g_free (user_data);
5874 }
5875
5876 static TnyAccount *
5877 get_account_from_folder_store (TnyFolderStore *folder_store)
5878 {
5879         if (TNY_IS_ACCOUNT (folder_store))
5880                 return g_object_ref (folder_store);
5881         else
5882                 return tny_folder_get_account (TNY_FOLDER (folder_store));
5883 }
5884
5885 /*
5886  * UI handler for the "Move to" action when invoked from the
5887  * ModestMainWindow
5888  */
5889 static void
5890 modest_ui_actions_on_main_window_move_to (GtkAction *action,
5891                                           GtkWidget *folder_view,
5892                                           TnyFolderStore *dst_folder,
5893                                           ModestMainWindow *win)
5894 {
5895         ModestHeaderView *header_view = NULL;
5896         TnyFolderStore *src_folder = NULL;
5897
5898         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5899
5900         /* Get the source folder */
5901         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5902
5903         /* Get header view */
5904         header_view = (ModestHeaderView *)
5905                 modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5906
5907         /* Get folder or messages to transfer */
5908         if (gtk_widget_is_focus (folder_view)) {
5909                 gboolean do_xfer = TRUE;
5910
5911                 /* Allow only to transfer folders to the local root folder */
5912                 if (TNY_IS_ACCOUNT (dst_folder) &&
5913                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5914                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5915                         do_xfer = FALSE;
5916                 } else if (!TNY_IS_FOLDER (src_folder)) {
5917                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5918                         do_xfer = FALSE;
5919                 }
5920
5921                 if (do_xfer) {
5922                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5923                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5924
5925                         info->src_folder = g_object_ref (src_folder);
5926                         info->dst_folder = g_object_ref (dst_folder);
5927                         info->delete_original = TRUE;
5928                         info->folder_view = folder_view;
5929
5930                         connect_info->callback = on_move_folder_cb;
5931                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5932                         connect_info->data = info;
5933
5934                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5935                                                                    TNY_FOLDER_STORE (src_folder),
5936                                                                    connect_info);
5937                 }
5938         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5939                 TnyList *headers;
5940
5941                 headers = modest_header_view_get_selected_headers(header_view);
5942
5943                 /* Transfer the messages */
5944                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder),
5945                                                             headers, TNY_FOLDER (dst_folder));
5946
5947                 g_object_unref (headers);
5948         }
5949
5950         /* Frees */
5951         g_object_unref (src_folder);
5952 }
5953
5954 #ifdef MODEST_TOOLKIT_HILDON2
5955 /*
5956  * UI handler for the "Move to" action when invoked from the
5957  * ModestFolderWindow
5958  */
5959 static void
5960 modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
5961                                             TnyFolderStore *dst_folder,
5962                                             TnyList *selection,
5963                                             GtkWindow *win)
5964 {
5965         TnyFolderStore *src_folder = NULL;
5966         TnyIterator *iterator;
5967
5968         if (tny_list_get_length (selection) != 1)
5969                 return;
5970
5971         iterator = tny_list_create_iterator (selection);
5972         src_folder = TNY_FOLDER_STORE (tny_iterator_get_current (iterator));
5973         g_object_unref (iterator);
5974
5975
5976         gboolean do_xfer = TRUE;
5977
5978         /* Allow only to transfer folders to the local root folder */
5979         if (TNY_IS_ACCOUNT (dst_folder) &&
5980             !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5981             !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5982                 do_xfer = FALSE;
5983                 /* Show an error */
5984                 modest_platform_run_information_dialog (win,
5985                                                         _("mail_in_ui_folder_move_target_error"),
5986                                                         FALSE);
5987         } else if (!TNY_IS_FOLDER (src_folder)) {
5988                 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5989                 do_xfer = FALSE;
5990         }
5991
5992         if (do_xfer) {
5993                 MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5994                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5995
5996                 info->src_folder = g_object_ref (src_folder);
5997                 info->dst_folder = g_object_ref (dst_folder);
5998                 info->delete_original = TRUE;
5999                 info->folder_view = folder_view;
6000
6001                 connect_info->callback = on_move_folder_cb;
6002                 connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
6003                 connect_info->data = info;
6004
6005                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
6006                                                            TNY_FOLDER_STORE (src_folder),
6007                                                            connect_info);
6008         }
6009
6010         /* Frees */
6011         g_object_unref (src_folder);
6012 }
6013 #endif
6014
6015
6016 void
6017 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
6018                                             TnyFolder *src_folder,
6019                                             TnyList *headers,
6020                                             TnyFolder *dst_folder)
6021 {
6022         gboolean need_connection = TRUE;
6023         gboolean do_xfer = TRUE;
6024         XferMsgsHelper *helper;
6025
6026         g_return_if_fail (TNY_IS_FOLDER (src_folder));
6027         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
6028         g_return_if_fail (TNY_IS_LIST (headers));
6029
6030         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder),
6031                                                headers, TNY_FOLDER (dst_folder),
6032                                                TRUE, &need_connection,
6033                                                &do_xfer);
6034
6035         /* If we don't want to transfer just return */
6036         if (!do_xfer)
6037                 return;
6038
6039         /* Create the helper */
6040         helper = g_slice_new (XferMsgsHelper);
6041         helper->dst_folder = g_object_ref (dst_folder);
6042         helper->headers = g_object_ref (headers);
6043
6044         if (need_connection) {
6045                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
6046                 connect_info->callback = xfer_messages_performer;
6047                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
6048                 connect_info->data = helper;
6049
6050                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
6051                                                            TNY_FOLDER_STORE (src_folder),
6052                                                            connect_info);
6053         } else {
6054                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
6055                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
6056                                          src_account, helper);
6057                 g_object_unref (src_account);
6058         }
6059 }
6060
6061 /*
6062  * UI handler for the "Move to" action when invoked from the
6063  * ModestMsgViewWindow
6064  */
6065 static void
6066 modest_ui_actions_on_window_move_to (GtkAction *action,
6067                                      TnyList *headers,
6068                                      TnyFolderStore *dst_folder,
6069                                      ModestWindow *win)
6070 {
6071         TnyFolder *src_folder = NULL;
6072
6073         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
6074
6075         if (headers) {
6076                 TnyHeader *header = NULL;
6077                 TnyIterator *iter;
6078
6079                 iter = tny_list_create_iterator (headers);
6080                 header = (TnyHeader *) tny_iterator_get_current (iter);
6081                 src_folder = tny_header_get_folder (header);
6082
6083                 /* Transfer the messages */
6084                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder,
6085                                                             headers,
6086                                                             TNY_FOLDER (dst_folder));
6087
6088                 /* Frees */
6089                 g_object_unref (header);
6090                 g_object_unref (iter);
6091                 g_object_unref (src_folder);
6092         }
6093 }
6094
6095 void
6096 modest_ui_actions_on_move_to (GtkAction *action,
6097                               ModestWindow *win)
6098 {
6099         modest_ui_actions_on_edit_mode_move_to (win);
6100 }
6101
6102 gboolean
6103 modest_ui_actions_on_edit_mode_move_to (ModestWindow *win)
6104 {
6105         GtkWidget *dialog = NULL;
6106         MoveToInfo *helper = NULL;
6107         TnyList *list_to_move;
6108
6109         g_return_val_if_fail (MODEST_IS_WINDOW (win), FALSE);
6110
6111 #ifndef MODEST_TOOLKIT_HILDON2
6112         /* Get the main window if exists */
6113         ModestMainWindow *main_window;
6114         if (MODEST_IS_MAIN_WINDOW (win))
6115                 main_window = MODEST_MAIN_WINDOW (win);
6116         else
6117                 main_window =
6118                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
6119                                                                                FALSE)); /* don't create */
6120 #endif
6121
6122         list_to_move = modest_platform_get_list_to_move (MODEST_WINDOW (win));
6123
6124         if (!list_to_move)
6125                 return FALSE;
6126
6127         if (tny_list_get_length (list_to_move) < 1) {
6128                 g_object_unref (list_to_move);
6129                 return FALSE;
6130         }
6131
6132         /* Create and run the dialog */
6133         dialog = create_move_to_dialog (GTK_WINDOW (win), NULL, list_to_move);
6134         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
6135                                      GTK_WINDOW (dialog),
6136                                      (GtkWindow *) win);
6137
6138         /* Create helper */
6139         helper = g_slice_new0 (MoveToInfo);
6140         helper->list = list_to_move;
6141         helper->win = win;
6142
6143         /* Listen to response signal */
6144         g_signal_connect (dialog, "response", G_CALLBACK (on_move_to_dialog_response), helper);
6145
6146         /* Show the dialog */
6147         gtk_widget_show (dialog);
6148
6149         return FALSE;
6150 }
6151
6152 /*
6153  * Calls #HeadersFunc for each header already selected in the main
6154  * window or the message currently being shown in the msg view window
6155  */
6156 static void
6157 do_headers_action (ModestWindow *win,
6158                    HeadersFunc func,
6159                    gpointer user_data)
6160 {
6161         TnyList *headers_list = NULL;
6162         TnyIterator *iter = NULL;
6163         TnyHeader *header = NULL;
6164         TnyFolder *folder = NULL;
6165
6166         /* Get headers */
6167         headers_list = get_selected_headers (win);
6168         if (!headers_list)
6169                 return;
6170
6171         /* Get the folder */
6172         iter = tny_list_create_iterator (headers_list);
6173         header = TNY_HEADER (tny_iterator_get_current (iter));
6174         if (header) {
6175                 folder = tny_header_get_folder (header);
6176                 g_object_unref (header);
6177         }
6178
6179         /* Call the function for each header */
6180         while (!tny_iterator_is_done (iter)) {
6181                 header = TNY_HEADER (tny_iterator_get_current (iter));
6182                 func (header, win, user_data);
6183                 g_object_unref (header);
6184                 tny_iterator_next (iter);
6185         }
6186
6187         /* Trick: do a poke status in order to speed up the signaling
6188            of observers */
6189         if (folder) {
6190                 tny_folder_poke_status (folder);
6191                 g_object_unref (folder);
6192         }
6193
6194         /* Frees */
6195         g_object_unref (iter);
6196         g_object_unref (headers_list);
6197 }
6198
6199 void
6200 modest_ui_actions_view_attachment (GtkAction *action,
6201                                    ModestWindow *window)
6202 {
6203         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6204                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
6205         } else {
6206                 /* not supported window for this action */
6207                 g_return_if_reached ();
6208         }
6209 }
6210
6211 void
6212 modest_ui_actions_save_attachments (GtkAction *action,
6213                                     ModestWindow *window)
6214 {
6215         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6216
6217                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
6218                         return;
6219
6220                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
6221         } else {
6222                 /* not supported window for this action */
6223                 g_return_if_reached ();
6224         }
6225 }
6226
6227 void
6228 modest_ui_actions_remove_attachments (GtkAction *action,
6229                                       ModestWindow *window)
6230 {
6231         if (MODEST_IS_MAIN_WINDOW (window)) {
6232                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
6233         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6234                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
6235         } else {
6236                 /* not supported window for this action */
6237                 g_return_if_reached ();
6238         }
6239 }
6240
6241 void
6242 modest_ui_actions_on_settings (GtkAction *action,
6243                                ModestWindow *win)
6244 {
6245         GtkWidget *dialog;
6246
6247         dialog = modest_platform_get_global_settings_dialog ();
6248         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
6249         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
6250         gtk_widget_show_all (dialog);
6251
6252         gtk_dialog_run (GTK_DIALOG (dialog));
6253
6254         gtk_widget_destroy (dialog);
6255 }
6256
6257 void
6258 modest_ui_actions_on_help (GtkAction *action,
6259                            GtkWindow *win)
6260 {
6261         /* Help app is not available at all in fremantle */
6262 #ifndef MODEST_TOOLKIT_HILDON2
6263         const gchar *help_id;
6264
6265         g_return_if_fail (win && GTK_IS_WINDOW(win));
6266
6267         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
6268
6269         if (help_id)
6270                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6271 #endif
6272 }
6273
6274 void
6275 modest_ui_actions_on_csm_help (GtkAction *action,
6276                                GtkWindow *win)
6277 {
6278         /* Help app is not available at all in fremantle */
6279 #ifndef MODEST_TOOLKIT_HILDON2
6280
6281         const gchar* help_id = NULL;
6282         GtkWidget *folder_view;
6283         TnyFolderStore *folder_store;
6284
6285         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
6286
6287         /* Get selected folder */
6288         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
6289                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6290         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6291
6292         /* Switch help_id */
6293         if (folder_store && TNY_IS_FOLDER (folder_store))
6294                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
6295
6296         if (folder_store)
6297                 g_object_unref (folder_store);
6298
6299         if (help_id)
6300                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6301         else
6302                 modest_ui_actions_on_help (action, win);
6303 #endif
6304 }
6305
6306 static void
6307 retrieve_contents_cb (ModestMailOperation *mail_op,
6308                       TnyHeader *header,
6309                       gboolean canceled,
6310                       TnyMsg *msg,
6311                       GError *err,
6312                       gpointer user_data)
6313 {
6314         /* We only need this callback to show an error in case of
6315            memory low condition */
6316         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
6317                 g_debug ("%s: message failed to retrieve. Memory low?", __FUNCTION__);
6318         }
6319 }
6320
6321 static void
6322 retrieve_msg_contents_performer (gboolean canceled,
6323                                  GError *err,
6324                                  GtkWindow *parent_window,
6325                                  TnyAccount *account,
6326                                  gpointer user_data)
6327 {
6328         ModestMailOperation *mail_op;
6329         TnyList *headers = TNY_LIST (user_data);
6330
6331         if (err || canceled) {
6332                 check_memory_full_error ((GtkWidget *) parent_window, err, NULL);
6333                 goto out;
6334         }
6335
6336         /* Create mail operation */
6337         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
6338                                                                  modest_ui_actions_disk_operations_error_handler,
6339                                                                  NULL, NULL);
6340         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
6341         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
6342
6343         /* Frees */
6344         g_object_unref (mail_op);
6345  out:
6346         g_object_unref (headers);
6347         g_object_unref (account);
6348 }
6349
6350 void
6351 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
6352                                             ModestWindow *window)
6353 {
6354         TnyList *headers = NULL;
6355         TnyAccount *account = NULL;
6356         TnyIterator *iter = NULL;
6357         TnyHeader *header = NULL;
6358         TnyFolder *folder = NULL;
6359
6360         /* Get headers */
6361         headers = get_selected_headers (window);
6362         if (!headers)
6363                 return;
6364
6365         /* Pick the account */
6366         iter = tny_list_create_iterator (headers);
6367         header = TNY_HEADER (tny_iterator_get_current (iter));
6368         folder = tny_header_get_folder (header);
6369         account = tny_folder_get_account (folder);
6370         g_object_unref (folder);
6371         g_object_unref (header);
6372         g_object_unref (iter);
6373
6374         /* Connect and perform the message retrieval */
6375         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
6376                                              g_object_ref (account),
6377                                              retrieve_msg_contents_performer,
6378                                              g_object_ref (headers));
6379
6380         /* Frees */
6381         g_object_unref (account);
6382         g_object_unref (headers);
6383 }
6384
6385 void
6386 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
6387 {
6388         g_return_if_fail (MODEST_IS_WINDOW (window));
6389
6390         /* Update dimmed */
6391         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
6392 }
6393
6394 void
6395 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
6396 {
6397         g_return_if_fail (MODEST_IS_WINDOW (window));
6398
6399         /* Update dimmed */
6400         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
6401 }
6402
6403 void
6404 modest_ui_actions_on_email_menu_activated (GtkAction *action,
6405                                           ModestWindow *window)
6406 {
6407         g_return_if_fail (MODEST_IS_WINDOW (window));
6408
6409         /* Update dimmed */
6410         modest_ui_actions_check_menu_dimming_rules (window);
6411 }
6412
6413 void
6414 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
6415                                           ModestWindow *window)
6416 {
6417         g_return_if_fail (MODEST_IS_WINDOW (window));
6418
6419         /* Update dimmed */
6420         modest_ui_actions_check_menu_dimming_rules (window);
6421 }
6422
6423 void
6424 modest_ui_actions_on_view_menu_activated (GtkAction *action,
6425                                           ModestWindow *window)
6426 {
6427         g_return_if_fail (MODEST_IS_WINDOW (window));
6428
6429         /* Update dimmed */
6430         modest_ui_actions_check_menu_dimming_rules (window);
6431 }
6432
6433 void
6434 modest_ui_actions_on_format_menu_activated (GtkAction *action,
6435                                             ModestWindow *window)
6436 {
6437         g_return_if_fail (MODEST_IS_WINDOW (window));
6438
6439         /* Update dimmed */
6440         modest_ui_actions_check_menu_dimming_rules (window);
6441 }
6442
6443 void
6444 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
6445                                           ModestWindow *window)
6446 {
6447         g_return_if_fail (MODEST_IS_WINDOW (window));
6448
6449         /* Update dimmed */
6450         modest_ui_actions_check_menu_dimming_rules (window);
6451 }
6452
6453 void
6454 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
6455                                           ModestWindow *window)
6456 {
6457         g_return_if_fail (MODEST_IS_WINDOW (window));
6458
6459         /* Update dimmed */
6460         modest_ui_actions_check_menu_dimming_rules (window);
6461 }
6462
6463 void
6464 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
6465                                                  ModestWindow *window)
6466 {
6467         g_return_if_fail (MODEST_IS_WINDOW (window));
6468
6469         /* Update dimmed */
6470         modest_ui_actions_check_menu_dimming_rules (window);
6471 }
6472
6473 void
6474 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
6475                                                      ModestWindow *window)
6476 {
6477         g_return_if_fail (MODEST_IS_WINDOW (window));
6478
6479         /* Update dimmed */
6480         modest_ui_actions_check_menu_dimming_rules (window);
6481 }
6482
6483 void
6484 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
6485                                                      ModestWindow *window)
6486 {
6487         g_return_if_fail (MODEST_IS_WINDOW (window));
6488
6489         /* Update dimmed */
6490         modest_ui_actions_check_menu_dimming_rules (window);
6491 }
6492
6493 void
6494 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
6495 {
6496         g_return_if_fail (MODEST_IS_WINDOW (window));
6497
6498         /* we check for low-mem; in that case, show a warning, and don't allow
6499          * searching
6500          */
6501         if (modest_platform_check_memory_low (window, TRUE))
6502                 return;
6503
6504         modest_platform_show_search_messages (GTK_WINDOW (window));
6505 }
6506
6507 void
6508 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
6509 {
6510         g_return_if_fail (MODEST_IS_WINDOW (win));
6511
6512
6513         /* we check for low-mem; in that case, show a warning, and don't allow
6514          * for the addressbook
6515          */
6516         if (modest_platform_check_memory_low (win, TRUE))
6517                 return;
6518
6519
6520         modest_platform_show_addressbook (GTK_WINDOW (win));
6521 }
6522
6523
6524 void
6525 modest_ui_actions_on_toggle_find_in_page (GtkAction *action,
6526                                           ModestWindow *window)
6527 {
6528         gboolean active;
6529         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
6530
6531         if (GTK_IS_TOGGLE_ACTION (action))
6532                 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
6533         else
6534                 active = TRUE;
6535
6536         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window),
6537                                                     active);
6538 }
6539
6540 static void
6541 on_send_receive_finished (ModestMailOperation  *mail_op,
6542                            gpointer user_data)
6543 {
6544         GtkWidget *header_view, *folder_view;
6545         TnyFolderStore *folder_store;
6546         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
6547
6548         /* Set send/receive operation finished */
6549         modest_main_window_notify_send_receive_completed (main_win);
6550
6551         /* Don't refresh the current folder if there were any errors */
6552         if (modest_mail_operation_get_status (mail_op) !=
6553             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
6554                 return;
6555
6556         /* Refresh the current folder if we're viewing a window. We do
6557            this because the user won't be able to see the new mails in
6558            the selected folder after a Send&Receive because it only
6559            performs a poke_status, i.e, only the number of read/unread
6560            messages is updated, but the new headers are not
6561            downloaded */
6562         folder_view = modest_main_window_get_child_widget (main_win,
6563                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6564         if (!folder_view)
6565                 return;
6566
6567         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6568
6569         /* Do not need to refresh INBOX again because the
6570            update_account does it always automatically */
6571         if (folder_store && TNY_IS_FOLDER (folder_store) &&
6572             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
6573                 ModestMailOperation *refresh_op;
6574
6575                 header_view = modest_main_window_get_child_widget (main_win,
6576                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6577
6578                 /* We do not need to set the contents style
6579                    because it hasn't changed. We also do not
6580                    need to save the widget status. Just force
6581                    a refresh */
6582                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
6583                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
6584                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
6585                                                       folder_refreshed_cb, main_win);
6586                 g_object_unref (refresh_op);
6587         }
6588
6589         if (folder_store)
6590                 g_object_unref (folder_store);
6591 }
6592
6593
6594 void
6595 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self,
6596                                                 TnyHeader *header,
6597                                                 TnyMsg *msg,
6598                                                 GError *err,
6599                                                 gpointer user_data)
6600 {
6601         const gchar* server_name = NULL;
6602         TnyTransportAccount *transport;
6603         gchar *message = NULL;
6604         ModestProtocol *protocol;
6605
6606         /* Don't show anything if the user cancelled something or the
6607          * send receive request is not interactive. Authentication
6608          * errors are managed by the account store so no need to show
6609          * a dialog here again */
6610         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
6611             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
6612             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
6613                 return;
6614
6615
6616         /* Get the server name. Note that we could be using a
6617            connection specific transport account */
6618         transport = (TnyTransportAccount *)
6619                 tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self));
6620         if (transport) {
6621                 ModestTnyAccountStore *acc_store;
6622                 const gchar *acc_name;
6623                 TnyTransportAccount *conn_specific;
6624
6625                 acc_store = modest_runtime_get_account_store();
6626                 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT (transport));
6627                 conn_specific = (TnyTransportAccount *)
6628                         modest_tny_account_store_get_transport_account_for_open_connection (acc_store, acc_name);
6629                 if (conn_specific) {
6630                         server_name = tny_account_get_hostname (TNY_ACCOUNT (conn_specific));
6631                         g_object_unref (conn_specific);
6632                 } else {
6633                         server_name = tny_account_get_hostname (TNY_ACCOUNT (transport));
6634                 }
6635                 g_object_unref (transport);
6636         }
6637
6638         /* Get protocol */
6639         protocol = modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
6640                                                                   MODEST_PROTOCOL_REGISTRY_TRANSPORT_STORE_PROTOCOLS,
6641                                                                   tny_account_get_proto (TNY_ACCOUNT (transport)));
6642         if (!protocol) {
6643                 g_warning ("%s: Account with no proto", __FUNCTION__);
6644                 return;
6645         }
6646
6647         /* Show the appropriate message text for the GError: */
6648         switch (err->code) {
6649         case TNY_SERVICE_ERROR_CONNECT:
6650                 message = modest_protocol_get_translation (protocol,
6651                                                            MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR,
6652                                                            server_name);
6653                 break;
6654         case TNY_SERVICE_ERROR_SEND:
6655                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6656                 break;
6657         case TNY_SERVICE_ERROR_UNAVAILABLE:
6658                 message = modest_protocol_get_translation (protocol,
6659                                                            MODEST_PROTOCOL_TRANSLATION_CONNECT_ERROR,
6660                                                            server_name);
6661                 break;
6662         default:
6663                 g_warning ("%s: unexpected ERROR %d",
6664                            __FUNCTION__, err->code);
6665                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6666                 break;
6667         }
6668
6669         modest_platform_run_information_dialog (NULL, message, FALSE);
6670         g_free (message);
6671 }
6672
6673 void
6674 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
6675                                                 gchar *msg_id,
6676                                                 guint status,
6677                                                 gpointer user_data)
6678 {
6679         ModestWindow *top_window = NULL;
6680         ModestWindowMgr *mgr = NULL;
6681         GtkWidget *header_view = NULL;
6682         TnyFolder *selected_folder = NULL;
6683         TnyFolderType folder_type;
6684
6685         mgr = modest_runtime_get_window_mgr ();
6686         top_window = modest_window_mgr_get_current_top (mgr);
6687
6688         if (!top_window)
6689                 return;
6690
6691 #ifndef MODEST_TOOLKIT_HILDON2
6692         if (MODEST_IS_MAIN_WINDOW (top_window)) {
6693                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (top_window),
6694                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6695         }
6696 #else
6697         if (MODEST_IS_HEADER_WINDOW (top_window)) {
6698                 header_view = (GtkWidget *)
6699                         modest_header_window_get_header_view (MODEST_HEADER_WINDOW (top_window));
6700         }
6701 #endif
6702
6703         /* Get selected folder */
6704         if (header_view)
6705                 selected_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
6706         if (!selected_folder)
6707                 return;
6708
6709         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
6710 #if GTK_CHECK_VERSION(2, 8, 0)
6711         folder_type = modest_tny_folder_guess_folder_type (selected_folder);
6712         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {
6713                 GtkTreeViewColumn *tree_column;
6714
6715                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view),
6716                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
6717                 if (tree_column)
6718                         gtk_tree_view_column_queue_resize (tree_column);
6719                 }
6720 #else /* #if GTK_CHECK_VERSION(2, 8, 0) */
6721         gtk_widget_queue_draw (header_view);
6722 #endif
6723
6724 #ifndef MODEST_TOOLKIT_HILDON2
6725         /* Rerun dimming rules, because the message could become deletable for example */
6726         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6727                                                  MODEST_DIMMING_RULES_TOOLBAR);
6728         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
6729                                                  MODEST_DIMMING_RULES_MENU);
6730 #endif
6731
6732         /* Free */
6733         g_object_unref (selected_folder);
6734 }
6735
6736 void
6737 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
6738                                                TnyAccount *account)
6739 {
6740         ModestProtocolType protocol_type;
6741         ModestProtocol *protocol;
6742         gchar *error_note = NULL;
6743
6744         protocol_type = modest_tny_account_get_protocol_type (account);
6745         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6746                                                                   protocol_type);
6747
6748         error_note = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR, tny_account_get_hostname (account));
6749         if (error_note == NULL) {
6750                 g_warning ("%s: This should not be reached", __FUNCTION__);
6751         } else {
6752                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
6753                 g_free (error_note);
6754         }
6755 }
6756
6757 gchar *
6758 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
6759 {
6760         gchar *msg = NULL;
6761         gchar *subject;
6762         TnyFolderStore *folder = NULL;
6763         TnyAccount *account = NULL;
6764         ModestProtocolType proto;
6765         ModestProtocol *protocol;
6766         TnyHeader *header = NULL;
6767
6768         if (MODEST_IS_MAIN_WINDOW (win)) {
6769                 GtkWidget *header_view;
6770                 TnyList* headers = NULL;
6771                 TnyIterator *iter;
6772                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
6773                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
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                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6783                 g_object_unref (iter);
6784                 g_object_unref (headers);
6785 #ifdef MODEST_TOOLKIT_HILDON2
6786         } else if (MODEST_IS_HEADER_WINDOW (win)) {
6787                 GtkWidget *header_view;
6788                 TnyList* headers = NULL;
6789                 TnyIterator *iter;
6790                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
6791                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6792                 if (!headers || tny_list_get_length (headers) == 0) {
6793                         if (headers)
6794                                 g_object_unref (headers);
6795                         return NULL;
6796                 }
6797                 iter = tny_list_create_iterator (headers);
6798                 header = TNY_HEADER (tny_iterator_get_current (iter));
6799                 if (header) {
6800                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6801                 } else {
6802                         g_warning ("List should contain headers");
6803                 }
6804                 g_object_unref (iter);
6805                 g_object_unref (headers);
6806 #endif
6807         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
6808                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
6809                 if (header)
6810                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6811         }
6812
6813         if (!header || !folder)
6814                 goto frees;
6815
6816         /* Get the account type */
6817         account = tny_folder_get_account (TNY_FOLDER (folder));
6818         proto = modest_tny_account_get_protocol_type (account);
6819         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6820                                                                   proto);
6821
6822         subject = tny_header_dup_subject (header);
6823         msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
6824         if (subject)
6825                 g_free (subject);
6826         if (msg == NULL) {
6827                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
6828         }
6829
6830  frees:
6831         /* Frees */
6832         if (account)
6833                 g_object_unref (account);
6834         if (folder)
6835                 g_object_unref (folder);
6836         if (header)
6837                 g_object_unref (header);
6838
6839         return msg;
6840 }
6841
6842 gboolean
6843 modest_ui_actions_on_delete_account (GtkWindow *parent_window,
6844                                      const gchar *account_name,
6845                                      const gchar *account_title)
6846 {
6847         ModestAccountMgr *account_mgr;
6848         gchar *txt = NULL;
6849         gint response;
6850         ModestProtocol *protocol;
6851         gboolean removed = FALSE;
6852
6853         g_return_val_if_fail (account_name, FALSE);
6854         g_return_val_if_fail (account_title, FALSE);
6855
6856         account_mgr = modest_runtime_get_account_mgr();
6857
6858         /* The warning text depends on the account type: */
6859         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6860                                                                   modest_account_mgr_get_store_protocol (account_mgr,
6861                                                                                                          account_name));
6862         txt = modest_protocol_get_translation (protocol,
6863                                                MODEST_PROTOCOL_TRANSLATION_DELETE_MAILBOX,
6864                                                account_title);
6865         if (txt == NULL)
6866                 txt = g_strdup_printf (_("emev_nc_delete_mailbox"), account_title);
6867
6868         response = modest_platform_run_confirmation_dialog (parent_window, txt);
6869         g_free (txt);
6870         txt = NULL;
6871
6872         if (response == GTK_RESPONSE_OK) {
6873                 /* Remove account. If it succeeds then it also removes
6874                    the account from the ModestAccountView: */
6875                 gboolean is_default = FALSE;
6876                 gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr);
6877                 if (default_account_name && (strcmp (default_account_name, account_name) == 0))
6878                         is_default = TRUE;
6879                 g_free (default_account_name);
6880
6881                 removed = modest_account_mgr_remove_account (account_mgr, account_name);
6882                 if (!removed)
6883                         g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__);
6884         }
6885         return removed;
6886 }
6887
6888 static void
6889 on_fetch_images_performer (gboolean canceled,
6890                            GError *err,
6891                            GtkWindow *parent_window,
6892                            TnyAccount *account,
6893                            gpointer user_data)
6894 {
6895         if (err || canceled) {
6896                 /* Show an unable to retrieve images ??? */
6897                 return;
6898         }
6899
6900         /* Note that the user could have closed the window while connecting */
6901         if (GTK_WIDGET_VISIBLE (parent_window))
6902                 modest_msg_view_window_fetch_images ((ModestMsgViewWindow *) parent_window);
6903         g_object_unref ((GObject *) user_data);
6904 }
6905
6906 void
6907 modest_ui_actions_on_fetch_images (GtkAction *action,
6908                                    ModestWindow *window)
6909 {
6910         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
6911
6912         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE, 
6913                                              NULL,
6914                                              on_fetch_images_performer, 
6915                                              g_object_ref (window));
6916 }
6917
6918 void
6919 modest_ui_actions_on_reload_message (const gchar *msg_id)
6920 {
6921         ModestWindow *window = NULL;
6922
6923         g_return_if_fail (msg_id && msg_id[0] != '\0');
6924         if (!modest_window_mgr_find_registered_message_uid (modest_runtime_get_window_mgr (),
6925                                                             msg_id,
6926                                                             &window))
6927                 return;
6928
6929
6930         if (window == NULL || !MODEST_IS_MSG_VIEW_WINDOW (window))
6931                 return;
6932
6933         modest_msg_view_window_reload (MODEST_MSG_VIEW_WINDOW (window));
6934 }