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