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