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