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