df873ddfc097705018fbc71b1c4eb970787795f5
[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 MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
92
93 typedef struct _GetMsgAsyncHelper {
94         ModestWindow *window;
95         ModestMailOperation *mail_op;
96         TnyIterator *iter;
97         guint num_ops;
98         GFunc func;
99         gpointer user_data;
100 } GetMsgAsyncHelper;
101
102 typedef enum _ReplyForwardAction {
103         ACTION_REPLY,
104         ACTION_REPLY_TO_ALL,
105         ACTION_FORWARD
106 } ReplyForwardAction;
107
108 typedef struct _ReplyForwardHelper {
109         guint reply_forward_type;
110         ReplyForwardAction action;
111         gchar *account_name;
112         gchar *mailbox;
113         GtkWidget *parent_window;
114         TnyHeader *header;
115 } ReplyForwardHelper;
116
117 typedef struct _MoveToHelper {
118         GtkTreeRowReference *reference;
119         GtkWidget *banner;
120 } MoveToHelper;
121
122 typedef struct _PasteAsAttachmentHelper {
123         ModestMsgEditWindow *window;
124         GtkWidget *banner;
125 } PasteAsAttachmentHelper;
126
127 typedef struct {
128         TnyList *list;
129         ModestWindow *win;
130 } MoveToInfo;
131
132 /*
133  * The do_headers_action uses this kind of functions to perform some
134  * action to each member of a list of headers
135  */
136 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
137
138 static void     do_headers_action     (ModestWindow *win,
139                                        HeadersFunc func,
140                                        gpointer user_data);
141
142 static void     open_msg_cb            (ModestMailOperation *mail_op,
143                                         TnyHeader *header,
144                                         gboolean canceled,
145                                         TnyMsg *msg,
146                                         GError *err,
147                                         gpointer user_data);
148
149 static void     reply_forward_cb       (ModestMailOperation *mail_op,
150                                         TnyHeader *header,
151                                         gboolean canceled,
152                                         TnyMsg *msg,
153                                         GError *err,
154                                         gpointer user_data);
155
156 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
157
158 static void     folder_refreshed_cb    (ModestMailOperation *mail_op,
159                                         TnyFolder *folder,
160                                         gpointer user_data);
161
162 static void     on_send_receive_finished (ModestMailOperation  *mail_op,
163                                           gpointer user_data);
164
165 static gint header_list_count_uncached_msgs (TnyList *header_list);
166
167 static gboolean connect_to_get_msg (ModestWindow *win,
168                                     gint num_of_uncached_msgs,
169                                     TnyAccount *account);
170
171 static gboolean remote_folder_has_leave_on_server (TnyFolderStore *folder);
172
173 static void     do_create_folder (GtkWindow *window,
174                                   TnyFolderStore *parent_folder,
175                                   const gchar *suggested_name);
176
177 static TnyAccount *get_account_from_folder_store (TnyFolderStore *folder_store);
178
179 static void modest_ui_actions_on_main_window_move_to (GtkAction *action,
180                                                       GtkWidget *folder_view,
181                                                       TnyFolderStore *dst_folder,
182                                                       ModestMainWindow *win);
183 #ifdef MODEST_TOOLKIT_HILDON2
184 static void modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
185                                                         TnyFolderStore *dst_folder,
186                                                         TnyList *selection,
187                                                         GtkWindow *win);
188 #endif
189
190 static void modest_ui_actions_on_window_move_to (GtkAction *action,
191                                                  TnyList *list_to_move,
192                                                  TnyFolderStore *dst_folder,
193                                                  ModestWindow *win);
194
195 /*
196  * This function checks whether a TnyFolderStore is a pop account
197  */
198 static gboolean
199 remote_folder_has_leave_on_server (TnyFolderStore *folder)
200 {
201         TnyAccount *account;
202         gboolean result;
203
204         g_return_val_if_fail (TNY_IS_FOLDER_STORE (folder), FALSE);
205
206         account = get_account_from_folder_store (folder);
207         result = (modest_protocol_registry_protocol_type_has_leave_on_server (modest_runtime_get_protocol_registry (),
208                                                                               modest_tny_account_get_protocol_type (account)));
209         g_object_unref (account);
210
211         return result;
212 }
213
214 /* FIXME: this should be merged with the similar code in modest-account-view-window */
215 /* Show the account creation wizard dialog.
216  * returns: TRUE if an account was created. FALSE if the user cancelled.
217  */
218 gboolean
219 modest_ui_actions_run_account_setup_wizard (ModestWindow *win)
220 {
221         gboolean result = FALSE;
222         GtkWindow *wizard;
223         gint dialog_response;
224
225         /* there is no such wizard yet */
226         wizard = GTK_WINDOW (modest_platform_get_account_settings_wizard ());
227         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (wizard), (GtkWindow *) win);
228
229 #ifndef MODEST_TOOLKIT_HILDON2
230         /* always present a main window in the background
231          * we do it here, so we cannot end up with two wizards (as this
232          * function might be called in modest_window_mgr_get_main_window as well */
233         if (!win)
234                 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
235                                                          TRUE);  /* create if not existent */
236 #else
237         if (!win) {
238                 GList *window_list;
239                 ModestWindowMgr *mgr;
240
241                 mgr = modest_runtime_get_window_mgr ();
242
243                 window_list = modest_window_mgr_get_window_list (mgr);
244                 if (window_list == NULL) {
245                         win = MODEST_WINDOW (modest_accounts_window_new ());
246                         if (modest_window_mgr_register_window (mgr, win, NULL)) {
247                                 gtk_widget_show_all (GTK_WIDGET (win));
248                         } else {
249                                 gtk_widget_destroy (GTK_WIDGET (win));
250                                 win = NULL;
251                         }
252
253                 } else {
254                         g_list_free (window_list);
255                 }
256         }
257 #endif
258
259         if (win)
260                 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
261
262         /* make sure the mainwindow is visible. We need to present the
263            wizard again to give it the focus back. show_all are needed
264            in order to get the widgets properly drawn (MainWindow main
265            paned won't be in its right position and the dialog will be
266            missplaced */
267 #ifndef MODEST_TOOLKIT_HILDON2
268         gtk_widget_show_all (GTK_WIDGET (win));
269         gtk_widget_show_all (GTK_WIDGET (wizard));
270         gtk_window_present (GTK_WINDOW (win));
271         gtk_window_present (GTK_WINDOW (wizard));
272 #endif
273
274         dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
275         gtk_widget_destroy (GTK_WIDGET (wizard));
276         if (gtk_events_pending ())
277                 gtk_main_iteration ();
278
279         if (dialog_response == GTK_RESPONSE_CANCEL) {
280                 result = FALSE;
281         } else {
282                 /* Check whether an account was created: */
283                 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
284         }
285         return result;
286 }
287
288
289 void
290 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
291 {
292         GtkWidget *about;
293         const gchar *authors[] = {
294                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
295                 NULL
296         };
297         about = gtk_about_dialog_new ();
298         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
299         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
300         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
301                                         _("Copyright (c) 2006, Nokia Corporation\n"
302                                           "All rights reserved."));
303         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
304                                        _("a modest e-mail client\n\n"
305                                          "design and implementation: Dirk-Jan C. Binnema\n"
306                                          "contributions from the fine people at KC and Ig\n"
307                                          "uses the tinymail email framework written by Philip van Hoof"));
308         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
309         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
310         gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
311         gtk_window_set_modal (GTK_WINDOW (about), TRUE);
312
313         gtk_dialog_run (GTK_DIALOG (about));
314         gtk_widget_destroy(about);
315 }
316
317 /*
318  * Gets the list of currently selected messages. If the win is the
319  * main window, then it returns a newly allocated list of the headers
320  * selected in the header view. If win is the msg view window, then
321  * the value returned is a list with just a single header.
322  *
323  * The caller of this funcion must free the list.
324  */
325 static TnyList *
326 get_selected_headers (ModestWindow *win)
327 {
328         if (MODEST_IS_MAIN_WINDOW(win)) {
329                 GtkWidget *header_view;
330
331                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
332                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
333                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
334
335         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
336                 /* for MsgViewWindows, we simply return a list with one element */
337                 TnyHeader *header;
338                 TnyList *list = NULL;
339
340                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
341                 if (header != NULL) {
342                         list = tny_simple_list_new ();
343                         tny_list_prepend (list, G_OBJECT(header));
344                         g_object_unref (G_OBJECT(header));
345                 }
346
347                 return list;
348
349 #ifdef MODEST_TOOLKIT_HILDON2
350         } else if (MODEST_IS_HEADER_WINDOW (win)) {
351                 GtkWidget *header_view;
352
353                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
354                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
355 #endif
356         } else
357                 return NULL;
358 }
359
360 static GtkTreeRowReference *
361 get_next_after_selected_headers (ModestHeaderView *header_view)
362 {
363         GtkTreeSelection *sel;
364         GList *selected_rows, *node;
365         GtkTreePath *path;
366         GtkTreeRowReference *result;
367         GtkTreeModel *model;
368
369         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
370         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
371         selected_rows = gtk_tree_selection_get_selected_rows (sel, NULL);
372
373         if (selected_rows == NULL)
374                 return NULL;
375
376         node = g_list_last (selected_rows);
377         path = gtk_tree_path_copy ((GtkTreePath *) node->data);
378         gtk_tree_path_next (path);
379
380         result = gtk_tree_row_reference_new (model, path);
381
382         gtk_tree_path_free (path);
383         g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
384         g_list_free (selected_rows);
385
386         return result;
387 }
388
389 static void
390 headers_action_mark_as_read (TnyHeader *header,
391                              ModestWindow *win,
392                              gpointer user_data)
393 {
394         TnyHeaderFlags flags;
395
396         g_return_if_fail (TNY_IS_HEADER(header));
397
398         flags = tny_header_get_flags (header);
399         if (flags & TNY_HEADER_FLAG_SEEN) return;
400         tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
401 }
402
403 static void
404 headers_action_mark_as_unread (TnyHeader *header,
405                                ModestWindow *win,
406                                gpointer user_data)
407 {
408         TnyHeaderFlags flags;
409
410         g_return_if_fail (TNY_IS_HEADER(header));
411
412         flags = tny_header_get_flags (header);
413         if (flags & TNY_HEADER_FLAG_SEEN)  {
414                 tny_header_unset_flag (header, TNY_HEADER_FLAG_SEEN);
415         }
416 }
417
418 /** After deleing a message that is currently visible in a window,
419  * show the next message from the list, or close the window if there are no more messages.
420  **/
421 void
422 modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
423 {
424         /* Close msg view window or select next */
425         if (!modest_msg_view_window_select_next_message (win) &&
426             !modest_msg_view_window_select_previous_message (win)) {
427                 gboolean ret_value;
428                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
429         }
430 }
431
432
433 void
434 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
435 {
436         modest_ui_actions_on_edit_mode_delete_message (win);
437 }
438
439 gboolean
440 modest_ui_actions_on_edit_mode_delete_message (ModestWindow *win)
441 {
442         TnyList *header_list = NULL;
443         TnyIterator *iter = NULL;
444         TnyHeader *header = NULL;
445         gchar *message = NULL;
446         gchar *desc = NULL;
447         gint response;
448         ModestWindowMgr *mgr;
449         GtkWidget *header_view = NULL;
450         gboolean retval = TRUE;
451
452         g_return_val_if_fail (MODEST_IS_WINDOW(win), FALSE);
453
454         /* Check first if the header view has the focus */
455         if (MODEST_IS_MAIN_WINDOW (win)) {
456                 header_view =
457                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
458                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
459                 if (!gtk_widget_is_focus (header_view))
460                         return FALSE;
461         }
462
463         /* Get the headers, either from the header view (if win is the main window),
464          * or from the message view window: */
465         header_list = get_selected_headers (win);
466         if (!header_list) return FALSE;
467
468         /* Check if any of the headers are already opened, or in the process of being opened */
469         if (MODEST_IS_MAIN_WINDOW (win)) {
470                 gint opened_headers = 0;
471
472                 iter = tny_list_create_iterator (header_list);
473                 mgr = modest_runtime_get_window_mgr ();
474                 while (!tny_iterator_is_done (iter)) {
475                         header = TNY_HEADER (tny_iterator_get_current (iter));
476                         if (header) {
477                                 if (modest_window_mgr_find_registered_header (mgr, header, NULL))
478                                         opened_headers++;
479                                 g_object_unref (header);
480                         }
481                         tny_iterator_next (iter);
482                 }
483                 g_object_unref (iter);
484
485                 if (opened_headers > 0) {
486                         gchar *msg;
487
488                         msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"),
489                                                opened_headers);
490
491                         modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg, FALSE);
492
493                         g_free (msg);
494                         g_object_unref (header_list);
495                         return FALSE;
496                 }
497         }
498
499         /* Select message */
500         if (tny_list_get_length(header_list) == 1) {
501                 iter = tny_list_create_iterator (header_list);
502                 header = TNY_HEADER (tny_iterator_get_current (iter));
503                 if (header) {
504                         gchar *subject;
505                         subject = tny_header_dup_subject (header);
506                         if (!subject)
507                                 subject = g_strdup (_("mail_va_no_subject"));
508                         desc = g_strdup_printf ("%s", subject);
509                         g_free (subject);
510                         g_object_unref (header);
511                 }
512
513                 g_object_unref (iter);
514         }
515         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages",
516                                            tny_list_get_length(header_list)), desc);
517
518         /* Confirmation dialog */
519         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
520                                                             message);
521
522
523         if (response == GTK_RESPONSE_OK) {
524                 ModestWindow *main_window = NULL;
525                 ModestWindowMgr *mgr = NULL;
526                 GtkTreeModel *model = NULL;
527                 GtkTreeSelection *sel = NULL;
528                 GList *sel_list = NULL, *tmp = NULL;
529                 GtkTreeRowReference *next_row_reference = NULL;
530                 GtkTreeRowReference *prev_row_reference = NULL;
531                 GtkTreePath *next_path = NULL;
532                 GtkTreePath *prev_path = NULL;
533                 ModestMailOperation *mail_op = NULL;
534
535                 /* Find last selected row */
536                 if (MODEST_IS_MAIN_WINDOW (win)) {
537                         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
538                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
539                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
540                         for (tmp=sel_list; tmp; tmp=tmp->next) {
541                                 if (tmp->next == NULL) {
542                                         prev_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
543                                         next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
544
545                                         gtk_tree_path_prev (prev_path);
546                                         gtk_tree_path_next (next_path);
547
548                                         prev_row_reference = gtk_tree_row_reference_new (model, prev_path);
549                                         next_row_reference = gtk_tree_row_reference_new (model, next_path);
550                                 }
551                         }
552                 }
553
554                 /* Disable window dimming management */
555                 modest_window_disable_dimming (MODEST_WINDOW(win));
556
557                 /* Remove each header. If it's a view window header_view == NULL */
558                 mail_op = modest_mail_operation_new ((GObject *) win);
559                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
560                                                  mail_op);
561                 modest_mail_operation_remove_msgs (mail_op, header_list, FALSE);
562                 g_object_unref (mail_op);
563
564                 /* Enable window dimming management */
565                 if (sel != NULL) {
566                         gtk_tree_selection_unselect_all (sel);
567                 }
568                 modest_window_enable_dimming (MODEST_WINDOW(win));
569
570                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
571                         modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
572
573                         /* Get main window */
574                         mgr = modest_runtime_get_window_mgr ();
575                         main_window = modest_window_mgr_get_main_window (mgr, FALSE); /* don't create */
576                 } else if (MODEST_IS_MAIN_WINDOW (win)) {
577                         /* Move cursor to next row */
578                         main_window = win;
579
580                         /* Select next or previous row */
581                         if (gtk_tree_row_reference_valid (next_row_reference)) {
582                                 gtk_tree_selection_select_path (sel, next_path);
583                         }
584                         else if (gtk_tree_row_reference_valid (prev_row_reference)) {
585                                 gtk_tree_selection_select_path (sel, prev_path);
586                         }
587
588                         /* Free */
589                         if (gtk_tree_row_reference_valid (next_row_reference))
590                                 gtk_tree_row_reference_free (next_row_reference);
591                         if (next_path != NULL)
592                                 gtk_tree_path_free (next_path);
593                         if (gtk_tree_row_reference_valid (prev_row_reference))
594                                 gtk_tree_row_reference_free (prev_row_reference);
595                         if (prev_path != NULL)
596                                 gtk_tree_path_free (prev_path);
597                 }
598
599                 /* Update toolbar dimming state */
600                 if (main_window) {
601                         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
602                         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
603                 }
604
605                 /* Free */
606                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
607                 g_list_free (sel_list);
608                 retval = TRUE;
609         } else {
610                 retval = FALSE;
611         }
612
613         /* Free*/
614         g_free(message);
615         g_free(desc);
616         g_object_unref (header_list);
617
618         return retval;
619 }
620
621
622
623
624 /* delete either message or folder, based on where we are */
625 void
626 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
627 {
628         g_return_if_fail (MODEST_IS_WINDOW(win));
629
630         /* Check first if the header view has the focus */
631         if (MODEST_IS_MAIN_WINDOW (win)) {
632                 GtkWidget *w;
633                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
634                                                          MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
635                 if (gtk_widget_is_focus (w)) {
636                         modest_ui_actions_on_delete_folder (action, MODEST_WINDOW(win));
637                         return;
638                 }
639         }
640         modest_ui_actions_on_delete_message (action, win);
641 }
642
643 void
644 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
645 {
646         ModestWindowMgr *mgr = NULL;
647
648 #ifdef MODEST_PLATFORM_MAEMO
649         modest_osso_save_state();
650 #endif /* MODEST_PLATFORM_MAEMO */
651
652         g_debug ("closing down, clearing %d item(s) from operation queue",
653                  modest_mail_operation_queue_num_elements
654                  (modest_runtime_get_mail_operation_queue()));
655
656         /* cancel all outstanding operations */
657         modest_mail_operation_queue_cancel_all
658                 (modest_runtime_get_mail_operation_queue());
659
660         g_debug ("queue has been cleared");
661
662
663         /* Check if there are opened editing windows */
664         mgr = modest_runtime_get_window_mgr ();
665         modest_window_mgr_close_all_windows (mgr);
666
667         /* note: when modest-tny-account-store is finalized,
668            it will automatically set all network connections
669            to offline */
670
671 /*      gtk_main_quit (); */
672 }
673
674 void
675 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
676 {
677         gboolean ret_value;
678
679         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
680
681 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
682 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
683 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
684 /*              gboolean ret_value; */
685 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
686 /*      } else if (MODEST_IS_WINDOW (win)) { */
687 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
688 /*      } else { */
689 /*              g_return_if_reached (); */
690 /*      } */
691 }
692
693 void
694 modest_ui_actions_add_to_contacts (GtkAction *action, ModestWindow *win)
695 {
696        g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (win));
697
698        modest_msg_view_window_add_to_contacts (MODEST_MSG_VIEW_WINDOW (win));
699 }
700
701 void
702 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
703 {
704         GtkClipboard *clipboard = NULL;
705         gchar *selection = NULL;
706
707         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
708         selection = gtk_clipboard_wait_for_text (clipboard);
709
710         /* Question: why is the clipboard being used here?
711          * It doesn't really make a lot of sense. */
712
713         if (selection)
714         {
715                 modest_address_book_add_address (selection);
716                 g_free (selection);
717         }
718 }
719
720 void
721 modest_ui_actions_on_new_account (GtkAction *action,
722                                   ModestWindow *window)
723 {
724         if (!modest_ui_actions_run_account_setup_wizard (window)) {
725                 g_debug ("%s: wizard was already running", __FUNCTION__);
726         }
727 }
728
729 void
730 modest_ui_actions_on_accounts (GtkAction *action,
731                                ModestWindow *win)
732 {
733         /* This is currently only implemented for Maemo */
734         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
735                 if (!modest_ui_actions_run_account_setup_wizard (win))
736                         g_debug ("%s: wizard was already running", __FUNCTION__);
737
738                 return;
739         } else {
740                 /* Show the list of accounts */
741                 GtkWindow *account_win = GTK_WINDOW (modest_account_view_window_new ());
742
743                 /* The accounts dialog must be modal */
744                 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (account_win), (GtkWindow *) win);
745                 modest_utils_show_dialog_and_forget (GTK_WINDOW (win), GTK_DIALOG (account_win));
746         }
747 }
748
749 void
750 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
751 {
752         /* This is currently only implemented for Maemo,
753          * because it requires an API (libconic) to detect different connection
754          * possiblities.
755          */
756 #ifndef MODEST_TOOLKIT_GTK /* Defined in config.h */
757
758         /* Create the window if necessary: */
759         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
760         modest_connection_specific_smtp_window_fill_with_connections (
761                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window),
762                 modest_runtime_get_account_mgr());
763
764         /* Show the window: */
765         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
766                                      GTK_WINDOW (specific_window), (GtkWindow *) win);
767         gtk_widget_show (specific_window);
768 #endif /* !MODEST_TOOLKIT_GTK */
769 }
770
771 static guint64
772 count_part_size (const gchar *part)
773 {
774         GnomeVFSURI *vfs_uri;
775         gchar *escaped_filename;
776         gchar *filename;
777         GnomeVFSFileInfo *info;
778         guint64 result;
779
780         /* Estimation of attachment size if we cannot get it from file info */
781         result = 32768;
782
783         vfs_uri = gnome_vfs_uri_new (part);
784
785         escaped_filename = g_path_get_basename (gnome_vfs_uri_get_path (vfs_uri));
786         filename = gnome_vfs_unescape_string_for_display (escaped_filename);
787         g_free (escaped_filename);
788         gnome_vfs_uri_unref (vfs_uri);
789
790         info = gnome_vfs_file_info_new ();
791         
792         if (gnome_vfs_get_file_info (part, 
793                                      info, 
794                                      GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
795             == GNOME_VFS_OK) {
796                 if (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
797                         result = info->size;
798                 }
799         }
800         g_free (filename);
801         gnome_vfs_file_info_unref (info);
802
803         return result;
804 }
805
806 static guint64 
807 count_parts_size (GSList *parts)
808 {
809         GSList *node;
810         guint64 result = 0;
811
812         for (node = parts; node != NULL; node = g_slist_next (node)) {
813                 result += count_part_size ((const gchar *) node->data);
814         }
815
816         return result;
817 }
818
819 void
820 modest_ui_actions_compose_msg(ModestWindow *win,
821                               const gchar *to_str,
822                               const gchar *cc_str,
823                               const gchar *bcc_str,
824                               const gchar *subject_str,
825                               const gchar *body_str,
826                               GSList *attachments,
827                               gboolean set_as_modified)
828 {
829         gchar *account_name = NULL;
830         const gchar *mailbox;
831         TnyMsg *msg = NULL;
832         TnyAccount *account = NULL;
833         TnyFolder *folder = NULL;
834         gchar *from_str = NULL, *signature = NULL, *body = NULL;
835         gchar *recipient = NULL;
836         gboolean use_signature = FALSE;
837         ModestWindow *msg_win = NULL;
838         ModestAccountMgr *mgr = modest_runtime_get_account_mgr();
839         ModestTnyAccountStore *store = modest_runtime_get_account_store();
840         GnomeVFSFileSize total_size, allowed_size;
841         guint64 available_disk, expected_size, parts_size;
842         guint parts_count;
843
844         /* we check for low-mem */
845         if (modest_platform_check_memory_low (win, TRUE))
846                 goto cleanup;
847
848         available_disk = modest_utils_get_available_space (NULL);
849         parts_count = g_slist_length (attachments);
850         parts_size = count_parts_size (attachments);
851         expected_size = modest_tny_msg_estimate_size (body, NULL, parts_count, parts_size);
852
853         /* Double check: disk full condition or message too big */
854         if (available_disk < MODEST_TNY_ACCOUNT_STORE_MIN_FREE_SPACE ||
855             expected_size > available_disk) {
856                 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
857                 modest_platform_system_banner (NULL, NULL, msg);
858                 g_free (msg);
859
860                 return;
861         }
862
863         if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
864                 modest_platform_run_information_dialog (
865                         GTK_WINDOW(win),
866                         _FM("sfil_ib_opening_not_allowed"),
867                         TRUE);
868                 return;
869         }
870
871
872 #ifdef MODEST_TOOLKIT_HILDON2
873         if (win)
874                 account_name = g_strdup (modest_window_get_active_account(win));
875 #endif
876         if (!account_name) {
877                 account_name = modest_account_mgr_get_default_account(mgr);
878         }
879         if (!account_name) {
880                 g_printerr ("modest: no account found\n");
881                 goto cleanup;
882         }
883
884         if (win)
885                 mailbox = modest_window_get_active_mailbox (win);
886         else
887                 mailbox = NULL;
888         account = modest_tny_account_store_get_server_account (store, account_name, TNY_ACCOUNT_TYPE_STORE);
889         if (!account) {
890                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
891                 goto cleanup;
892         }
893         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
894         if (!folder) {
895                 g_printerr ("modest: failed to find Drafts folder\n");
896                 goto cleanup;
897         }
898         from_str = modest_account_mgr_get_from_string (mgr, account_name, mailbox);
899         if (!from_str) {
900                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
901                 goto cleanup;
902         }
903
904         recipient = modest_text_utils_get_email_address (from_str);
905         signature = modest_account_mgr_get_signature_from_recipient (mgr, recipient, &use_signature);
906         g_free (recipient);
907         if (body_str != NULL) {
908                 body = use_signature ? g_strconcat(body_str, "\n--\n", signature, NULL) : g_strdup(body_str);
909         } else {
910                 body = use_signature ? g_strconcat("\n--\n", signature, NULL) : g_strdup("");
911         }
912
913         msg = modest_tny_msg_new (to_str, from_str, cc_str, bcc_str, subject_str, NULL, NULL, body, NULL, NULL, NULL);
914         if (!msg) {
915                 g_printerr ("modest: failed to create new msg\n");
916                 goto cleanup;
917         }
918
919         /* Create and register edit window */
920         /* This is destroyed by TODO. */
921         total_size = 0;
922         allowed_size = MODEST_MAX_ATTACHMENT_SIZE;
923         msg_win = modest_msg_edit_window_new (msg, account_name, mailbox, FALSE);
924
925         if (!modest_window_mgr_register_window (modest_runtime_get_window_mgr(), msg_win, win)) {
926                 gtk_widget_destroy (GTK_WIDGET (msg_win));
927                 goto cleanup;
928         }
929         modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (msg_win), set_as_modified);
930         gtk_widget_show_all (GTK_WIDGET (msg_win));
931
932         while (attachments) {
933                 GnomeVFSFileSize att_size;
934                 att_size =
935                         modest_msg_edit_window_attach_file_one((ModestMsgEditWindow *)msg_win,
936                                                                attachments->data, allowed_size);
937                 total_size += att_size;
938
939                 if (att_size > allowed_size) {
940                         g_debug ("%s: total size: %u",
941                                  __FUNCTION__, (unsigned int)total_size);
942                         break;
943                 }
944                 allowed_size -= att_size;
945
946                 attachments = g_slist_next(attachments);
947         }
948
949 cleanup:
950         g_free (from_str);
951         g_free (signature);
952         g_free (body);
953         g_free (account_name);
954         if (account)
955                 g_object_unref (G_OBJECT(account));
956         if (folder)
957                 g_object_unref (G_OBJECT(folder));
958         if (msg)
959                 g_object_unref (G_OBJECT(msg));
960 }
961
962 void
963 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
964 {
965         /* if there are no accounts yet, just show the wizard */
966         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE))
967                 if (!modest_ui_actions_run_account_setup_wizard (win))
968                         return;
969
970         modest_ui_actions_compose_msg(win, NULL, NULL, NULL, NULL, NULL, NULL, FALSE);
971 }
972
973
974 gboolean
975 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
976                                        TnyHeader *header,
977                                        TnyMsg *msg)
978 {
979         ModestMailOperationStatus status;
980
981         /* If there is no message or the operation was not successful */
982         status = modest_mail_operation_get_status (mail_op);
983         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
984                 const GError *error;
985
986                 /* If it's a memory low issue, then show a banner */
987                 error = modest_mail_operation_get_error (mail_op);
988                 if (error && error->domain == MODEST_MAIL_OPERATION_ERROR &&
989                     error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
990                         GObject *source = modest_mail_operation_get_source (mail_op);
991                         modest_platform_run_information_dialog (GTK_IS_WINDOW (source) ? GTK_WINDOW (source) : NULL,
992                                                                 _KR("memr_ib_operation_disabled"),
993                                                                 TRUE);
994                         g_object_unref (source);
995                 }
996
997                 if (error && ((error->code == TNY_SERVICE_ERROR_NO_SUCH_MESSAGE) ||
998                               error->code == TNY_SERVICE_ERROR_MESSAGE_NOT_AVAILABLE)) {
999                         gchar *subject, *msg, *format = NULL;
1000                         TnyAccount *account;
1001                         subject = tny_header_dup_subject (header);
1002                         if (!subject)
1003                                 subject = g_strdup (_("mail_va_no_subject"));
1004
1005                         account = modest_mail_operation_get_account (mail_op);
1006                         if (account) {
1007                                 ModestProtocol *protocol;
1008                                 ModestProtocolType proto;
1009                                 proto = modest_tny_account_get_protocol_type (account);
1010                                 protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (), proto);
1011                                 if (protocol)
1012                                   format = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
1013                                 g_object_unref (account);
1014                         }
1015
1016                         if (!format)
1017                                 format = g_strdup (_("emev_ni_ui_imap_message_not_available_in_server"));
1018
1019                         msg = g_strdup_printf (format, subject);
1020                         modest_platform_run_information_dialog (NULL, msg, FALSE);
1021                         g_free (msg);
1022                         g_free (format);
1023                         g_free (subject);
1024                 }
1025
1026                 /* Remove the header from the preregistered uids */
1027                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1028                                                      header);
1029
1030                 return FALSE;
1031         }
1032
1033         return TRUE;
1034 }
1035
1036 typedef struct {
1037         guint idle_handler;
1038         gchar *message;
1039         GtkWidget *banner;
1040 } OpenMsgBannerInfo;
1041
1042 typedef struct {
1043         GtkTreeModel *model;
1044         TnyHeader *header;
1045         OpenMsgBannerInfo *banner_info;
1046         GtkTreeRowReference *rowref;
1047 } OpenMsgHelper;
1048
1049 gboolean
1050 open_msg_banner_idle (gpointer userdata)
1051 {
1052         OpenMsgBannerInfo *banner_info = (OpenMsgBannerInfo *) userdata;
1053
1054         gdk_threads_enter ();
1055         banner_info->idle_handler = 0;
1056         banner_info->banner = modest_platform_animation_banner (NULL, NULL, banner_info->message);
1057         if (banner_info->banner)
1058                 g_object_ref (banner_info->banner);
1059
1060         gdk_threads_leave ();
1061
1062         return FALSE;
1063 }
1064
1065 static GtkWidget *
1066 get_header_view_from_window (ModestWindow *window)
1067 {
1068         GtkWidget *header_view;
1069
1070         if (MODEST_IS_MAIN_WINDOW (window)) {
1071                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
1072                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1073 #ifdef MODEST_TOOLKIT_HILDON2
1074         } else if (MODEST_IS_HEADER_WINDOW (window)){
1075                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window)));
1076 #endif
1077         } else {
1078                 header_view = NULL;
1079         }
1080
1081         return header_view;
1082 }
1083
1084 static gchar *
1085 get_info_from_header (TnyHeader *header, gboolean *is_draft, gboolean *can_open)
1086 {
1087         TnyFolder *folder;
1088         gchar *account = NULL;
1089         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
1090
1091         *is_draft = FALSE;
1092         *can_open = TRUE;
1093
1094         folder = tny_header_get_folder (header);
1095         /* Gets folder type (OUTBOX headers will be opened in edit window */
1096         if (modest_tny_folder_is_local_folder (folder)) {
1097                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1098                 if (folder_type == TNY_FOLDER_TYPE_INVALID)
1099                         g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
1100         }
1101
1102         if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
1103                 TnyTransportAccount *traccount = NULL;
1104                 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
1105                 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
1106                 if (traccount) {
1107                         ModestTnySendQueue *send_queue = NULL;
1108                         ModestTnySendQueueStatus status;
1109                         gchar *msg_id;
1110                         account = g_strdup(modest_tny_account_get_parent_modest_account_name_for_server_account(
1111                                                    TNY_ACCOUNT(traccount)));
1112                         send_queue = modest_runtime_get_send_queue(traccount, TRUE);
1113                         if (TNY_IS_SEND_QUEUE (send_queue)) {
1114                                 msg_id = modest_tny_send_queue_get_msg_id (header);
1115                                 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
1116                                 g_free (msg_id);
1117                                 /* Only open messages in outbox with the editor if they are in Failed state */
1118                                 if (status == MODEST_TNY_SEND_QUEUE_FAILED) {
1119                                         *is_draft = TRUE;
1120                                 }
1121 #ifdef MODEST_TOOLKIT_HILDON2
1122                                 else {
1123                                         /* In Fremantle we can not
1124                                            open any message from
1125                                            outbox which is not in
1126                                            failed state */
1127                                         *can_open = FALSE;
1128                                 }
1129 #endif
1130                         }
1131                         g_object_unref(traccount);
1132                 } else {
1133                         g_warning("Cannot get transport account for message in outbox!!");
1134                 }
1135         } else if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
1136                 *is_draft = TRUE; /* Open in editor if the message is in the Drafts folder */
1137         }
1138
1139         if (!account) {
1140                 TnyAccount *acc = tny_folder_get_account (folder);
1141                 if (acc) {
1142                         account =
1143                                 g_strdup (modest_tny_account_get_parent_modest_account_name_for_server_account (acc));
1144                         g_object_unref (acc);
1145                 }
1146         }
1147
1148         g_object_unref (folder);
1149
1150         return account;
1151 }
1152
1153 static void
1154 open_msg_cb (ModestMailOperation *mail_op,
1155              TnyHeader *header,
1156              gboolean canceled,
1157              TnyMsg *msg,
1158              GError *err,
1159              gpointer user_data)
1160 {
1161         ModestWindowMgr *mgr = NULL;
1162         ModestWindow *parent_win = NULL;
1163         ModestWindow *win = NULL;
1164         gchar *account = NULL;
1165         gboolean open_in_editor = FALSE;
1166         gboolean can_open;
1167         OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
1168
1169         /* Do nothing if there was any problem with the mail
1170            operation. The error will be shown by the error_handler of
1171            the mail operation */
1172         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1173                 return;
1174
1175         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
1176
1177         /* Mark header as read */
1178         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
1179
1180         account = get_info_from_header (header, &open_in_editor, &can_open);
1181
1182         /* Get account */
1183         if (!account)
1184                 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
1185         if (!account)
1186                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1187
1188         if (open_in_editor) {
1189                 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
1190                 gchar *from_header = NULL, *acc_name;
1191                 gchar *mailbox = NULL;
1192
1193                 from_header = tny_header_dup_from (header);
1194
1195                 /* we cannot edit without a valid account... */
1196                 if (!modest_account_mgr_has_accounts(mgr, TRUE)) {
1197                         if (!modest_ui_actions_run_account_setup_wizard(parent_win)) {
1198                                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1199                                                                      header);
1200                                 g_free (from_header);
1201                                 goto cleanup;
1202                         }
1203                 }
1204
1205                 acc_name = modest_utils_get_account_name_from_recipient (from_header, &mailbox);
1206                 g_free (from_header);
1207                 if (acc_name) {
1208                         g_free (account);
1209                         account = acc_name;
1210                 }
1211
1212                 win = modest_msg_edit_window_new (msg, account, mailbox, TRUE);
1213                 if (mailbox)
1214                         g_free (mailbox);
1215         } else {
1216                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
1217                 const gchar *mailbox = NULL;
1218
1219                 if (parent_win && MODEST_IS_WINDOW (parent_win))
1220                         mailbox = modest_window_get_active_mailbox (MODEST_WINDOW (parent_win));
1221
1222                 if (helper->rowref && helper->model) {
1223                         win = modest_msg_view_window_new_with_header_model (msg, account, mailbox, (const gchar*) uid,
1224                                                                             helper->model, helper->rowref);
1225                 } else {
1226                         win = modest_msg_view_window_new_for_attachment (msg, account, mailbox, (const gchar*) uid);
1227                 }
1228                 g_free (uid);
1229         }
1230
1231         /* Register and show new window */
1232         if (win != NULL) {
1233                 mgr = modest_runtime_get_window_mgr ();
1234                 if (!modest_window_mgr_register_window (mgr, win, NULL)) {
1235                         gtk_widget_destroy (GTK_WIDGET (win));
1236                         goto cleanup;
1237                 }
1238                 gtk_widget_show_all (GTK_WIDGET(win));
1239         }
1240
1241         /* Update toolbar dimming state */
1242         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
1243                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
1244         }
1245
1246 cleanup:
1247         /* Free */
1248         g_free(account);
1249         g_object_unref (parent_win);
1250 }
1251
1252 void
1253 modest_ui_actions_disk_operations_error_handler (ModestMailOperation *mail_op,
1254                                                  gpointer user_data)
1255 {
1256         const GError *error;
1257         GObject *win = NULL;
1258         ModestMailOperationStatus status;
1259
1260         win = modest_mail_operation_get_source (mail_op);
1261         error = modest_mail_operation_get_error (mail_op);
1262         status = modest_mail_operation_get_status (mail_op);
1263
1264         /* If the mail op has been cancelled then it's not an error:
1265            don't show any message */
1266         if (status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
1267                 TnyAccount *account = modest_mail_operation_get_account (mail_op);
1268                 if (modest_tny_account_store_is_disk_full_error (modest_runtime_get_account_store(),
1269                                                                  (GError *) error, account)) {
1270                         gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
1271                         modest_platform_information_banner ((GtkWidget *) win, NULL, msg);
1272                         g_free (msg);
1273                 } else if (error->code == TNY_SYSTEM_ERROR_MEMORY) {
1274                         modest_platform_information_banner ((GtkWidget *) win,
1275                                                             NULL, _("emev_ui_imap_inbox_select_error"));
1276                 } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
1277                            error->code == MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
1278                         modest_platform_information_banner ((GtkWidget *) win,
1279                                                             NULL, _CS ("sfil_ni_unable_to_open_file_not_found"));
1280                 } else if (user_data) {
1281                         modest_platform_information_banner ((GtkWidget *) win,
1282                                                             NULL, user_data);
1283                 }
1284                 if (account)
1285                         g_object_unref (account);
1286         }
1287
1288         if (win)
1289                 g_object_unref (win);
1290 }
1291
1292 /**
1293  * Returns the account a list of headers belongs to. It returns a
1294  * *new* reference so don't forget to unref it
1295  */
1296 static TnyAccount*
1297 get_account_from_header_list (TnyList *headers)
1298 {
1299         TnyAccount *account = NULL;
1300
1301         if (tny_list_get_length (headers) > 0) {
1302                 TnyIterator *iter = tny_list_create_iterator (headers);
1303                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1304                 TnyFolder *folder = tny_header_get_folder (header);
1305
1306                 if (!folder) {
1307                         g_object_unref (header);
1308
1309                         while (!tny_iterator_is_done (iter)) {
1310                                 header = TNY_HEADER (tny_iterator_get_current (iter));
1311                                 folder = tny_header_get_folder (header);
1312                                 if (folder)
1313                                         break;
1314                                 g_object_unref (header);
1315                                 header = NULL;
1316                                 tny_iterator_next (iter);
1317                         }
1318                 }
1319
1320                 if (folder) {
1321                         account = tny_folder_get_account (folder);
1322                         g_object_unref (folder);
1323                 }
1324
1325                 if (header)
1326                         g_object_unref (header);
1327
1328                 g_object_unref (iter);
1329         }
1330         return account;
1331 }
1332
1333 static TnyAccount*
1334 get_account_from_header (TnyHeader *header)
1335 {
1336         TnyAccount *account = NULL;
1337         TnyFolder *folder;
1338
1339         folder = tny_header_get_folder (header);
1340
1341         if (folder) {
1342                 account = tny_folder_get_account (folder);
1343                 g_object_unref (folder);
1344         }
1345         return account;
1346 }
1347
1348 static void
1349 open_msg_helper_destroyer (gpointer user_data)
1350 {
1351         OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
1352
1353         if (helper->banner_info) {
1354                 g_free (helper->banner_info->message);
1355                 if (helper->banner_info->idle_handler > 0) {
1356                         g_source_remove (helper->banner_info->idle_handler);
1357                         helper->banner_info->idle_handler = 0;
1358                 }
1359                 if (helper->banner_info->banner != NULL) {
1360                         gtk_widget_destroy (helper->banner_info->banner);
1361                         g_object_unref (helper->banner_info->banner);
1362                         helper->banner_info->banner = NULL;
1363                 }
1364                 g_slice_free (OpenMsgBannerInfo, helper->banner_info);
1365                 helper->banner_info = NULL;
1366         }
1367         g_object_unref (helper->model);
1368         g_object_unref (helper->header);
1369         gtk_tree_row_reference_free (helper->rowref);
1370         g_slice_free (OpenMsgHelper, helper);
1371 }
1372
1373 static void
1374 open_msg_performer(gboolean canceled,
1375                     GError *err,
1376                     GtkWindow *parent_window,
1377                     TnyAccount *account,
1378                     gpointer user_data)
1379 {
1380         ModestMailOperation *mail_op = NULL;
1381         gchar *error_msg = NULL;
1382         ModestProtocolType proto;
1383         TnyConnectionStatus status;
1384         OpenMsgHelper *helper = NULL;
1385         ModestProtocol *protocol;
1386         ModestProtocolRegistry *protocol_registry;
1387         gchar *subject;
1388
1389         helper = (OpenMsgHelper *) user_data;
1390
1391         status = tny_account_get_connection_status (account);
1392         if (err || canceled) {
1393                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (), helper->header);
1394                 /* Free the helper */
1395                 open_msg_helper_destroyer (helper);
1396
1397                 /* In disk full conditions we could get this error here */
1398                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
1399                                                                 (GtkWidget *) parent_window, err,
1400                                                                 account, NULL);
1401
1402                 goto clean;
1403         }
1404
1405         /* Get the error message depending on the protocol */
1406         proto = modest_tny_account_get_protocol_type (account);
1407         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
1408                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
1409         }
1410
1411         protocol_registry = modest_runtime_get_protocol_registry ();
1412         subject = tny_header_dup_subject (helper->header);
1413
1414         protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, proto);
1415         error_msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
1416         if (subject)
1417                 g_free (subject);
1418
1419         if (error_msg == NULL) {
1420                 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1421         }
1422
1423 #ifndef MODEST_TOOLKIT_HILDON2
1424         gboolean show_open_draft = FALSE;
1425         if (modest_protocol_registry_protocol_type_has_tag (protocol_registry,
1426                                                             proto,
1427                                                             MODEST_PROTOCOL_REGISTRY_LOCAL_STORE_PROTOCOLS)) {
1428                 TnyFolder *folder;
1429                 TnyFolderType folder_type;
1430
1431                 folder = tny_header_get_folder (helper->header);
1432                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1433                 show_open_draft = (folder_type == TNY_FOLDER_TYPE_DRAFTS);
1434                 g_object_unref (folder);
1435         }
1436 #endif
1437
1438 #ifdef MODEST_TOOLKIT_HILDON2
1439         gboolean is_draft;
1440         gboolean can_open;
1441         gchar *account_name = get_info_from_header (helper->header, &is_draft, &can_open);
1442
1443         if (!can_open) {
1444                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (), helper->header);
1445                 g_free (account_name);
1446                 open_msg_helper_destroyer (helper);
1447                 goto clean;
1448         }
1449
1450         if (!is_draft) {
1451                 ModestWindow *window;
1452                 GtkWidget *header_view;
1453                 gchar *uid;
1454
1455                 header_view = get_header_view_from_window (MODEST_WINDOW (parent_window));
1456                 uid = modest_tny_folder_get_header_unique_id (helper->header);
1457                 if (header_view) {
1458                         const gchar *mailbox = NULL;
1459                         mailbox = modest_window_get_active_mailbox (MODEST_WINDOW (parent_window));
1460                         window = modest_msg_view_window_new_from_header_view 
1461                                 (MODEST_HEADER_VIEW (header_view), account_name, mailbox, uid, helper->rowref);
1462                         if (window != NULL) {
1463                                 if (!modest_window_mgr_register_window (modest_runtime_get_window_mgr (),
1464                                                                         window, NULL)) {
1465                                         gtk_widget_destroy (GTK_WIDGET (window));
1466                                 } else {
1467                                         gtk_widget_show_all (GTK_WIDGET(window));
1468                                 }
1469                         }
1470                 }
1471                 g_free (account_name);
1472                 g_free (uid);
1473                 open_msg_helper_destroyer (helper);
1474                 goto clean;
1475         }
1476         g_free (account_name);
1477 #endif
1478         /* Create the mail operation */
1479         mail_op =
1480                 modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
1481                                                                modest_ui_actions_disk_operations_error_handler,
1482                                                                g_strdup (error_msg), g_free);
1483         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1484                                          mail_op);
1485
1486
1487 #ifndef MODEST_TOOLKIT_HILDON2
1488         if (show_open_draft) {
1489                 helper->banner_info = g_slice_new (OpenMsgBannerInfo);
1490                 helper->banner_info->message = g_strdup (_("mail_ib_opening_draft_message"));
1491                 helper->banner_info->banner = NULL;
1492                 helper->banner_info->idle_handler = g_timeout_add (500, open_msg_banner_idle,
1493                                                                    helper->banner_info);
1494         }
1495 #endif
1496
1497
1498         TnyList *headers;
1499         headers = TNY_LIST (tny_simple_list_new ());
1500         tny_list_prepend (headers, G_OBJECT (helper->header));
1501         modest_mail_operation_get_msgs_full (mail_op,
1502                                              headers,
1503                                              open_msg_cb,
1504                                              helper,
1505                                              open_msg_helper_destroyer);
1506         g_object_unref (headers);
1507
1508         /* Frees */
1509  clean:
1510         if (error_msg)
1511                 g_free (error_msg);
1512         if (mail_op)
1513                 g_object_unref (mail_op);
1514         g_object_unref (account);
1515 }
1516
1517 /*
1518  * This function is used by both modest_ui_actions_on_open and
1519  * modest_ui_actions_on_header_activated. This way we always do the
1520  * same when trying to open messages.
1521  */
1522 static void
1523 open_msg_from_header (TnyHeader *header, GtkTreeRowReference *rowref, ModestWindow *win)
1524 {
1525         ModestWindowMgr *mgr = NULL;
1526         TnyAccount *account;
1527         gboolean cached = FALSE;
1528         gboolean found;
1529         GtkWidget *header_view = NULL;
1530         OpenMsgHelper *helper;
1531         ModestWindow *window;
1532
1533         g_return_if_fail (header != NULL && rowref != NULL);
1534
1535         mgr = modest_runtime_get_window_mgr ();
1536
1537         /* get model */
1538         header_view = get_header_view_from_window (MODEST_WINDOW (win));
1539         if (header_view == NULL)
1540                 return;
1541
1542         /* Get the account */
1543         account = get_account_from_header (header);
1544         if (!account)
1545                 return;
1546
1547         window = NULL;
1548         found = modest_window_mgr_find_registered_header (mgr, header, &window);
1549
1550         /* Do not open again the message and present the
1551            window to the user */
1552         if (found) {
1553                 if (window) {
1554 #ifndef MODEST_TOOLKIT_HILDON2
1555                         gtk_window_present (GTK_WINDOW (window));
1556 #endif
1557                 } else {
1558                         /* the header has been registered already, we don't do
1559                          * anything but wait for the window to come up*/
1560                         g_debug ("header %p already registered, waiting for window", header);
1561                 }
1562                 goto cleanup;
1563         }
1564
1565         /* Open each message */
1566         cached = tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED;
1567         if (!cached) {
1568                 /* Allways download if we are online. */
1569                 if (!tny_device_is_online (modest_runtime_get_device ())) {
1570                         gint response;
1571
1572                         /* If ask for user permission to download the messages */
1573                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1574                                                                             _("mcen_nc_get_msg"));
1575
1576                         /* End if the user does not want to continue */
1577                         if (response == GTK_RESPONSE_CANCEL) {
1578                                 goto cleanup;
1579                         }
1580                 }
1581         }
1582
1583         /* We register the window for opening */
1584         modest_window_mgr_register_header (mgr, header, NULL);
1585
1586         /* Create the helper. We need to get a reference to the model
1587            here because it could change while the message is readed
1588            (the user could switch between folders) */
1589         helper = g_slice_new (OpenMsgHelper);
1590         helper->model = g_object_ref (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)));
1591         helper->header = g_object_ref (header);
1592         helper->rowref = gtk_tree_row_reference_copy (rowref);
1593         helper->banner_info = NULL;
1594
1595         /* Connect to the account and perform */
1596         if (!cached) {
1597                 modest_platform_connect_and_perform ((GtkWindow *) win, TRUE, g_object_ref (account),
1598                                                      open_msg_performer, helper);
1599         } else {
1600                 /* Call directly the performer, do not need to connect */
1601                 open_msg_performer (FALSE, NULL, (GtkWindow *) win,
1602                                     g_object_ref (account), helper);
1603         }
1604 cleanup:
1605         /* Clean */
1606         if (account)
1607                 g_object_unref (account);
1608 }
1609
1610 void
1611 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1612 {
1613         TnyList *headers;
1614         TnyHeader *header;
1615         gint headers_count;
1616         TnyIterator *iter;
1617
1618         /* we check for low-mem; in that case, show a warning, and don't allow
1619          * opening
1620          */
1621         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
1622                 return;
1623
1624         /* Get headers */
1625         headers = get_selected_headers (win);
1626         if (!headers)
1627                 return;
1628
1629         headers_count = tny_list_get_length (headers);
1630         if (headers_count != 1) {
1631                 if (headers_count > 1) {
1632                         /* Don't allow activation if there are more than one message selected */
1633                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
1634                 }
1635
1636                 g_object_unref (headers);
1637                 return;
1638         }
1639
1640         iter = tny_list_create_iterator (headers);
1641         header = TNY_HEADER (tny_iterator_get_current (iter));
1642         g_object_unref (iter);
1643
1644         /* Open them */
1645         if (header) {
1646                 open_msg_from_header (header, NULL, win);
1647                 g_object_unref (header);
1648         }
1649
1650         g_object_unref(headers);
1651 }
1652
1653 static void
1654 rf_helper_window_closed (gpointer data,
1655                          GObject *object)
1656 {
1657         ReplyForwardHelper *helper = (ReplyForwardHelper *) data;
1658
1659         helper->parent_window = NULL;
1660 }
1661
1662 static ReplyForwardHelper*
1663 create_reply_forward_helper (ReplyForwardAction action,
1664                              ModestWindow *win,
1665                              guint reply_forward_type,
1666                              TnyHeader *header)
1667 {
1668         ReplyForwardHelper *rf_helper = NULL;
1669         const gchar *active_acc = modest_window_get_active_account (win);
1670         const gchar *active_mailbox = modest_window_get_active_mailbox (win);
1671
1672         rf_helper = g_slice_new0 (ReplyForwardHelper);
1673         rf_helper->reply_forward_type = reply_forward_type;
1674         rf_helper->action = action;
1675         rf_helper->parent_window = (MODEST_IS_WINDOW (win)) ? GTK_WIDGET (win) : NULL;
1676         rf_helper->header = (header) ? g_object_ref (header) : NULL;
1677         rf_helper->account_name = (active_acc) ?
1678                 g_strdup (active_acc) :
1679                 modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1680         rf_helper->mailbox = g_strdup (active_mailbox);
1681
1682         /* Note that window could be destroyed just AFTER calling
1683            register_window so we must ensure that this pointer does
1684            not hold invalid references */
1685         if (rf_helper->parent_window)
1686                 g_object_weak_ref (G_OBJECT (rf_helper->parent_window),
1687                                    rf_helper_window_closed, rf_helper);
1688
1689         return rf_helper;
1690 }
1691
1692 static void
1693 free_reply_forward_helper (gpointer data)
1694 {
1695         ReplyForwardHelper *helper;
1696
1697         helper = (ReplyForwardHelper *) data;
1698         g_free (helper->account_name);
1699         g_free (helper->mailbox);
1700         if (helper->header)
1701                 g_object_unref (helper->header);
1702         if (helper->parent_window)
1703                 g_object_weak_unref (G_OBJECT (helper->parent_window),
1704                                      rf_helper_window_closed, helper);
1705         g_slice_free (ReplyForwardHelper, helper);
1706 }
1707
1708 static void
1709 reply_forward_cb (ModestMailOperation *mail_op,
1710                   TnyHeader *header,
1711                   gboolean canceled,
1712                   TnyMsg *msg,
1713                   GError *err,
1714                   gpointer user_data)
1715 {
1716         TnyMsg *new_msg = NULL;
1717         ReplyForwardHelper *rf_helper;
1718         ModestWindow *msg_win = NULL;
1719         ModestEditType edit_type;
1720         gchar *from = NULL;
1721         TnyAccount *account = NULL;
1722         ModestWindowMgr *mgr = NULL;
1723         gchar *signature = NULL;
1724         gboolean use_signature;
1725         gchar *recipient;
1726
1727         /* If there was any error. The mail operation could be NULL,
1728            this means that we already have the message downloaded and
1729            that we didn't do a mail operation to retrieve it */
1730         rf_helper = (ReplyForwardHelper *) user_data;
1731         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1732                 goto cleanup;
1733
1734         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1735                                                    rf_helper->account_name, rf_helper->mailbox);
1736         recipient = modest_text_utils_get_email_address (from);
1737         signature = modest_account_mgr_get_signature_from_recipient (modest_runtime_get_account_mgr(), 
1738                                                                      recipient, 
1739                                                                      &use_signature);
1740         g_free (recipient);
1741
1742         /* Create reply mail */
1743         switch (rf_helper->action) {
1744         case ACTION_REPLY:
1745                 new_msg =
1746                         modest_tny_msg_create_reply_msg (msg, header, from,
1747                                                          (use_signature) ? signature : NULL,
1748                                                          rf_helper->reply_forward_type,
1749                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1750                 break;
1751         case ACTION_REPLY_TO_ALL:
1752                 new_msg =
1753                         modest_tny_msg_create_reply_msg (msg, header, from,
1754                                                          (use_signature) ? signature : NULL,
1755                                                          rf_helper->reply_forward_type,
1756                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1757                 edit_type = MODEST_EDIT_TYPE_REPLY;
1758                 break;
1759         case ACTION_FORWARD:
1760                 new_msg =
1761                         modest_tny_msg_create_forward_msg (msg, from, (use_signature) ? signature : NULL,
1762                                                            rf_helper->reply_forward_type);
1763                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1764                 break;
1765         default:
1766                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1767                                                      header);
1768                 g_return_if_reached ();
1769                 return;
1770         }
1771
1772         g_free (from);
1773         g_free (signature);
1774
1775         if (!new_msg) {
1776                 g_warning ("%s: failed to create message\n", __FUNCTION__);
1777                 goto cleanup;
1778         }
1779
1780         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1781                                                                        rf_helper->account_name,
1782                                                                        TNY_ACCOUNT_TYPE_STORE);
1783         if (!account) {
1784                 g_warning ("%s: failed to get tnyaccount for '%s'\n", __FUNCTION__, rf_helper->account_name);
1785                 goto cleanup;
1786         }
1787
1788         /* Create and register the windows */
1789         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, rf_helper->mailbox, FALSE);
1790         mgr = modest_runtime_get_window_mgr ();
1791         modest_window_mgr_register_window (mgr, msg_win, (ModestWindow *) rf_helper->parent_window);
1792
1793         /* Note that register_window could have deleted the account */
1794         if (MODEST_IS_WINDOW (rf_helper->parent_window)) {
1795                 gdouble parent_zoom;
1796
1797                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1798                 modest_window_set_zoom (msg_win, parent_zoom);
1799         }
1800
1801         /* Show edit window */
1802         gtk_widget_show_all (GTK_WIDGET (msg_win));
1803
1804 cleanup:
1805         /* We always unregister the header because the message is
1806            forwarded or replied so the original one is no longer
1807            opened */
1808         modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1809                                              header);
1810         if (new_msg)
1811                 g_object_unref (G_OBJECT (new_msg));
1812         if (account)
1813                 g_object_unref (G_OBJECT (account));
1814         free_reply_forward_helper (rf_helper);
1815 }
1816
1817 /* Checks a list of headers. If any of them are not currently
1818  * downloaded (CACHED) then returns TRUE else returns FALSE.
1819  */
1820 static gint
1821 header_list_count_uncached_msgs (TnyList *header_list)
1822 {
1823         TnyIterator *iter;
1824         gint uncached_messages = 0;
1825
1826         iter = tny_list_create_iterator (header_list);
1827         while (!tny_iterator_is_done (iter)) {
1828                 TnyHeader *header;
1829
1830                 header = TNY_HEADER (tny_iterator_get_current (iter));
1831                 if (header) {
1832                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1833                                 uncached_messages ++;
1834                         g_object_unref (header);
1835                 }
1836
1837                 tny_iterator_next (iter);
1838         }
1839         g_object_unref (iter);
1840
1841         return uncached_messages;
1842 }
1843
1844 /* Returns FALSE if the user does not want to download the
1845  * messages. Returns TRUE if the user allowed the download.
1846  */
1847 static gboolean
1848 connect_to_get_msg (ModestWindow *win,
1849                     gint num_of_uncached_msgs,
1850                     TnyAccount *account)
1851 {
1852         GtkResponseType response;
1853
1854         /* Allways download if we are online. */
1855         if (tny_device_is_online (modest_runtime_get_device ()))
1856                 return TRUE;
1857
1858         /* If offline, then ask for user permission to download the messages */
1859         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1860                         ngettext("mcen_nc_get_msg",
1861                         "mcen_nc_get_msgs",
1862                         num_of_uncached_msgs));
1863
1864         if (response == GTK_RESPONSE_CANCEL)
1865                 return FALSE;
1866
1867         return modest_platform_connect_and_wait((GtkWindow *) win, account);
1868 }
1869
1870 static void
1871 reply_forward_performer (gboolean canceled,
1872                          GError *err,
1873                          GtkWindow *parent_window,
1874                          TnyAccount *account,
1875                          gpointer user_data)
1876 {
1877         ReplyForwardHelper *rf_helper = NULL;
1878         ModestMailOperation *mail_op;
1879
1880         rf_helper = (ReplyForwardHelper *) user_data;
1881
1882         if (canceled || err) {
1883                 free_reply_forward_helper (rf_helper);
1884                 return;
1885         }
1886
1887         /* Retrieve the message */
1888         modest_window_mgr_register_header (modest_runtime_get_window_mgr (), rf_helper->header, NULL);
1889         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (parent_window),
1890                                                                  modest_ui_actions_disk_operations_error_handler,
1891                                                                  NULL, NULL);
1892         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1893         modest_mail_operation_get_msg (mail_op, rf_helper->header, TRUE, reply_forward_cb, rf_helper);
1894
1895         /* Frees */
1896         g_object_unref(mail_op);
1897 }
1898
1899 /*
1900  * Common code for the reply and forward actions
1901  */
1902 static void
1903 reply_forward (ReplyForwardAction action, ModestWindow *win)
1904 {
1905         ReplyForwardHelper *rf_helper = NULL;
1906         guint reply_forward_type;
1907
1908         g_return_if_fail (MODEST_IS_WINDOW(win));
1909
1910         /* we check for low-mem; in that case, show a warning, and don't allow
1911          * reply/forward (because it could potentially require a lot of memory */
1912         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
1913                 return;
1914
1915
1916         /* we need an account when editing */
1917         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1918                 if (!modest_ui_actions_run_account_setup_wizard (win))
1919                         return;
1920         }
1921
1922         reply_forward_type =
1923                 modest_conf_get_int (modest_runtime_get_conf (),
1924                                      (action == ACTION_FORWARD) ?
1925                                      MODEST_CONF_FORWARD_TYPE :
1926                                      MODEST_CONF_REPLY_TYPE,
1927                                      NULL);
1928
1929         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1930                 TnyMsg *msg = NULL;
1931                 TnyHeader *header = NULL;
1932                 /* Get header and message. Do not free them here, the
1933                    reply_forward_cb must do it */
1934                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1935                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
1936
1937                 if (msg && header) {
1938                         /* Create helper */
1939                         rf_helper = create_reply_forward_helper (action, win,
1940                                                                  reply_forward_type, header);
1941                         reply_forward_cb (NULL, header, FALSE, msg, NULL, rf_helper);
1942                 } else {
1943                         g_warning("%s: no message or header found in viewer\n", __FUNCTION__);
1944                 }
1945
1946                 if (msg)
1947                         g_object_unref (msg);
1948                 if (header)
1949                         g_object_unref (header);
1950         } else {
1951                 TnyHeader *header = NULL;
1952                 TnyIterator *iter;
1953                 gboolean do_retrieve = TRUE;
1954                 TnyList *header_list = NULL;
1955
1956                 header_list = get_selected_headers (win);
1957                 if (!header_list)
1958                         return;
1959                 /* Check that only one message is selected for replying */
1960                 if (tny_list_get_length (header_list) != 1) {
1961                         modest_platform_information_banner ((win) ? GTK_WIDGET (win) : NULL,
1962                                                             NULL, _("mcen_ib_select_one_message"));
1963                         g_object_unref (header_list);
1964                         return;
1965                 }
1966
1967                 /* Only reply/forward to one message */
1968                 iter = tny_list_create_iterator (header_list);
1969                 header = TNY_HEADER (tny_iterator_get_current (iter));
1970                 g_object_unref (iter);
1971
1972                 /* Retrieve messages */
1973                 do_retrieve = (action == ACTION_FORWARD) ||
1974                         (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1975
1976                 if (do_retrieve) {
1977                         TnyAccount *account = NULL;
1978                         TnyFolder *folder = NULL;
1979                         gdouble download = TRUE;
1980                         guint uncached_msgs = 0;
1981
1982                         folder = tny_header_get_folder (header);
1983                         if (!folder)
1984                                 goto do_retrieve_frees;
1985                         account = tny_folder_get_account (folder);
1986                         if (!account)
1987                                 goto do_retrieve_frees;
1988
1989                         uncached_msgs = header_list_count_uncached_msgs (header_list);
1990
1991                         if (uncached_msgs > 0) {
1992                                 /* Allways download if we are online. */
1993                                 if (!tny_device_is_online (modest_runtime_get_device ())) {
1994                                         gint response;
1995
1996                                         /* If ask for user permission to download the messages */
1997                                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1998                                                                                             ngettext("mcen_nc_get_msg",
1999                                                                                                      "mcen_nc_get_msgs",
2000                                                                                                      uncached_msgs));
2001
2002                                         /* End if the user does not want to continue */
2003                                         if (response == GTK_RESPONSE_CANCEL)
2004                                                 download = FALSE;
2005                                 }
2006                         }
2007
2008                         if (download) {
2009                                 /* Create helper */
2010                                 rf_helper = create_reply_forward_helper (action, win,
2011                                                                          reply_forward_type, header);
2012                                 if (uncached_msgs > 0) {
2013                                         modest_platform_connect_and_perform (GTK_WINDOW (win),
2014                                                                              TRUE, account,
2015                                                                              reply_forward_performer,
2016                                                                              rf_helper);
2017                                 } else {
2018                                         reply_forward_performer (FALSE, NULL, GTK_WINDOW (win),
2019                                                                  account, rf_helper);
2020                                 }
2021                         }
2022                 do_retrieve_frees:
2023                         if (account)
2024                                 g_object_unref (account);
2025                         if (folder)
2026                                 g_object_unref (folder);
2027                 } else {
2028                         reply_forward_cb (NULL, header, FALSE, NULL, NULL, rf_helper);
2029                 }
2030                 /* Frees */
2031                 g_object_unref (header_list);
2032                 g_object_unref (header);
2033         }
2034 }
2035
2036 void
2037 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
2038 {
2039         g_return_if_fail (MODEST_IS_WINDOW(win));
2040
2041         reply_forward (ACTION_REPLY, win);
2042 }
2043
2044 void
2045 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
2046 {
2047         g_return_if_fail (MODEST_IS_WINDOW(win));
2048
2049         reply_forward (ACTION_FORWARD, win);
2050 }
2051
2052 void
2053 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
2054 {
2055         g_return_if_fail (MODEST_IS_WINDOW(win));
2056
2057         reply_forward (ACTION_REPLY_TO_ALL, win);
2058 }
2059
2060 void
2061 modest_ui_actions_on_next (GtkAction *action,
2062                            ModestWindow *window)
2063 {
2064         if (MODEST_IS_MAIN_WINDOW (window)) {
2065                 GtkWidget *header_view;
2066
2067                 header_view = modest_main_window_get_child_widget (
2068                                 MODEST_MAIN_WINDOW(window),
2069                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2070                 if (!header_view)
2071                         return;
2072
2073                 modest_header_view_select_next (
2074                                 MODEST_HEADER_VIEW(header_view));
2075         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2076                 modest_msg_view_window_select_next_message (
2077                                 MODEST_MSG_VIEW_WINDOW (window));
2078         } else {
2079                 g_return_if_reached ();
2080         }
2081 }
2082
2083 void
2084 modest_ui_actions_on_prev (GtkAction *action,
2085                            ModestWindow *window)
2086 {
2087         g_return_if_fail (MODEST_IS_WINDOW(window));
2088
2089         if (MODEST_IS_MAIN_WINDOW (window)) {
2090                 GtkWidget *header_view;
2091                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
2092                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2093                 if (!header_view)
2094                         return;
2095
2096                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view));
2097         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2098                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
2099         } else {
2100                 g_return_if_reached ();
2101         }
2102 }
2103
2104 void
2105 modest_ui_actions_on_sort (GtkAction *action,
2106                            ModestWindow *window)
2107 {
2108         GtkWidget *header_view = NULL;
2109
2110         g_return_if_fail (MODEST_IS_WINDOW(window));
2111
2112         if (MODEST_IS_MAIN_WINDOW (window)) {
2113                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
2114                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2115 #ifdef MODEST_TOOLKIT_HILDON2
2116         } else if (MODEST_IS_HEADER_WINDOW (window)) {
2117                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window)));
2118 #endif
2119         }
2120
2121         if (!header_view) {
2122                 modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
2123
2124                 return;
2125         }
2126
2127         /* Show sorting dialog */
2128         modest_utils_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);
2129 }
2130
2131 static void
2132 new_messages_arrived (ModestMailOperation *self,
2133                       TnyList *new_headers,
2134                       gpointer user_data)
2135 {
2136         GObject *source;
2137         gboolean show_visual_notifications;
2138
2139         source = modest_mail_operation_get_source (self);
2140         show_visual_notifications = (source) ? FALSE : TRUE;
2141         if (source)
2142                 g_object_unref (source);
2143
2144         /* Notify new messages have been downloaded. If the
2145            send&receive was invoked by the user then do not show any
2146            visual notification, only play a sound and activate the LED
2147            (for the Maemo version) */
2148         if (TNY_IS_LIST(new_headers) && (tny_list_get_length (new_headers)) > 0) {
2149
2150                 /* We only notify about really new messages (not seen) we get */
2151                 TnyList *actually_new_list;
2152                 TnyIterator *iterator;
2153                 actually_new_list = TNY_LIST (tny_simple_list_new ());
2154                 for (iterator = tny_list_create_iterator (new_headers);
2155                      !tny_iterator_is_done (iterator);
2156                      tny_iterator_next (iterator)) {
2157                         TnyHeader *header;
2158                         TnyHeaderFlags flags;
2159                         header = TNY_HEADER (tny_iterator_get_current (iterator));
2160                         flags = tny_header_get_flags (header);
2161
2162                         if (!(flags & TNY_HEADER_FLAG_SEEN)) {
2163                                 tny_list_append (actually_new_list, G_OBJECT (header));
2164                         }
2165                         g_object_unref (header);
2166                 }
2167                 g_object_unref (iterator);
2168
2169                 if (tny_list_get_length (actually_new_list) > 0) {
2170                         GList *new_headers_list = NULL;
2171
2172                         new_headers_list = modest_utils_create_notification_list_from_header_list (actually_new_list);
2173
2174                         /* Send notifications */
2175                         if (new_headers_list) {
2176                                 modest_platform_on_new_headers_received (new_headers_list,
2177                                                                          show_visual_notifications);
2178                                 /* Free the list */
2179                                 modest_utils_free_notification_list (new_headers_list);
2180                         }
2181                 }
2182                 g_object_unref (actually_new_list);
2183         }
2184
2185 }
2186
2187 gboolean
2188 retrieve_all_messages_cb (GObject *source,
2189                           guint num_msgs,
2190                           guint retrieve_limit)
2191 {
2192         GtkWindow *window;
2193         gchar *msg;
2194         gint response;
2195
2196         window = GTK_WINDOW (source);
2197         msg = g_strdup_printf (_("mail_nc_msg_count_limit_exceeded"),
2198                                num_msgs, retrieve_limit);
2199
2200         /* Ask the user if they want to retrieve all the messages */
2201         response =
2202                 modest_platform_run_confirmation_dialog_with_buttons (window, msg,
2203                                                                       _("mcen_bd_get_all"),
2204                                                                       _("mcen_bd_newest_only"));
2205         /* Free and return */
2206         g_free (msg);
2207         return (response == GTK_RESPONSE_ACCEPT) ? TRUE : FALSE;
2208 }
2209
2210 typedef struct {
2211         TnyAccount *account;
2212         ModestWindow *win;
2213         gchar *account_name;
2214         gboolean poke_status;
2215         gboolean interactive;
2216         ModestMailOperation *mail_op;
2217 } SendReceiveInfo;
2218
2219 static void
2220 do_send_receive_performer (gboolean canceled,
2221                            GError *err,
2222                            GtkWindow *parent_window,
2223                            TnyAccount *account,
2224                            gpointer user_data)
2225 {
2226         SendReceiveInfo *info;
2227
2228         info = (SendReceiveInfo *) user_data;
2229
2230         if (err || canceled) {
2231                 /* In disk full conditions we could get this error here */
2232                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
2233                                                                 (GtkWidget *) parent_window, err,
2234                                                                 account, NULL);
2235
2236                 if (info->mail_op) {
2237                         modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (),
2238                                                             info->mail_op);
2239                 }
2240                 goto clean;
2241         }
2242
2243         /* Set send/receive operation in progress */
2244         if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
2245                 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
2246         }
2247
2248         if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
2249                 g_signal_connect (G_OBJECT (info->mail_op), "operation-finished",
2250                                   G_CALLBACK (on_send_receive_finished),
2251                                   info->win);
2252
2253         /* Send & receive. */
2254         modest_mail_operation_update_account (info->mail_op, info->account_name, info->poke_status, info->interactive,
2255                                               (info->win) ? retrieve_all_messages_cb : NULL,
2256                                               new_messages_arrived, info->win);
2257
2258  clean:
2259         /* Frees */
2260         if (info->mail_op)
2261                 g_object_unref (G_OBJECT (info->mail_op));
2262         if (info->account_name)
2263                 g_free (info->account_name);
2264         if (info->win)
2265                 g_object_unref (info->win);
2266         if (info->account)
2267                 g_object_unref (info->account);
2268         g_slice_free (SendReceiveInfo, info);
2269 }
2270
2271 /*
2272  * This function performs the send & receive required actions. The
2273  * window is used to create the mail operation. Typically it should
2274  * always be the main window, but we pass it as argument in order to
2275  * be more flexible.
2276  */
2277 void
2278 modest_ui_actions_do_send_receive (const gchar *account_name,
2279                                    gboolean force_connection,
2280                                    gboolean poke_status,
2281                                    gboolean interactive,
2282                                    ModestWindow *win)
2283 {
2284         gchar *acc_name = NULL;
2285         SendReceiveInfo *info;
2286         ModestTnyAccountStore *acc_store;
2287         TnyAccount *account;
2288
2289         /* If no account name was provided then get the current account, and if
2290            there is no current account then pick the default one: */
2291         if (!account_name) {
2292                 if (win)
2293                         acc_name = g_strdup (modest_window_get_active_account (win));
2294                 if (!acc_name)
2295                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
2296                 if (!acc_name) {
2297                         g_printerr ("modest: cannot get default account\n");
2298                         return;
2299                 }
2300         } else {
2301                 acc_name = g_strdup (account_name);
2302         }
2303
2304         acc_store = modest_runtime_get_account_store ();
2305         account = modest_tny_account_store_get_server_account (acc_store, acc_name, TNY_ACCOUNT_TYPE_STORE);
2306
2307         /* Do not automatically refresh accounts that are flagged as
2308            NO_AUTO_UPDATE. This could be useful for accounts that
2309            handle their own update times */
2310         if (!interactive) {
2311                 ModestProtocolType proto = modest_tny_account_get_protocol_type (account);
2312                 if (proto != MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
2313                         const gchar *tag = MODEST_PROTOCOL_REGISTRY_NO_AUTO_UPDATE_PROTOCOLS;
2314                         ModestProtocolRegistry *registry = modest_runtime_get_protocol_registry ();
2315
2316                         if (modest_protocol_registry_protocol_type_has_tag (registry, proto, tag)) {
2317                                 g_debug ("%s no auto update allowed for account %s", __FUNCTION__, account_name);
2318                                 g_object_unref (account);
2319                                 g_free (acc_name);
2320                                 return;
2321                         }
2322                 }
2323         }
2324
2325         /* Create the info for the connect and perform */
2326         info = g_slice_new (SendReceiveInfo);
2327         info->account_name = acc_name;
2328         info->win = (win) ? g_object_ref (win) : NULL;
2329         info->poke_status = poke_status;
2330         info->interactive = interactive;
2331         info->account = account;
2332         /* We need to create the operation here, because otherwise it
2333            could happen that the queue emits the queue-empty signal
2334            while we're trying to connect the account */
2335         info->mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
2336                                                                        modest_ui_actions_disk_operations_error_handler,
2337                                                                        NULL, NULL);
2338         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), info->mail_op);
2339
2340         /* Invoke the connect and perform */
2341         modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL,
2342                                              force_connection, info->account,
2343                                              do_send_receive_performer, info);
2344 }
2345
2346
2347 static void
2348 modest_ui_actions_do_cancel_send (const gchar *account_name,
2349                                   ModestWindow *win)
2350 {
2351         TnyTransportAccount *transport_account;
2352         TnySendQueue *send_queue = NULL;
2353         GError *error = NULL;
2354
2355         /* Get transport account */
2356         transport_account =
2357                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2358                                       (modest_runtime_get_account_store(),
2359                                        account_name,
2360                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2361         if (!transport_account) {
2362                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2363                 goto frees;
2364         }
2365
2366         /* Get send queue*/
2367         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account, TRUE));
2368         if (!TNY_IS_SEND_QUEUE(send_queue)) {
2369                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
2370                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2371                              "modest: could not find send queue for account\n");
2372         } else {
2373                 /* Cancel the current send */
2374                 tny_account_cancel (TNY_ACCOUNT (transport_account));
2375
2376                 /* Suspend all pending messages */
2377                 tny_send_queue_cancel (send_queue, TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, &error);
2378         }
2379
2380  frees:
2381         if (transport_account != NULL)
2382                 g_object_unref (G_OBJECT (transport_account));
2383 }
2384
2385 static void
2386 modest_ui_actions_cancel_send_all (ModestWindow *win)
2387 {
2388         GSList *account_names, *iter;
2389
2390         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2391                                                           TRUE);
2392
2393         iter = account_names;
2394         while (iter) {
2395                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
2396                 iter = g_slist_next (iter);
2397         }
2398
2399         modest_account_mgr_free_account_names (account_names);
2400         account_names = NULL;
2401 }
2402
2403 void
2404 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
2405
2406 {
2407         /* Check if accounts exist */
2408         gboolean accounts_exist =
2409                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2410
2411         /* If not, allow the user to create an account before trying to send/receive. */
2412         if (!accounts_exist)
2413                 modest_ui_actions_on_accounts (NULL, win);
2414
2415         /* Cancel all sending operaitons */
2416         modest_ui_actions_cancel_send_all (win);
2417 }
2418
2419 /*
2420  * Refreshes all accounts. This function will be used by automatic
2421  * updates
2422  */
2423 void
2424 modest_ui_actions_do_send_receive_all (ModestWindow *win,
2425                                        gboolean force_connection,
2426                                        gboolean poke_status,
2427                                        gboolean interactive)
2428 {
2429         GSList *account_names, *iter;
2430
2431         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2432                                                           TRUE);
2433
2434         iter = account_names;
2435         while (iter) {
2436                 modest_ui_actions_do_send_receive ((const char*) iter->data,
2437                                                    force_connection,
2438                                                    poke_status, interactive, win);
2439                 iter = g_slist_next (iter);
2440         }
2441
2442         modest_account_mgr_free_account_names (account_names);
2443         account_names = NULL;
2444 }
2445
2446 /*
2447  * Handler of the click on Send&Receive button in the main toolbar
2448  */
2449 void
2450 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
2451 {
2452         /* Check if accounts exist */
2453         gboolean accounts_exist;
2454
2455         accounts_exist =
2456                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2457
2458         /* If not, allow the user to create an account before trying to send/receive. */
2459         if (!accounts_exist)
2460                 modest_ui_actions_on_accounts (NULL, win);
2461
2462         /* Refresh the current folder. The if is always TRUE it's just an extra check */
2463         if (MODEST_IS_MAIN_WINDOW (win)) {
2464                 GtkWidget *folder_view;
2465                 TnyFolderStore *folder_store;
2466
2467                 folder_view =
2468                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2469                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2470                 if (!folder_view)
2471                         return;
2472
2473                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2474
2475                 if (folder_store)
2476                         g_object_unref (folder_store);
2477                 /* Refresh the active account. Force the connection if needed
2478                    and poke the status of all folders */
2479                 modest_ui_actions_do_send_receive (NULL, TRUE, TRUE, TRUE, win);
2480 #ifdef MODEST_TOOLKIT_HILDON2
2481         } else if (MODEST_IS_ACCOUNTS_WINDOW (win)) {
2482                 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2483 #endif
2484         } else {
2485                 const gchar *active_account;
2486                 active_account = modest_window_get_active_account (MODEST_WINDOW (win));
2487
2488                 modest_ui_actions_do_send_receive (active_account, TRUE, TRUE, TRUE, win);
2489         }
2490
2491 }
2492
2493
2494 void
2495 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
2496 {
2497         ModestConf *conf;
2498         GtkWidget *header_view;
2499
2500         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2501
2502         header_view = modest_main_window_get_child_widget (main_window,
2503                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2504         if (!header_view)
2505                 return;
2506
2507         conf = modest_runtime_get_conf ();
2508
2509         /* what is saved/restored is depending on the style; thus; we save with
2510          * old style, then update the style, and restore for this new style
2511          */
2512         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
2513
2514         if (modest_header_view_get_style
2515             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
2516                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2517                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
2518         else
2519                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2520                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
2521
2522         modest_widget_memory_restore (conf, G_OBJECT(header_view),
2523                                       MODEST_CONF_HEADER_VIEW_KEY);
2524 }
2525
2526
2527 void
2528 modest_ui_actions_on_header_selected (ModestHeaderView *header_view,
2529                                       TnyHeader *header,
2530                                       ModestMainWindow *main_window)
2531 {
2532         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2533         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2534
2535         /* in the case the folder is empty, show the empty folder message and focus
2536          * folder view */
2537         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
2538                 if (modest_header_view_is_empty (header_view)) {
2539                         TnyFolder *folder = modest_header_view_get_folder (header_view);
2540                         GtkWidget *folder_view =
2541                                 modest_main_window_get_child_widget (main_window,
2542                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2543                         if (folder != NULL) {
2544                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
2545                                 g_object_unref (folder);
2546                         }
2547                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
2548                         return;
2549                 }
2550         }
2551         /* If no header has been selected then exit */
2552         if (!header)
2553                 return;
2554
2555         /* Update focus */
2556         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
2557             gtk_widget_grab_focus (GTK_WIDGET(header_view));
2558
2559         /* Update toolbar dimming state */
2560         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2561         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2562 }
2563
2564 void
2565 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
2566                                        TnyHeader *header,
2567                                        GtkTreePath *path,
2568                                        ModestWindow *window)
2569 {
2570         GtkWidget *open_widget;
2571         GtkTreeRowReference *rowref;
2572
2573         g_return_if_fail (MODEST_IS_WINDOW(window));
2574         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2575         g_return_if_fail (TNY_IS_HEADER (header));
2576
2577         if (modest_header_view_count_selected_headers (header_view) > 1) {
2578                 /* Don't allow activation if there are more than one message selected */
2579                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
2580                 return;
2581         }
2582
2583         /* we check for low-mem; in that case, show a warning, and don't allow
2584          * activating headers
2585          */
2586         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2587                 return;
2588
2589         if (MODEST_IS_MAIN_WINDOW (window)) {
2590                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2591                 open_widget = modest_window_get_action_widget (MODEST_WINDOW (window), "/MenuBar/EmailMenu/EmailOpenMenu");
2592                 if (!GTK_WIDGET_IS_SENSITIVE (open_widget))
2593                         return;
2594         }
2595
2596         rowref = gtk_tree_row_reference_new (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)), path);
2597         open_msg_from_header (header, rowref, MODEST_WINDOW (window));
2598         gtk_tree_row_reference_free (rowref);
2599 }
2600
2601 static void
2602 set_active_account_from_tny_account (TnyAccount *account,
2603                                      ModestWindow *window)
2604 {
2605         const gchar *server_acc_name = tny_account_get_id (account);
2606
2607         /* We need the TnyAccount provided by the
2608            account store because that is the one that
2609            knows the name of the Modest account */
2610         TnyAccount *modest_server_account =
2611                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2612                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID,
2613                                                              server_acc_name);
2614         if (!modest_server_account) {
2615                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2616                 return;
2617         }
2618
2619         /* Update active account, but only if it's not a pseudo-account */
2620         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2621             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2622                 const gchar *modest_acc_name =
2623                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2624                 if (modest_acc_name)
2625                         modest_window_set_active_account (window, modest_acc_name);
2626         }
2627
2628         g_object_unref (modest_server_account);
2629 }
2630
2631
2632 static void
2633 folder_refreshed_cb (ModestMailOperation *mail_op,
2634                      TnyFolder *folder,
2635                      gpointer user_data)
2636 {
2637         ModestMainWindow *win = NULL;
2638         GtkWidget *folder_view, *header_view;
2639         const GError *error;
2640
2641         g_return_if_fail (TNY_IS_FOLDER (folder));
2642
2643         win = MODEST_MAIN_WINDOW (user_data);
2644
2645         /* Check if the operation failed due to memory low conditions */
2646         error = modest_mail_operation_get_error (mail_op);
2647         if (error && error->domain == MODEST_MAIL_OPERATION_ERROR &&
2648             error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
2649                 modest_platform_run_information_dialog (GTK_WINDOW (win),
2650                                                         _KR("memr_ib_operation_disabled"),
2651                                                         TRUE);
2652                 return;
2653         }
2654
2655         folder_view =
2656                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2657         header_view =
2658                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2659
2660         if (folder_view) {
2661                 TnyFolderStore *current_folder;
2662
2663                 current_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2664                 if (current_folder) {
2665                         gboolean different = ((TnyFolderStore *) folder != current_folder);
2666                         g_object_unref (current_folder);
2667                         if (different)
2668                                 return;
2669                 }
2670         }
2671
2672         /* Check if folder is empty and set headers view contents style */
2673         if ((tny_folder_get_all_count (folder) == 0) ||
2674             modest_header_view_is_empty (MODEST_HEADER_VIEW (header_view)))
2675                 modest_main_window_set_contents_style (win,
2676                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2677 }
2678
2679 void
2680 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2681                                                TnyFolderStore *folder_store,
2682                                                gboolean selected,
2683                                                ModestMainWindow *main_window)
2684 {
2685         GtkWidget *header_view;
2686
2687         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2688
2689         header_view = modest_main_window_get_child_widget(main_window,
2690                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2691         if (!header_view)
2692                 return;
2693
2694
2695         if (TNY_IS_ACCOUNT (folder_store)) {
2696                 if (selected) {
2697                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2698
2699                         /* Show account details */
2700                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2701                 }
2702         } else {
2703                 if (TNY_IS_FOLDER (folder_store) && selected) {
2704                         TnyAccount *account;
2705
2706                         /* Update the active account */
2707                         account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2708                         if (account) {
2709                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2710                                 g_object_unref (account);
2711                                 account = NULL;
2712                         }
2713
2714                         /* Set the header style by default, it could
2715                            be changed later by the refresh callback to
2716                            empty */
2717                         modest_main_window_set_contents_style (main_window,
2718                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2719
2720                         /* Set folder on header view. This function
2721                            will call tny_folder_refresh_async so we
2722                            pass a callback that will be called when
2723                            finished. We use that callback to set the
2724                            empty view if there are no messages */
2725                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2726                                                        TNY_FOLDER (folder_store),
2727                                                        TRUE,
2728                                                        MODEST_WINDOW (main_window),
2729                                                        folder_refreshed_cb,
2730                                                        main_window);
2731
2732                         /* Restore configuration. We need to do this
2733                            *after* the set_folder because the widget
2734                            memory asks the header view about its
2735                            folder  */
2736                         modest_widget_memory_restore (modest_runtime_get_conf (),
2737                                                       G_OBJECT(header_view),
2738                                                       MODEST_CONF_HEADER_VIEW_KEY);
2739                 } else {
2740                         /* No need to save the header view
2741                            configuration for Maemo because it only
2742                            saves the sorting stuff and that it's
2743                            already being done by the sort
2744                            dialog. Remove it when the GNOME version
2745                            has the same behaviour */
2746 #ifdef MODEST_TOOLKIT_GTK
2747                         if (modest_main_window_get_contents_style (main_window) ==
2748                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2749                                 modest_widget_memory_save (modest_runtime_get_conf (), 
2750                                                            G_OBJECT (header_view),
2751                                                            MODEST_CONF_HEADER_VIEW_KEY);
2752 #endif
2753                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2754                 }
2755         }
2756
2757         /* Update dimming state */
2758         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2759         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2760 }
2761
2762 void
2763 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2764                                      ModestWindow *win)
2765 {
2766         GtkWidget *dialog;
2767         gchar *txt, *item;
2768         gboolean online;
2769
2770         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2771
2772         online = tny_device_is_online (modest_runtime_get_device());
2773
2774         if (online) {
2775                 /* already online -- the item is simply not there... */
2776                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2777                                                  GTK_DIALOG_MODAL,
2778                                                  GTK_MESSAGE_WARNING,
2779                                                  GTK_BUTTONS_NONE,
2780                                                  _("The %s you selected cannot be found"),
2781                                                  item);
2782                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2783                 gtk_dialog_run (GTK_DIALOG(dialog));
2784         } else {
2785                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2786                                                       GTK_WINDOW (win),
2787                                                       GTK_DIALOG_MODAL,
2788                                                       _("mcen_bd_dialog_cancel"),
2789                                                       GTK_RESPONSE_REJECT,
2790                                                       _("mcen_bd_dialog_ok"),
2791                                                       GTK_RESPONSE_ACCEPT,
2792                                                       NULL);
2793                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2794                                          "Do you want to get online?"), item);
2795                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
2796                                     gtk_label_new (txt), FALSE, FALSE, 0);
2797                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2798                 g_free (txt);
2799
2800                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2801                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2802                         /* TODO: Comment about why is this commented out: */
2803                         /* modest_platform_connect_and_wait (); */
2804                 }
2805         }
2806         gtk_widget_destroy (dialog);
2807 }
2808
2809 void
2810 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2811                                      ModestWindow *win)
2812 {
2813         /* g_debug ("%s %s", __FUNCTION__, link); */
2814 }
2815
2816
2817 void
2818 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2819                                         ModestWindow *win)
2820 {
2821         modest_platform_activate_uri (link);
2822 }
2823
2824 void
2825 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2826                                           ModestWindow *win)
2827 {
2828         modest_platform_show_uri_popup (link);
2829 }
2830
2831 void
2832 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2833                                              ModestWindow *win)
2834 {
2835         /* we check for low-mem; in that case, show a warning, and don't allow
2836          * viewing attachments
2837          */
2838         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
2839                 return;
2840
2841         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2842 }
2843
2844 void
2845 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2846                                           const gchar *address,
2847                                           ModestWindow *win)
2848 {
2849         /* g_debug ("%s %s", __FUNCTION__, address); */
2850 }
2851
2852 static void
2853 on_save_to_drafts_cb (ModestMailOperation *mail_op,
2854                       TnyMsg *saved_draft,
2855                       gpointer user_data)
2856 {
2857         ModestMsgEditWindow *edit_window;
2858
2859         /* TODO: in hildon 2 we have to dim and undim the header views while we're saving */
2860 #ifndef MODEST_TOOLKIT_HILDON2
2861         ModestMainWindow *win;
2862
2863         /* FIXME. Make the header view sensitive again. This is a
2864          * temporary hack. See modest_ui_actions_on_save_to_drafts()
2865          * for details */
2866         win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2867                                          modest_runtime_get_window_mgr(), FALSE));
2868         if (win != NULL) {
2869                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2870                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2871                 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2872         }
2873 #endif
2874
2875         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2876
2877         /* Set draft is there was no error */
2878         if (!modest_mail_operation_get_error (mail_op))
2879                 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2880
2881         g_object_unref(edit_window);
2882 }
2883
2884 static gboolean
2885 enough_space_for_message (ModestMsgEditWindow *edit_window,
2886                           MsgData *data)
2887 {
2888         guint64 available_disk, expected_size;
2889         gint parts_count;
2890         guint64 parts_size;
2891
2892         /* Check size */
2893         available_disk = modest_utils_get_available_space (NULL);
2894         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2895         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2896                                                       data->html_body,
2897                                                       parts_count,
2898                                                       parts_size);
2899
2900         /* Double check: disk full condition or message too big */
2901         if (available_disk < MODEST_TNY_ACCOUNT_STORE_MIN_FREE_SPACE ||
2902             expected_size > available_disk) {
2903                 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
2904                 modest_platform_information_banner (NULL, NULL, msg);
2905                 g_free (msg);
2906
2907                 return FALSE;
2908         }
2909
2910         /*
2911          * djcb: if we're in low-memory state, we only allow for
2912          * saving messages smaller than
2913          * MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h) this
2914          * should still allow for sending anything critical...
2915          */
2916         if ((expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) &&
2917             modest_platform_check_memory_low (MODEST_WINDOW(edit_window), TRUE))
2918                 return FALSE;
2919
2920         /*
2921          * djcb: we also make sure that the attachments are smaller than the max size
2922          * this is for the case where we'd try to forward a message with attachments
2923          * bigger than our max allowed size, or sending an message from drafts which
2924          * somehow got past our checks when attaching.
2925          */
2926         if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
2927                 modest_platform_run_information_dialog (
2928                         GTK_WINDOW(edit_window),
2929                         _FM("sfil_ib_opening_not_allowed"),
2930                         TRUE);
2931                 return FALSE;
2932         }
2933
2934         return TRUE;
2935 }
2936
2937 gboolean
2938 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2939 {
2940         TnyTransportAccount *transport_account;
2941         ModestMailOperation *mail_operation;
2942         MsgData *data;
2943         gchar *account_name;
2944         ModestAccountMgr *account_mgr;
2945         gboolean had_error = FALSE;
2946         ModestMainWindow *win = NULL;
2947
2948         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
2949
2950         data = modest_msg_edit_window_get_msg_data (edit_window);
2951
2952         /* Check size */
2953         if (!enough_space_for_message (edit_window, data)) {
2954                 modest_msg_edit_window_free_msg_data (edit_window, data);
2955                 return FALSE;
2956         }
2957
2958         account_name = g_strdup (data->account_name);
2959         account_mgr = modest_runtime_get_account_mgr();
2960         if (!account_name)
2961                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2962         if (!account_name)
2963                 account_name = modest_account_mgr_get_default_account (account_mgr);
2964         if (!account_name) {
2965                 g_printerr ("modest: no account found\n");
2966                 modest_msg_edit_window_free_msg_data (edit_window, data);
2967                 return FALSE;
2968         }
2969
2970         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2971                 account_name = g_strdup (data->account_name);
2972         }
2973
2974         transport_account =
2975                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2976                                       (modest_runtime_get_account_store (),
2977                                        account_name,
2978                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2979         if (!transport_account) {
2980                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2981                 g_free (account_name);
2982                 modest_msg_edit_window_free_msg_data (edit_window, data);
2983                 return FALSE;
2984         }
2985
2986         /* Create the mail operation */
2987         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler,
2988                                                                         NULL, NULL);
2989         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2990
2991         modest_mail_operation_save_to_drafts (mail_operation,
2992                                               transport_account,
2993                                               data->draft_msg,
2994                                               data->from,
2995                                               data->to, 
2996                                               data->cc, 
2997                                               data->bcc,
2998                                               data->subject,
2999                                               data->plain_body,
3000                                               data->html_body,
3001                                               data->attachments,
3002                                               data->images,
3003                                               data->priority_flags,
3004                                               data->references,
3005                                               data->in_reply_to,
3006                                               on_save_to_drafts_cb,
3007                                               g_object_ref(edit_window));
3008
3009 #ifdef MODEST_TOOLKIT_HILDON2
3010         /* In hildon2 we always show the information banner on saving to drafts.
3011          * It will be a system information banner in this case.
3012          */
3013         gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
3014         modest_platform_information_banner (NULL, NULL, text);
3015         g_free (text);
3016 #else
3017         /* Use the main window as the parent of the banner, if the
3018            main window does not exist it won't be shown, if the parent
3019            window exists then it's properly shown. We don't use the
3020            editor window because it could be closed (save to drafts
3021            could happen after closing the window */
3022         win = (ModestMainWindow *)
3023                 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
3024         if (win) {
3025                 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
3026                 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
3027                 g_free (text);
3028         }
3029 #endif
3030         modest_msg_edit_window_set_modified (edit_window, FALSE);
3031
3032         /* Frees */
3033         g_free (account_name);
3034         g_object_unref (G_OBJECT (transport_account));
3035         g_object_unref (G_OBJECT (mail_operation));
3036
3037         modest_msg_edit_window_free_msg_data (edit_window, data);
3038
3039         /* ** FIXME **
3040          * If the drafts folder is selected then make the header view
3041          * insensitive while the message is being saved to drafts
3042          * (it'll be sensitive again in on_save_to_drafts_cb()). This
3043          * is not very clean but it avoids letting the drafts folder
3044          * in an inconsistent state: the user could edit the message
3045          * being saved and undesirable things would happen.
3046          * In the average case the user won't notice anything at
3047          * all. In the worst case (the user is editing a really big
3048          * file from Drafts) the header view will be insensitive
3049          * during the saving process (10 or 20 seconds, depending on
3050          * the message). Anyway this is just a quick workaround: once
3051          * we find a better solution it should be removed
3052          * See NB#65125 (commend #18) for details.
3053          */
3054         if (!had_error && win != NULL) {
3055                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
3056                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
3057                 if (view != NULL) {
3058                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
3059                         if (folder) {
3060                                 if (modest_tny_folder_is_local_folder(folder)) {
3061                                         TnyFolderType folder_type;
3062                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
3063                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
3064                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
3065                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3066                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
3067                                         }
3068                                 }
3069                         }
3070                         if (folder != NULL) g_object_unref(folder);
3071                 }
3072         }
3073
3074         return !had_error;
3075 }
3076
3077 /* For instance, when clicking the Send toolbar button when editing a message: */
3078 gboolean
3079 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
3080 {
3081         TnyTransportAccount *transport_account = NULL;
3082         gboolean had_error = FALSE;
3083         MsgData *data;
3084         ModestAccountMgr *account_mgr;
3085         gchar *account_name;
3086         ModestMailOperation *mail_operation;
3087         gchar *recipients;
3088
3089         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
3090
3091         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
3092                 return TRUE;
3093
3094         data = modest_msg_edit_window_get_msg_data (edit_window);
3095
3096         if (data->subject == NULL || data->subject[0] == '\0') {
3097                 /* Empty subject -> no send */
3098                 modest_msg_edit_window_free_msg_data (edit_window, data);
3099                 return FALSE;
3100         }
3101
3102         recipients = g_strconcat (data->to?data->to:"", 
3103                                   data->cc?data->cc:"",
3104                                   data->bcc?data->bcc:"",
3105                                   NULL);
3106         if (recipients == NULL || recipients[0] == '\0') {
3107                 /* Empty subject -> no send */
3108                 g_free (recipients);
3109                 modest_msg_edit_window_free_msg_data (edit_window, data);
3110                 return FALSE;
3111         }
3112         g_free (recipients);
3113
3114         /* Check size */
3115         if (!enough_space_for_message (edit_window, data)) {
3116                 modest_msg_edit_window_free_msg_data (edit_window, data);
3117                 return FALSE;
3118         }
3119
3120         account_mgr = modest_runtime_get_account_mgr();
3121         account_name = g_strdup (data->account_name);
3122         if (!account_name)
3123                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
3124
3125         if (!account_name)
3126                 account_name = modest_account_mgr_get_default_account (account_mgr);
3127
3128         if (!account_name) {
3129                 modest_msg_edit_window_free_msg_data (edit_window, data);
3130                 /* Run account setup wizard */
3131                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
3132                         return TRUE;
3133                 }
3134         }
3135
3136         /* Get the currently-active transport account for this modest account: */
3137         if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
3138                 transport_account =
3139                         TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3140                                               (modest_runtime_get_account_store (),
3141                                                account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
3142         }
3143
3144         if (!transport_account) {
3145                 modest_msg_edit_window_free_msg_data (edit_window, data);
3146                 /* Run account setup wizard */
3147                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
3148                         return TRUE;
3149         }
3150
3151
3152         /* Create the mail operation */
3153         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler, NULL, NULL);
3154         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3155
3156         modest_mail_operation_send_new_mail (mail_operation,
3157                                              transport_account,
3158                                              data->draft_msg,
3159                                              data->from,
3160                                              data->to,
3161                                              data->cc,
3162                                              data->bcc,
3163                                              data->subject,
3164                                              data->plain_body,
3165                                              data->html_body,
3166                                              data->attachments,
3167                                              data->images,
3168                                              data->references,
3169                                              data->in_reply_to,
3170                                              data->priority_flags);
3171
3172         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3173                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
3174
3175         if (modest_mail_operation_get_error (mail_operation) != NULL) {
3176                 const GError *error = modest_mail_operation_get_error (mail_operation);
3177                 if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3178                     error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
3179                         g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
3180                         modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
3181                         had_error = TRUE;
3182                 }
3183         }
3184
3185         /* Free data: */
3186         g_free (account_name);
3187         g_object_unref (G_OBJECT (transport_account));
3188         g_object_unref (G_OBJECT (mail_operation));
3189
3190         modest_msg_edit_window_free_msg_data (edit_window, data);
3191
3192         if (!had_error) {
3193                 modest_msg_edit_window_set_sent (edit_window, TRUE);
3194
3195                 /* Save settings and close the window: */
3196                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
3197         }
3198
3199         return !had_error;
3200 }
3201
3202 void
3203 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
3204                                   ModestMsgEditWindow *window)
3205 {
3206         ModestMsgEditFormatState *format_state = NULL;
3207
3208         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3209         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3210
3211         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3212                 return;
3213
3214         format_state = modest_msg_edit_window_get_format_state (window);
3215         g_return_if_fail (format_state != NULL);
3216
3217         format_state->bold = gtk_toggle_action_get_active (action);
3218         modest_msg_edit_window_set_format_state (window, format_state);
3219         g_free (format_state);
3220
3221 }
3222
3223 void
3224 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
3225                                      ModestMsgEditWindow *window)
3226 {
3227         ModestMsgEditFormatState *format_state = NULL;
3228
3229         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3230         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3231
3232         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3233                 return;
3234
3235         format_state = modest_msg_edit_window_get_format_state (window);
3236         g_return_if_fail (format_state != NULL);
3237
3238         format_state->italics = gtk_toggle_action_get_active (action);
3239         modest_msg_edit_window_set_format_state (window, format_state);
3240         g_free (format_state);
3241
3242 }
3243
3244 void
3245 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
3246                                      ModestMsgEditWindow *window)
3247 {
3248         ModestMsgEditFormatState *format_state = NULL;
3249
3250         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3251         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3252
3253         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3254                 return;
3255
3256         format_state = modest_msg_edit_window_get_format_state (window);
3257         g_return_if_fail (format_state != NULL);
3258
3259         format_state->bullet = gtk_toggle_action_get_active (action);
3260         modest_msg_edit_window_set_format_state (window, format_state);
3261         g_free (format_state);
3262
3263 }
3264
3265 void
3266 modest_ui_actions_on_change_justify (GtkRadioAction *action,
3267                                      GtkRadioAction *selected,
3268                                      ModestMsgEditWindow *window)
3269 {
3270         ModestMsgEditFormatState *format_state = NULL;
3271         GtkJustification value;
3272
3273         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3274
3275         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3276                 return;
3277
3278         value = gtk_radio_action_get_current_value (selected);
3279
3280         format_state = modest_msg_edit_window_get_format_state (window);
3281         g_return_if_fail (format_state != NULL);
3282
3283         format_state->justification = value;
3284         modest_msg_edit_window_set_format_state (window, format_state);
3285         g_free (format_state);
3286 }
3287
3288 void
3289 modest_ui_actions_on_select_editor_color (GtkAction *action,
3290                                           ModestMsgEditWindow *window)
3291 {
3292         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3293         g_return_if_fail (GTK_IS_ACTION (action));
3294
3295         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3296                 return;
3297
3298         modest_msg_edit_window_select_color (window);
3299 }
3300
3301 void
3302 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
3303                                                      ModestMsgEditWindow *window)
3304 {
3305         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3306         g_return_if_fail (GTK_IS_ACTION (action));
3307
3308         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3309                 return;
3310
3311         modest_msg_edit_window_select_background_color (window);
3312 }
3313
3314 void
3315 modest_ui_actions_on_insert_image (GObject *object,
3316                                    ModestMsgEditWindow *window)
3317 {
3318         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3319
3320
3321         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3322                 return;
3323
3324         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3325                 return;
3326
3327         modest_msg_edit_window_insert_image (window);
3328 }
3329
3330 void
3331 modest_ui_actions_on_attach_file (GtkAction *action,
3332                                   ModestMsgEditWindow *window)
3333 {
3334         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3335         g_return_if_fail (GTK_IS_ACTION (action));
3336
3337         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3338                 return;
3339
3340         modest_msg_edit_window_offer_attach_file (window);
3341 }
3342
3343 void
3344 modest_ui_actions_on_remove_attachments (GtkAction *action,
3345                                          ModestMsgEditWindow *window)
3346 {
3347         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3348
3349         modest_msg_edit_window_remove_attachments (window, NULL);
3350 }
3351
3352 static void
3353 do_create_folder_cb (ModestMailOperation *mail_op,
3354                      TnyFolderStore *parent_folder,
3355                      TnyFolder *new_folder,
3356                      gpointer user_data)
3357 {
3358         gchar *suggested_name = (gchar *) user_data;
3359         GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
3360         const GError *error;
3361
3362         error = modest_mail_operation_get_error (mail_op);
3363         if (error) {
3364                 gboolean disk_full;
3365                 TnyAccount *account;
3366                 /* Show an error. If there was some problem writing to
3367                    disk, show it, otherwise show the generic folder
3368                    create error. We do it here and not in an error
3369                    handler because the call to do_create_folder will
3370                    stop the main loop in a gtk_dialog_run and then,
3371                    the message won't be shown until that dialog is
3372                    closed */
3373                 account = modest_mail_operation_get_account (mail_op);
3374                 if (account) {
3375                         disk_full =
3376                                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3377                                                                                 (GtkWidget *) source_win,
3378                                                                                 (GError *) error,
3379                                                                                 account,
3380                                                                                 _("mail_in_ui_folder_create_error_memory"));
3381                         g_object_unref (account);
3382                 }
3383                 if (!disk_full) {
3384                         /* Show an error and try again if there is no
3385                            full memory condition */
3386                         modest_platform_information_banner ((GtkWidget *) source_win, NULL,
3387                                                             _("mail_in_ui_folder_create_error"));
3388                         do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
3389                 }
3390
3391         } else {
3392                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
3393                  * FIXME: any other? */
3394                 GtkWidget *folder_view;
3395
3396                 if (MODEST_IS_MAIN_WINDOW(source_win))
3397                         folder_view =
3398                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
3399                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3400                 else
3401                         folder_view = GTK_WIDGET(g_object_get_data (G_OBJECT (source_win),
3402                                                                     MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
3403
3404                 /* Select the newly created folder. It could happen
3405                    that the widget is no longer there (i.e. the window
3406                    has been destroyed, so we need to check this */
3407                 if (folder_view)
3408                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
3409                                                           new_folder, FALSE);
3410                 g_object_unref (new_folder);
3411         }
3412         /* Free. Note that the first time it'll be NULL so noop */
3413         g_free (suggested_name);
3414         g_object_unref (source_win);
3415 }
3416
3417 typedef struct {
3418         gchar *folder_name;
3419         TnyFolderStore *parent;
3420 } CreateFolderConnect;
3421
3422 static void
3423 do_create_folder_performer (gboolean canceled,
3424                          GError *err,
3425                          GtkWindow *parent_window,
3426                          TnyAccount *account,
3427                          gpointer user_data)
3428 {
3429         CreateFolderConnect *helper = (CreateFolderConnect *) user_data;
3430         ModestMailOperation *mail_op;
3431
3432         if (canceled || err) {
3433                 TnyAccount *account = modest_mail_operation_get_account (mail_op);
3434                 /* In disk full conditions we could get this error here */
3435                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3436                                                                 (GtkWidget *) parent_window, err,
3437                                                                 account,
3438                                                                 _("mail_in_ui_folder_create_error_memory"));
3439                 if (account)
3440                         g_object_unref (account);
3441
3442                 /* This happens if we have selected the outbox folder
3443                    as the parent */
3444                 if (err->code == TNY_SERVICE_ERROR_UNKNOWN &&
3445                     TNY_IS_MERGE_FOLDER (helper->parent)) {
3446                         /* Show an error and retry */
3447                         modest_platform_information_banner ((GtkWidget *) parent_window,
3448                                                             NULL,
3449                                                             _("mail_in_ui_folder_create_error"));
3450
3451                         do_create_folder (parent_window, helper->parent, helper->folder_name);
3452                 }
3453
3454                 goto frees;
3455         }
3456
3457         mail_op  = modest_mail_operation_new ((GObject *) parent_window);
3458         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3459                                          mail_op);
3460         modest_mail_operation_create_folder (mail_op,
3461                                              helper->parent,
3462                                              (const gchar *) helper->folder_name,
3463                                              do_create_folder_cb,
3464                                              g_strdup (helper->folder_name));
3465         g_object_unref (mail_op);
3466
3467  frees:
3468         if (helper->parent)
3469                 g_object_unref (helper->parent);
3470         if (helper->folder_name)
3471                 g_free (helper->folder_name);
3472         g_slice_free (CreateFolderConnect, helper);
3473 }
3474
3475
3476 static void
3477 do_create_folder (GtkWindow *parent_window,
3478                   TnyFolderStore *suggested_parent,
3479                   const gchar *suggested_name)
3480 {
3481         gint result;
3482         gchar *folder_name = NULL;
3483         TnyFolderStore *parent_folder = NULL;
3484
3485         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
3486                                                         suggested_parent,
3487                                                         (gchar *) suggested_name,
3488                                                         &folder_name,
3489                                                         &parent_folder);
3490
3491         if (result == GTK_RESPONSE_ACCEPT && parent_folder) {
3492                 CreateFolderConnect *helper = (CreateFolderConnect *) g_slice_new0 (CreateFolderConnect);
3493                 helper->folder_name = g_strdup (folder_name);
3494                 helper->parent = g_object_ref (parent_folder);
3495
3496                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window),
3497                                                                TRUE,
3498                                                                parent_folder,
3499                                                                do_create_folder_performer,
3500                                                                helper);
3501         }
3502
3503         if (folder_name)
3504                 g_free (folder_name);
3505         if (parent_folder)
3506                 g_object_unref (parent_folder);
3507 }
3508
3509 static void
3510 modest_ui_actions_create_folder(GtkWidget *parent_window,
3511                                 GtkWidget *folder_view,
3512                                 TnyFolderStore *parent_folder)
3513 {
3514         if (!parent_folder) {
3515 #ifdef MODEST_TOOLKIT_HILDON2
3516                 ModestTnyAccountStore *acc_store;
3517
3518                 acc_store = modest_runtime_get_account_store ();
3519
3520                 parent_folder = (TnyFolderStore *)
3521                         modest_tny_account_store_get_local_folders_account (acc_store);
3522 #else
3523                 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3524 #endif
3525         }
3526
3527         if (parent_folder) {
3528                 do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
3529                 g_object_unref (parent_folder);
3530         }
3531 }
3532
3533 void
3534 modest_ui_actions_on_new_folder (GtkAction *action, ModestWindow *window)
3535 {
3536
3537         g_return_if_fail (MODEST_IS_WINDOW(window));
3538
3539         if (MODEST_IS_MAIN_WINDOW (window)) {
3540                 GtkWidget *folder_view;
3541
3542                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3543                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3544                 if (!folder_view)
3545                         return;
3546
3547                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3548 #ifdef MODEST_TOOLKIT_HILDON2
3549         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3550                 GtkWidget *folder_view;
3551
3552                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3553                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3554 #endif
3555         } else {
3556                 g_assert_not_reached ();
3557         }
3558 }
3559
3560 static void
3561 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
3562                                                gpointer user_data)
3563 {
3564         const GError *error = NULL;
3565         gchar *message = NULL;
3566         gboolean mem_full;
3567         TnyAccount *account = modest_mail_operation_get_account (mail_op);
3568
3569         /* Get error message */
3570         error = modest_mail_operation_get_error (mail_op);
3571         if (!error)
3572                 g_return_if_reached ();
3573
3574         mem_full = modest_tny_account_store_is_disk_full_error (modest_runtime_get_account_store(),
3575                                                                 (GError *) error, account);
3576         if (mem_full) {
3577                 message = g_strdup_printf (_KR("cerm_device_memory_full"), "");
3578         } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3579                    error->code == MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS) {
3580                 message = _CS("ckdg_ib_folder_already_exists");
3581         } else if (error->domain == TNY_ERROR_DOMAIN &&
3582                    error->code == TNY_SERVICE_ERROR_STATE) {
3583                 /* This means that the folder is already in use (a
3584                    message is opened for example */
3585                 message = _("emev_ni_internal_error");
3586         } else {
3587                 message = _CS("ckdg_ib_unable_to_rename");
3588         }
3589
3590         /* We don't set a parent for the dialog because the dialog
3591            will be destroyed so the banner won't appear */
3592         modest_platform_information_banner (NULL, NULL, message);
3593
3594         if (account)
3595                 g_object_unref (account);
3596         if (mem_full)
3597                 g_free (message);
3598 }
3599
3600 typedef struct {
3601         TnyFolderStore *folder;
3602         gchar *new_name;
3603 } RenameFolderInfo;
3604
3605 static void
3606 on_rename_folder_cb (ModestMailOperation *mail_op,
3607                      TnyFolder *new_folder,
3608                      gpointer user_data)
3609 {
3610         ModestFolderView *folder_view;
3611
3612         /* If the window was closed when renaming a folder, or if
3613          * it's not a main window this will happen */
3614         if (!MODEST_IS_FOLDER_VIEW (user_data))
3615                 return;
3616
3617         folder_view = MODEST_FOLDER_VIEW (user_data);
3618         /* Note that if the rename fails new_folder will be NULL */
3619         if (new_folder) {
3620                 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
3621         } else {
3622                 modest_folder_view_select_first_inbox_or_local (folder_view);
3623         }
3624         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
3625 }
3626
3627 static void
3628 on_rename_folder_performer (gboolean canceled,
3629                             GError *err,
3630                             GtkWindow *parent_window,
3631                             TnyAccount *account,
3632                             gpointer user_data)
3633 {
3634         ModestMailOperation *mail_op = NULL;
3635         GtkTreeSelection *sel = NULL;
3636         GtkWidget *folder_view = NULL;
3637         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
3638
3639         if (canceled || err) {
3640                 /* In disk full conditions we could get this error here */
3641                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3642                                                                 (GtkWidget *) parent_window, err,
3643                                                                 account, NULL);
3644         } else {
3645
3646                 mail_op =
3647                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3648                                         modest_ui_actions_rename_folder_error_handler,
3649                                         parent_window, NULL);
3650
3651                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3652                                 mail_op);
3653
3654                 if (MODEST_IS_MAIN_WINDOW(parent_window)) {
3655
3656                         folder_view = modest_main_window_get_child_widget (
3657                                 MODEST_MAIN_WINDOW (parent_window),
3658                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3659                 }
3660 #ifdef MODEST_TOOLKIT_HILDON2
3661                 else if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3662                         ModestFolderWindow *folder_window = (ModestFolderWindow *) parent_window;
3663                         folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (folder_window));
3664                 }
3665 #endif
3666
3667                 /* Clear the folders view */
3668                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3669                 gtk_tree_selection_unselect_all (sel);
3670
3671                 /* Actually rename the folder */
3672                 modest_mail_operation_rename_folder (mail_op,
3673                                                      TNY_FOLDER (data->folder),
3674                                                      (const gchar *) (data->new_name),
3675                                                      on_rename_folder_cb,
3676                                                      folder_view);
3677                 g_object_unref (mail_op);
3678         }
3679
3680         g_object_unref (data->folder);
3681         g_free (data->new_name);
3682         g_free (data);
3683 }
3684
3685 void
3686 modest_ui_actions_on_rename_folder (GtkAction *action,
3687                                      ModestWindow *window)
3688 {
3689         modest_ui_actions_on_edit_mode_rename_folder (window);
3690 }
3691
3692 gboolean
3693 modest_ui_actions_on_edit_mode_rename_folder (ModestWindow *window)
3694 {
3695         TnyFolderStore *folder;
3696         GtkWidget *folder_view;
3697         gboolean do_rename = TRUE;
3698
3699         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3700
3701         if (MODEST_IS_MAIN_WINDOW (window)) {
3702                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3703                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3704                 if (!folder_view)
3705                         return FALSE;
3706
3707 #ifdef MODEST_TOOLKIT_HILDON2
3708         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3709                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3710 #endif
3711         } else {
3712                 return FALSE;
3713         }
3714
3715         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3716
3717         if (!folder)
3718                 return FALSE;
3719
3720         if (TNY_IS_FOLDER (folder)) {
3721                 gchar *folder_name = NULL;
3722                 gint response;
3723                 const gchar *current_name;
3724                 TnyFolderStore *parent;
3725
3726                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
3727                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
3728                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (window),
3729                                                                      parent, current_name,
3730                                                                      &folder_name);
3731                 g_object_unref (parent);
3732
3733                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
3734                         do_rename = FALSE;
3735                 } else {
3736                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
3737                         rename_folder_data->folder = g_object_ref (folder);
3738                         rename_folder_data->new_name = folder_name;
3739                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(window), TRUE,
3740                                         folder, on_rename_folder_performer, rename_folder_data);
3741                 }
3742         }
3743         g_object_unref (folder);
3744         return do_rename;
3745 }
3746
3747 static void
3748 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3749                                                gpointer user_data)
3750 {
3751         GObject *win = modest_mail_operation_get_source (mail_op);
3752
3753         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3754                                                &nbs