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