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