258d0c970f00b877ce5e075e88f34c8a1b0ef0ce
[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         gchar *from;
2232         gchar *recipient;
2233         gchar *signature;
2234         gboolean use_signature;
2235         TnyMsg *new_msg;
2236         GtkWidget *msg_win;
2237         const gchar *account_name;
2238         const gchar *mailbox;
2239         TnyHeader *msg_header;
2240         ModestWindowMgr *mgr;
2241         TnyMsg *msg;
2242
2243         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW(win));
2244
2245         /* we check for low-mem; in that case, show a warning, and don't allow
2246          * reply/forward (because it could potentially require a lot of memory */
2247         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
2248                 return;
2249
2250         account_name = modest_window_get_active_account (MODEST_WINDOW (win));
2251         mailbox = modest_window_get_active_mailbox (MODEST_WINDOW (win));
2252         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
2253                                                    account_name, mailbox);
2254         recipient = modest_text_utils_get_email_address (from);
2255         signature = modest_account_mgr_get_signature_from_recipient (modest_runtime_get_account_mgr(), 
2256                                                                      recipient, 
2257                                                                      &use_signature);
2258         g_free (recipient);
2259
2260         msg = modest_msg_view_window_get_message(MODEST_MSG_VIEW_WINDOW(win));
2261         g_return_if_fail(msg);
2262
2263         msg_header = tny_msg_get_header (msg);
2264         new_msg =
2265                 modest_tny_msg_create_reply_calendar_msg (msg, msg_header, from,
2266                                                           (use_signature) ? signature : NULL,
2267                                                           header_pairs);
2268         g_object_unref (msg_header);
2269
2270         g_free (from);
2271         g_free (signature);
2272
2273         if (!new_msg) {
2274                 g_warning ("%s: failed to create message\n", __FUNCTION__);
2275                 goto cleanup;
2276         }
2277
2278         msg_win = (GtkWidget *) modest_msg_edit_window_new (new_msg, account_name, mailbox, FALSE);
2279         mgr = modest_runtime_get_window_mgr ();
2280         modest_window_mgr_register_window (mgr, MODEST_WINDOW (msg_win), (ModestWindow *) win);
2281
2282         /* Show edit window */
2283         gtk_widget_show_all (GTK_WIDGET (msg_win));
2284
2285 cleanup:
2286         if (new_msg)
2287                 g_object_unref (G_OBJECT (new_msg));
2288 }
2289
2290 void
2291 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
2292 {
2293         g_return_if_fail (MODEST_IS_WINDOW(win));
2294
2295         reply_forward (ACTION_REPLY, win);
2296 }
2297
2298 void
2299 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
2300 {
2301         g_return_if_fail (MODEST_IS_WINDOW(win));
2302
2303         reply_forward (ACTION_FORWARD, win);
2304 }
2305
2306 void
2307 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
2308 {
2309         g_return_if_fail (MODEST_IS_WINDOW(win));
2310
2311         reply_forward (ACTION_REPLY_TO_ALL, win);
2312 }
2313
2314 void
2315 modest_ui_actions_on_next (GtkAction *action,
2316                            ModestWindow *window)
2317 {
2318         if (MODEST_IS_MAIN_WINDOW (window)) {
2319                 GtkWidget *header_view;
2320
2321                 header_view = modest_main_window_get_child_widget (
2322                                 MODEST_MAIN_WINDOW(window),
2323                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2324                 if (!header_view)
2325                         return;
2326
2327                 modest_header_view_select_next (
2328                                 MODEST_HEADER_VIEW(header_view));
2329         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2330                 modest_msg_view_window_select_next_message (
2331                                 MODEST_MSG_VIEW_WINDOW (window));
2332         } else {
2333                 g_return_if_reached ();
2334         }
2335 }
2336
2337 void
2338 modest_ui_actions_on_prev (GtkAction *action,
2339                            ModestWindow *window)
2340 {
2341         g_return_if_fail (MODEST_IS_WINDOW(window));
2342
2343         if (MODEST_IS_MAIN_WINDOW (window)) {
2344                 GtkWidget *header_view;
2345                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
2346                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2347                 if (!header_view)
2348                         return;
2349
2350                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view));
2351         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2352                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
2353         } else {
2354                 g_return_if_reached ();
2355         }
2356 }
2357
2358 void
2359 modest_ui_actions_on_sort (GtkAction *action,
2360                            ModestWindow *window)
2361 {
2362         GtkWidget *header_view = NULL;
2363
2364         g_return_if_fail (MODEST_IS_WINDOW(window));
2365
2366         if (MODEST_IS_MAIN_WINDOW (window)) {
2367                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
2368                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2369 #ifdef MODEST_TOOLKIT_HILDON2
2370         } else if (MODEST_IS_HEADER_WINDOW (window)) {
2371                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (window)));
2372 #endif
2373         }
2374
2375         if (!header_view) {
2376                 modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
2377
2378                 return;
2379         }
2380
2381         /* Show sorting dialog */
2382         modest_utils_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);
2383 }
2384
2385 static void
2386 sync_folder_cb (ModestMailOperation *mail_op,
2387                 TnyFolder *folder,
2388                 gpointer user_data)
2389 {
2390         ModestHeaderView *header_view = (ModestHeaderView *) user_data;
2391
2392         if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
2393                 ModestWindow *parent = (ModestWindow *) modest_mail_operation_get_source (mail_op);
2394
2395                 /* We must clear first, because otherwise set_folder will ignore */
2396                 /*    the change as the folders are the same */
2397                 modest_header_view_clear (header_view);
2398                 modest_header_view_set_folder (header_view, folder, TRUE, parent, NULL, NULL);
2399
2400                 g_object_unref (parent);
2401         }
2402
2403         g_object_unref (header_view);
2404 }
2405
2406 static gboolean
2407 idle_refresh_folder (gpointer source)
2408 {
2409         ModestHeaderView *header_view = NULL;
2410
2411         /* If the window still exists */
2412         if (!GTK_IS_WIDGET (source) ||
2413             !GTK_WIDGET_VISIBLE (source))
2414                 return FALSE;
2415
2416         /* Refresh the current view */
2417 #ifdef MODEST_TOOLKIT_HILDON2
2418         if (MODEST_IS_HEADER_WINDOW (source))
2419                 header_view = modest_header_window_get_header_view ((ModestHeaderWindow *) source);
2420 #else
2421         if (MODEST_IS_MAIN_WINDOW (source))
2422                 header_view = MODEST_HEADER_VIEW (modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source),
2423                                                                                        MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
2424 #endif
2425         if (header_view) {
2426                 TnyFolder *folder = modest_header_view_get_folder (header_view);
2427                 if (folder) {
2428                         /* Sync the folder status */
2429                         ModestMailOperation *mail_op = modest_mail_operation_new (source);
2430                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
2431                         modest_mail_operation_sync_folder (mail_op, folder, FALSE, sync_folder_cb, g_object_ref (header_view));
2432                         g_object_unref (folder);
2433                         g_object_unref (mail_op);
2434                 }
2435         }
2436
2437         return FALSE;
2438 }
2439
2440 static void
2441 update_account_cb (ModestMailOperation *self,
2442                    TnyList *new_headers,
2443                    gpointer user_data)
2444 {
2445         ModestWindow *top;
2446         gboolean show_visual_notifications;
2447
2448         top = modest_window_mgr_get_current_top (modest_runtime_get_window_mgr ());
2449         show_visual_notifications = (top) ? FALSE : TRUE;
2450
2451         /* Notify new messages have been downloaded. If the
2452            send&receive was invoked by the user then do not show any
2453            visual notification, only play a sound and activate the LED
2454            (for the Maemo version) */
2455         if (TNY_IS_LIST(new_headers) && (tny_list_get_length (new_headers)) > 0) {
2456
2457                 /* We only notify about really new messages (not seen) we get */
2458                 TnyList *actually_new_list;
2459                 TnyIterator *iterator;
2460                 actually_new_list = TNY_LIST (tny_simple_list_new ());
2461                 for (iterator = tny_list_create_iterator (new_headers);
2462                      !tny_iterator_is_done (iterator);
2463                      tny_iterator_next (iterator)) {
2464                         TnyHeader *header;
2465                         TnyHeaderFlags flags;
2466                         header = TNY_HEADER (tny_iterator_get_current (iterator));
2467                         flags = tny_header_get_flags (header);
2468
2469                         if (!(flags & TNY_HEADER_FLAG_SEEN)) {
2470                                 /* Messages are ordered from most
2471                                    recent to oldest. But we want to
2472                                    show notifications starting from
2473                                    the oldest message. That's why we
2474                                    reverse the list */
2475                                 tny_list_prepend (actually_new_list, G_OBJECT (header));
2476                         }
2477                         g_object_unref (header);
2478                 }
2479                 g_object_unref (iterator);
2480
2481                 if (tny_list_get_length (actually_new_list) > 0) {
2482                         GList *new_headers_list = NULL;
2483
2484                         new_headers_list = modest_utils_create_notification_list_from_header_list (actually_new_list);
2485
2486                         /* Send notifications */
2487                         if (new_headers_list) {
2488                                 modest_platform_on_new_headers_received (new_headers_list,
2489                                                                          show_visual_notifications);
2490                                 /* Free the list */
2491                                 modest_utils_free_notification_list (new_headers_list);
2492                         }
2493                 }
2494                 g_object_unref (actually_new_list);
2495         }
2496
2497         if (top) {
2498                 /* Refresh the current folder in an idle. We do this
2499                    in order to avoid refresh cancelations if the
2500                    currently viewed folder is the inbox */
2501                 g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
2502                                  idle_refresh_folder,
2503                                  g_object_ref (top),
2504                                  g_object_unref);
2505         }
2506 }
2507
2508 typedef struct {
2509         TnyAccount *account;
2510         ModestWindow *win;
2511         gchar *account_name;
2512         gboolean poke_status;
2513         gboolean interactive;
2514         ModestMailOperation *mail_op;
2515 } SendReceiveInfo;
2516
2517 static void
2518 do_send_receive_performer (gboolean canceled,
2519                            GError *err,
2520                            GtkWindow *parent_window,
2521                            TnyAccount *account,
2522                            gpointer user_data)
2523 {
2524         SendReceiveInfo *info;
2525
2526         info = (SendReceiveInfo *) user_data;
2527
2528         if (err || canceled) {
2529                 /* In disk full conditions we could get this error here */
2530                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
2531                                                                 (GtkWidget *) parent_window, err,
2532                                                                 account, NULL);
2533
2534                 if (info->mail_op) {
2535                         modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (),
2536                                                             info->mail_op);
2537                 }
2538                 goto clean;
2539         }
2540
2541         /* Set send/receive operation in progress */
2542         if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
2543                 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
2544         }
2545
2546         if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
2547                 g_signal_connect (G_OBJECT (info->mail_op), "operation-finished",
2548                                   G_CALLBACK (on_send_receive_finished),
2549                                   info->win);
2550
2551         /* Send & receive. */
2552         modest_mail_operation_update_account (info->mail_op, info->account_name, info->poke_status, info->interactive,
2553                                               update_account_cb, info->win);
2554
2555  clean:
2556         /* Frees */
2557         if (info->mail_op)
2558                 g_object_unref (G_OBJECT (info->mail_op));
2559         if (info->account_name)
2560                 g_free (info->account_name);
2561         if (info->win)
2562                 g_object_unref (info->win);
2563         if (info->account)
2564                 g_object_unref (info->account);
2565         g_slice_free (SendReceiveInfo, info);
2566 }
2567
2568 /*
2569  * This function performs the send & receive required actions. The
2570  * window is used to create the mail operation. Typically it should
2571  * always be the main window, but we pass it as argument in order to
2572  * be more flexible.
2573  */
2574 void
2575 modest_ui_actions_do_send_receive (const gchar *account_name,
2576                                    gboolean force_connection,
2577                                    gboolean poke_status,
2578                                    gboolean interactive,
2579                                    ModestWindow *win)
2580 {
2581         gchar *acc_name = NULL;
2582         SendReceiveInfo *info;
2583         ModestTnyAccountStore *acc_store;
2584         TnyAccount *account;
2585
2586         /* If no account name was provided then get the current account, and if
2587            there is no current account then pick the default one: */
2588         if (!account_name) {
2589                 if (win)
2590                         acc_name = g_strdup (modest_window_get_active_account (win));
2591                 if (!acc_name)
2592                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
2593                 if (!acc_name) {
2594                         modest_platform_information_banner (NULL, NULL, _("emev_ni_internal_error"));
2595                         return;
2596                 }
2597         } else {
2598                 acc_name = g_strdup (account_name);
2599         }
2600
2601         acc_store = modest_runtime_get_account_store ();
2602         account = modest_tny_account_store_get_server_account (acc_store, acc_name, TNY_ACCOUNT_TYPE_STORE);
2603
2604         if (!account) {
2605                 g_free (acc_name);
2606                 modest_platform_information_banner (NULL, NULL, _("emev_ni_internal_error"));
2607                 return;
2608         }
2609
2610         /* Do not automatically refresh accounts that are flagged as
2611            NO_AUTO_UPDATE. This could be useful for accounts that
2612            handle their own update times */
2613         if (!interactive) {
2614                 ModestProtocolType proto = modest_tny_account_get_protocol_type (account);
2615                 if (proto != MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
2616                         const gchar *tag = MODEST_PROTOCOL_REGISTRY_NO_AUTO_UPDATE_PROTOCOLS;
2617                         ModestProtocolRegistry *registry = modest_runtime_get_protocol_registry ();
2618
2619                         if (modest_protocol_registry_protocol_type_has_tag (registry, proto, tag)) {
2620                                 g_debug ("%s no auto update allowed for account %s", __FUNCTION__, account_name);
2621                                 g_object_unref (account);
2622                                 g_free (acc_name);
2623                                 return;
2624                         }
2625                 }
2626         }
2627
2628         /* Create the info for the connect and perform */
2629         info = g_slice_new (SendReceiveInfo);
2630         info->account_name = acc_name;
2631         info->win = (win) ? g_object_ref (win) : NULL;
2632         info->poke_status = poke_status;
2633         info->interactive = interactive;
2634         info->account = account;
2635         /* We need to create the operation here, because otherwise it
2636            could happen that the queue emits the queue-empty signal
2637            while we're trying to connect the account */
2638         info->mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
2639                                                                        modest_ui_actions_disk_operations_error_handler,
2640                                                                        NULL, NULL);
2641         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), info->mail_op);
2642
2643         /* Invoke the connect and perform */
2644         modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL,
2645                                              force_connection, info->account,
2646                                              do_send_receive_performer, info);
2647 }
2648
2649
2650 static void
2651 modest_ui_actions_do_cancel_send (const gchar *account_name,
2652                                   ModestWindow *win)
2653 {
2654         TnyTransportAccount *transport_account;
2655         TnySendQueue *send_queue = NULL;
2656         GError *error = NULL;
2657
2658         /* Get transport account */
2659         transport_account =
2660                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2661                                       (modest_runtime_get_account_store(),
2662                                        account_name,
2663                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2664         if (!transport_account) {
2665                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2666                 goto frees;
2667         }
2668
2669         /* Get send queue*/
2670         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account, TRUE));
2671         if (!TNY_IS_SEND_QUEUE(send_queue)) {
2672                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
2673                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2674                              "modest: could not find send queue for account\n");
2675         } else {
2676                 /* Cancel the current send */
2677                 tny_account_cancel (TNY_ACCOUNT (transport_account));
2678
2679                 /* Suspend all pending messages */
2680                 tny_send_queue_cancel (send_queue, TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, &error);
2681         }
2682
2683  frees:
2684         if (transport_account != NULL)
2685                 g_object_unref (G_OBJECT (transport_account));
2686 }
2687
2688 static void
2689 modest_ui_actions_cancel_send_all (ModestWindow *win)
2690 {
2691         GSList *account_names, *iter;
2692
2693         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2694                                                           TRUE);
2695
2696         iter = account_names;
2697         while (iter) {
2698                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
2699                 iter = g_slist_next (iter);
2700         }
2701
2702         modest_account_mgr_free_account_names (account_names);
2703         account_names = NULL;
2704 }
2705
2706 void
2707 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
2708
2709 {
2710         /* Check if accounts exist */
2711         gboolean accounts_exist =
2712                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2713
2714         /* If not, allow the user to create an account before trying to send/receive. */
2715         if (!accounts_exist)
2716                 modest_ui_actions_on_accounts (NULL, win);
2717
2718         /* Cancel all sending operaitons */
2719         modest_ui_actions_cancel_send_all (win);
2720 }
2721
2722 /*
2723  * Refreshes all accounts. This function will be used by automatic
2724  * updates
2725  */
2726 void
2727 modest_ui_actions_do_send_receive_all (ModestWindow *win,
2728                                        gboolean force_connection,
2729                                        gboolean poke_status,
2730                                        gboolean interactive)
2731 {
2732         GSList *account_names, *iter;
2733
2734         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
2735                                                           TRUE);
2736
2737         iter = account_names;
2738         while (iter) {
2739                 modest_ui_actions_do_send_receive ((const char*) iter->data,
2740                                                    force_connection,
2741                                                    poke_status, interactive, win);
2742                 iter = g_slist_next (iter);
2743         }
2744
2745         modest_account_mgr_free_account_names (account_names);
2746         account_names = NULL;
2747 }
2748
2749 /*
2750  * Handler of the click on Send&Receive button in the main toolbar
2751  */
2752 void
2753 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
2754 {
2755         /* Check if accounts exist */
2756         gboolean accounts_exist;
2757
2758         accounts_exist =
2759                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2760
2761         /* If not, allow the user to create an account before trying to send/receive. */
2762         if (!accounts_exist)
2763                 modest_ui_actions_on_accounts (NULL, win);
2764
2765         /* Refresh the current folder. The if is always TRUE it's just an extra check */
2766         if (MODEST_IS_MAIN_WINDOW (win)) {
2767                 GtkWidget *folder_view;
2768                 TnyFolderStore *folder_store;
2769
2770                 folder_view =
2771                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2772                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2773                 if (!folder_view)
2774                         return;
2775
2776                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2777
2778                 if (folder_store)
2779                         g_object_unref (folder_store);
2780                 /* Refresh the active account. Force the connection if needed
2781                    and poke the status of all folders */
2782                 modest_ui_actions_do_send_receive (NULL, TRUE, TRUE, TRUE, win);
2783 #ifdef MODEST_TOOLKIT_HILDON2
2784         } else if (MODEST_IS_ACCOUNTS_WINDOW (win)) {
2785                 modest_ui_actions_do_send_receive_all (win, TRUE, TRUE, TRUE);
2786 #endif
2787         } else {
2788                 const gchar *active_account;
2789                 active_account = modest_window_get_active_account (MODEST_WINDOW (win));
2790
2791                 modest_ui_actions_do_send_receive (active_account, TRUE, TRUE, TRUE, win);
2792         }
2793
2794 }
2795
2796
2797 void
2798 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
2799 {
2800         ModestConf *conf;
2801         GtkWidget *header_view;
2802
2803         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2804
2805         header_view = modest_main_window_get_child_widget (main_window,
2806                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2807         if (!header_view)
2808                 return;
2809
2810         conf = modest_runtime_get_conf ();
2811
2812         /* what is saved/restored is depending on the style; thus; we save with
2813          * old style, then update the style, and restore for this new style
2814          */
2815         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
2816
2817         if (modest_header_view_get_style
2818             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
2819                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2820                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
2821         else
2822                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2823                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
2824
2825         modest_widget_memory_restore (conf, G_OBJECT(header_view),
2826                                       MODEST_CONF_HEADER_VIEW_KEY);
2827 }
2828
2829
2830 void
2831 modest_ui_actions_on_header_selected (ModestHeaderView *header_view,
2832                                       TnyHeader *header,
2833                                       ModestMainWindow *main_window)
2834 {
2835         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2836         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2837
2838         /* in the case the folder is empty, show the empty folder message and focus
2839          * folder view */
2840         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
2841                 if (modest_header_view_is_empty (header_view)) {
2842                         TnyFolder *folder = modest_header_view_get_folder (header_view);
2843                         GtkWidget *folder_view =
2844                                 modest_main_window_get_child_widget (main_window,
2845                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2846                         if (folder != NULL) {
2847                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
2848                                 g_object_unref (folder);
2849                         }
2850                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
2851                         return;
2852                 }
2853         }
2854         /* If no header has been selected then exit */
2855         if (!header)
2856                 return;
2857
2858         /* Update focus */
2859         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
2860             gtk_widget_grab_focus (GTK_WIDGET(header_view));
2861
2862         /* Update toolbar dimming state */
2863         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2864         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2865 }
2866
2867 void
2868 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
2869                                        TnyHeader *header,
2870                                        GtkTreePath *path,
2871                                        ModestWindow *window)
2872 {
2873         GtkWidget *open_widget;
2874         GtkTreeRowReference *rowref;
2875
2876         g_return_if_fail (MODEST_IS_WINDOW(window));
2877         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2878         g_return_if_fail (TNY_IS_HEADER (header));
2879
2880         if (modest_header_view_count_selected_headers (header_view) > 1) {
2881                 /* Don't allow activation if there are more than one message selected */
2882                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
2883                 return;
2884         }
2885
2886         /* we check for low-mem; in that case, show a warning, and don't allow
2887          * activating headers
2888          */
2889         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
2890                 return;
2891
2892         if (MODEST_IS_MAIN_WINDOW (window)) {
2893                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
2894                 open_widget = modest_window_get_action_widget (MODEST_WINDOW (window), "/MenuBar/EmailMenu/EmailOpenMenu");
2895                 if (!GTK_WIDGET_IS_SENSITIVE (open_widget))
2896                         return;
2897         }
2898
2899         rowref = gtk_tree_row_reference_new (gtk_tree_view_get_model (GTK_TREE_VIEW (header_view)), path);
2900         open_msg_from_header (header, rowref, MODEST_WINDOW (window));
2901         gtk_tree_row_reference_free (rowref);
2902 }
2903
2904 static void
2905 set_active_account_from_tny_account (TnyAccount *account,
2906                                      ModestWindow *window)
2907 {
2908         const gchar *server_acc_name = tny_account_get_id (account);
2909
2910         /* We need the TnyAccount provided by the
2911            account store because that is the one that
2912            knows the name of the Modest account */
2913         TnyAccount *modest_server_account =
2914                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2915                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID,
2916                                                              server_acc_name);
2917         if (!modest_server_account) {
2918                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2919                 return;
2920         }
2921
2922         /* Update active account, but only if it's not a pseudo-account */
2923         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2924             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2925                 const gchar *modest_acc_name =
2926                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2927                 if (modest_acc_name)
2928                         modest_window_set_active_account (window, modest_acc_name);
2929         }
2930
2931         g_object_unref (modest_server_account);
2932 }
2933
2934
2935 static void
2936 folder_refreshed_cb (ModestMailOperation *mail_op,
2937                      TnyFolder *folder,
2938                      gpointer user_data)
2939 {
2940         ModestMainWindow *win = NULL;
2941         GtkWidget *folder_view, *header_view;
2942         const GError *error;
2943
2944         g_return_if_fail (TNY_IS_FOLDER (folder));
2945
2946         win = MODEST_MAIN_WINDOW (user_data);
2947
2948         /* Check if the operation failed due to memory low conditions */
2949         error = modest_mail_operation_get_error (mail_op);
2950         if (error && error->domain == MODEST_MAIL_OPERATION_ERROR &&
2951             error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
2952                 modest_platform_run_information_dialog (GTK_WINDOW (win),
2953                                                         _KR("memr_ib_operation_disabled"),
2954                                                         TRUE);
2955                 return;
2956         }
2957
2958         folder_view =
2959                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2960         header_view =
2961                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2962
2963         if (folder_view) {
2964                 TnyFolderStore *current_folder;
2965
2966                 current_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2967                 if (current_folder) {
2968                         gboolean different = ((TnyFolderStore *) folder != current_folder);
2969                         g_object_unref (current_folder);
2970                         if (different)
2971                                 return;
2972                 }
2973         }
2974
2975         /* Check if folder is empty and set headers view contents style */
2976         if ((tny_folder_get_all_count (folder) == 0) ||
2977             modest_header_view_is_empty (MODEST_HEADER_VIEW (header_view)))
2978                 modest_main_window_set_contents_style (win,
2979                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2980 }
2981
2982 void
2983 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2984                                                TnyFolderStore *folder_store,
2985                                                gboolean selected,
2986                                                ModestMainWindow *main_window)
2987 {
2988         GtkWidget *header_view;
2989
2990         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2991
2992         header_view = modest_main_window_get_child_widget(main_window,
2993                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2994         if (!header_view)
2995                 return;
2996
2997
2998         if (TNY_IS_ACCOUNT (folder_store)) {
2999                 if (selected) {
3000                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
3001
3002                         /* Show account details */
3003                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
3004                 }
3005         } else {
3006                 if (TNY_IS_FOLDER (folder_store) && selected) {
3007                         TnyAccount *account;
3008
3009                         /* Update the active account */
3010                         account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
3011                         if (account) {
3012                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
3013                                 g_object_unref (account);
3014                                 account = NULL;
3015                         }
3016
3017                         /* Set the header style by default, it could
3018                            be changed later by the refresh callback to
3019                            empty */
3020                         modest_main_window_set_contents_style (main_window,
3021                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
3022
3023                         /* Set folder on header view. This function
3024                            will call tny_folder_refresh_async so we
3025                            pass a callback that will be called when
3026                            finished. We use that callback to set the
3027                            empty view if there are no messages */
3028                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
3029                                                        TNY_FOLDER (folder_store),
3030                                                        TRUE,
3031                                                        MODEST_WINDOW (main_window),
3032                                                        folder_refreshed_cb,
3033                                                        main_window);
3034
3035                         /* Restore configuration. We need to do this
3036                            *after* the set_folder because the widget
3037                            memory asks the header view about its
3038                            folder  */
3039                         modest_widget_memory_restore (modest_runtime_get_conf (),
3040                                                       G_OBJECT(header_view),
3041                                                       MODEST_CONF_HEADER_VIEW_KEY);
3042                 } else {
3043                         /* No need to save the header view
3044                            configuration for Maemo because it only
3045                            saves the sorting stuff and that it's
3046                            already being done by the sort
3047                            dialog. Remove it when the GNOME version
3048                            has the same behaviour */
3049 #ifdef MODEST_TOOLKIT_GTK
3050                         if (modest_main_window_get_contents_style (main_window) ==
3051                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
3052                                 modest_widget_memory_save (modest_runtime_get_conf (), 
3053                                                            G_OBJECT (header_view),
3054                                                            MODEST_CONF_HEADER_VIEW_KEY);
3055 #endif
3056                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
3057                 }
3058         }
3059
3060         /* Update dimming state */
3061         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
3062         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
3063 }
3064
3065 void
3066 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
3067                                      ModestWindow *win)
3068 {
3069         GtkWidget *dialog;
3070         gchar *txt, *item;
3071         gboolean online;
3072
3073         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
3074
3075         online = tny_device_is_online (modest_runtime_get_device());
3076
3077         if (online) {
3078                 /* already online -- the item is simply not there... */
3079                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
3080                                                  GTK_DIALOG_MODAL,
3081                                                  GTK_MESSAGE_WARNING,
3082                                                  GTK_BUTTONS_NONE,
3083                                                  _("The %s you selected cannot be found"),
3084                                                  item);
3085                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
3086                 gtk_dialog_run (GTK_DIALOG(dialog));
3087         } else {
3088                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
3089                                                       GTK_WINDOW (win),
3090                                                       GTK_DIALOG_MODAL,
3091                                                       _("mcen_bd_dialog_cancel"),
3092                                                       GTK_RESPONSE_REJECT,
3093                                                       _("mcen_bd_dialog_ok"),
3094                                                       GTK_RESPONSE_ACCEPT,
3095                                                       NULL);
3096                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
3097                                          "Do you want to get online?"), item);
3098                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox),
3099                                     gtk_label_new (txt), FALSE, FALSE, 0);
3100                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3101                 g_free (txt);
3102
3103                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
3104                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
3105                         /* TODO: Comment about why is this commented out: */
3106                         /* modest_platform_connect_and_wait (); */
3107                 }
3108         }
3109         gtk_widget_destroy (dialog);
3110 }
3111
3112 void
3113 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
3114                                      ModestWindow *win)
3115 {
3116         /* g_debug ("%s %s", __FUNCTION__, link); */
3117 }
3118
3119
3120 void
3121 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
3122                                         ModestWindow *win)
3123 {
3124         modest_platform_activate_uri (link);
3125 }
3126
3127 void
3128 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
3129                                           ModestWindow *win)
3130 {
3131         modest_platform_show_uri_popup (link);
3132 }
3133
3134 void
3135 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
3136                                              ModestWindow *win)
3137 {
3138         /* we check for low-mem; in that case, show a warning, and don't allow
3139          * viewing attachments
3140          */
3141         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
3142                 return;
3143
3144         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
3145 }
3146
3147 void
3148 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
3149                                           const gchar *address,
3150                                           ModestWindow *win)
3151 {
3152         /* g_debug ("%s %s", __FUNCTION__, address); */
3153 }
3154
3155 static void
3156 on_save_to_drafts_cb (ModestMailOperation *mail_op,
3157                       TnyMsg *saved_draft,
3158                       gpointer user_data)
3159 {
3160         ModestMsgEditWindow *edit_window;
3161
3162         /* TODO: in hildon 2 we have to dim and undim the header views while we're saving */
3163 #ifndef MODEST_TOOLKIT_HILDON2
3164         ModestMainWindow *win;
3165
3166         /* FIXME. Make the header view sensitive again. This is a
3167          * temporary hack. See modest_ui_actions_on_save_to_drafts()
3168          * for details */
3169         win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
3170                                          modest_runtime_get_window_mgr(), FALSE));
3171         if (win != NULL) {
3172                 GtkWidget *hdrview = modest_main_window_get_child_widget(
3173                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3174                 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
3175         }
3176 #endif
3177
3178         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
3179
3180         /* Set draft is there was no error */
3181         if (!modest_mail_operation_get_error (mail_op))
3182                 modest_msg_edit_window_set_draft (edit_window, saved_draft);
3183
3184         g_object_unref(edit_window);
3185 }
3186
3187 static gboolean
3188 enough_space_for_message (ModestMsgEditWindow *edit_window,
3189                           MsgData *data)
3190 {
3191         guint64 available_disk, expected_size;
3192         gint parts_count;
3193         guint64 parts_size;
3194
3195         /* Check size */
3196         available_disk = modest_utils_get_available_space (NULL);
3197         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
3198         expected_size = modest_tny_msg_estimate_size (data->plain_body,
3199                                                       data->html_body,
3200                                                       parts_count,
3201                                                       parts_size);
3202
3203         /* Double check: disk full condition or message too big */
3204         if (available_disk < MODEST_TNY_ACCOUNT_STORE_MIN_FREE_SPACE ||
3205             expected_size > available_disk) {
3206                 gchar *msg = g_strdup_printf (_KR("cerm_device_memory_full"), "");
3207                 modest_platform_information_banner (NULL, NULL, msg);
3208                 g_free (msg);
3209
3210                 return FALSE;
3211         }
3212
3213         /*
3214          * djcb: if we're in low-memory state, we only allow for
3215          * saving messages smaller than
3216          * MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h) this
3217          * should still allow for sending anything critical...
3218          */
3219         if ((expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) &&
3220             modest_platform_check_memory_low (MODEST_WINDOW(edit_window), TRUE))
3221                 return FALSE;
3222
3223         /*
3224          * djcb: we also make sure that the attachments are smaller than the max size
3225          * this is for the case where we'd try to forward a message with attachments
3226          * bigger than our max allowed size, or sending an message from drafts which
3227          * somehow got past our checks when attaching.
3228          */
3229         if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
3230                 modest_platform_run_information_dialog (
3231                         GTK_WINDOW(edit_window),
3232                         _("mail_ib_error_attachment_size"),
3233                         TRUE);
3234                 return FALSE;
3235         }
3236
3237         return TRUE;
3238 }
3239
3240 gboolean
3241 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
3242 {
3243         TnyTransportAccount *transport_account;
3244         ModestMailOperation *mail_operation;
3245         MsgData *data;
3246         gchar *account_name;
3247         ModestAccountMgr *account_mgr;
3248         gboolean had_error = FALSE;
3249         ModestMainWindow *win = NULL;
3250
3251         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
3252
3253         data = modest_msg_edit_window_get_msg_data (edit_window);
3254
3255         /* Check size */
3256         if (!enough_space_for_message (edit_window, data)) {
3257                 modest_msg_edit_window_free_msg_data (edit_window, data);
3258                 return FALSE;
3259         }
3260
3261         account_name = g_strdup (data->account_name);
3262         account_mgr = modest_runtime_get_account_mgr();
3263         if (!account_name)
3264                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
3265         if (!account_name)
3266                 account_name = modest_account_mgr_get_default_account (account_mgr);
3267         if (!account_name) {
3268                 g_printerr ("modest: no account found\n");
3269                 modest_msg_edit_window_free_msg_data (edit_window, data);
3270                 return FALSE;
3271         }
3272
3273         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
3274                 account_name = g_strdup (data->account_name);
3275         }
3276
3277         transport_account =
3278                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3279                                       (modest_runtime_get_account_store (),
3280                                        account_name,
3281                                        TNY_ACCOUNT_TYPE_TRANSPORT));
3282         if (!transport_account) {
3283                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
3284                 g_free (account_name);
3285                 modest_msg_edit_window_free_msg_data (edit_window, data);
3286                 return FALSE;
3287         }
3288
3289         /* Create the mail operation */
3290         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler,
3291                                                                         NULL, NULL);
3292         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3293
3294         modest_mail_operation_save_to_drafts (mail_operation,
3295                                               transport_account,
3296                                               data->draft_msg,
3297                                               data->from,
3298                                               data->to, 
3299                                               data->cc, 
3300                                               data->bcc,
3301                                               data->subject,
3302                                               data->plain_body,
3303                                               data->html_body,
3304                                               data->attachments,
3305                                               data->images,
3306                                               data->priority_flags,
3307                                               data->references,
3308                                               data->in_reply_to,
3309                                               data->custom_header_pairs,
3310                                               on_save_to_drafts_cb,
3311                                               g_object_ref(edit_window));
3312
3313 #ifdef MODEST_TOOLKIT_HILDON2
3314         /* In hildon2 we always show the information banner on saving to drafts.
3315          * It will be a system information banner in this case.
3316          */
3317         gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
3318         modest_platform_information_banner (NULL, NULL, text);
3319         g_free (text);
3320 #else
3321         /* Use the main window as the parent of the banner, if the
3322            main window does not exist it won't be shown, if the parent
3323            window exists then it's properly shown. We don't use the
3324            editor window because it could be closed (save to drafts
3325            could happen after closing the window */
3326         win = (ModestMainWindow *)
3327                 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
3328         if (win) {
3329                 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
3330                 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
3331                 g_free (text);
3332         }
3333 #endif
3334         modest_msg_edit_window_set_modified (edit_window, FALSE);
3335
3336         /* Frees */
3337         g_free (account_name);
3338         g_object_unref (G_OBJECT (transport_account));
3339         g_object_unref (G_OBJECT (mail_operation));
3340
3341         modest_msg_edit_window_free_msg_data (edit_window, data);
3342
3343         /* ** FIXME **
3344          * If the drafts folder is selected then make the header view
3345          * insensitive while the message is being saved to drafts
3346          * (it'll be sensitive again in on_save_to_drafts_cb()). This
3347          * is not very clean but it avoids letting the drafts folder
3348          * in an inconsistent state: the user could edit the message
3349          * being saved and undesirable things would happen.
3350          * In the average case the user won't notice anything at
3351          * all. In the worst case (the user is editing a really big
3352          * file from Drafts) the header view will be insensitive
3353          * during the saving process (10 or 20 seconds, depending on
3354          * the message). Anyway this is just a quick workaround: once
3355          * we find a better solution it should be removed
3356          * See NB#65125 (commend #18) for details.
3357          */
3358         if (!had_error && win != NULL) {
3359                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
3360                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
3361                 if (view != NULL) {
3362                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
3363                         if (folder) {
3364                                 if (modest_tny_folder_is_local_folder(folder)) {
3365                                         TnyFolderType folder_type;
3366                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
3367                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
3368                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
3369                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3370                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
3371                                         }
3372                                 }
3373                         }
3374                         if (folder != NULL) g_object_unref(folder);
3375                 }
3376         }
3377
3378         return !had_error;
3379 }
3380
3381 /* For instance, when clicking the Send toolbar button when editing a message: */
3382 gboolean
3383 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
3384 {
3385         TnyTransportAccount *transport_account = NULL;
3386         gboolean had_error = FALSE, add_to_contacts;
3387         MsgData *data;
3388         ModestAccountMgr *account_mgr;
3389         gchar *account_name;
3390         ModestMailOperation *mail_operation;
3391         gchar *recipients;
3392
3393         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
3394
3395         /* Check whether to automatically add new contacts to addressbook or not */
3396         add_to_contacts = modest_conf_get_bool (modest_runtime_get_conf (),
3397                                                 MODEST_CONF_AUTO_ADD_TO_CONTACTS, NULL);
3398         if (!modest_msg_edit_window_check_names (edit_window, add_to_contacts))
3399                 return TRUE;
3400
3401         data = modest_msg_edit_window_get_msg_data (edit_window);
3402
3403         recipients = g_strconcat (data->to?data->to:"", 
3404                                   data->cc?data->cc:"",
3405                                   data->bcc?data->bcc:"",
3406                                   NULL);
3407         if (recipients == NULL || recipients[0] == '\0') {
3408                 /* Empty subject -> no send */
3409                 g_free (recipients);
3410                 modest_msg_edit_window_free_msg_data (edit_window, data);
3411                 return FALSE;
3412         }
3413         g_free (recipients);
3414
3415         /* Check size */
3416         if (!enough_space_for_message (edit_window, data)) {
3417                 modest_msg_edit_window_free_msg_data (edit_window, data);
3418                 return FALSE;
3419         }
3420
3421         account_mgr = modest_runtime_get_account_mgr();
3422         account_name = g_strdup (data->account_name);
3423         if (!account_name)
3424                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
3425
3426         if (!account_name)
3427                 account_name = modest_account_mgr_get_default_account (account_mgr);
3428
3429         if (!account_name) {
3430                 modest_msg_edit_window_free_msg_data (edit_window, data);
3431                 /* Run account setup wizard */
3432                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
3433                         return TRUE;
3434                 }
3435         }
3436
3437         /* Get the currently-active transport account for this modest account: */
3438         if (account_name && strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
3439                 transport_account =
3440                         TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
3441                                               (modest_runtime_get_account_store (),
3442                                                account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
3443         }
3444
3445         if (!transport_account) {
3446                 modest_msg_edit_window_free_msg_data (edit_window, data);
3447                 /* Run account setup wizard */
3448                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
3449                         return TRUE;
3450         }
3451
3452
3453         /* Create the mail operation */
3454         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler, NULL, NULL);
3455         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
3456
3457         modest_mail_operation_send_new_mail (mail_operation,
3458                                              transport_account,
3459                                              data->draft_msg,
3460                                              data->from,
3461                                              data->to,
3462                                              data->cc,
3463                                              data->bcc,
3464                                              data->subject,
3465                                              data->plain_body,
3466                                              data->html_body,
3467                                              data->attachments,
3468                                              data->images,
3469                                              data->references,
3470                                              data->in_reply_to,
3471                                              data->priority_flags,
3472                                              data->custom_header_pairs);
3473
3474         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3475                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
3476
3477         if (modest_mail_operation_get_error (mail_operation) != NULL) {
3478                 const GError *error = modest_mail_operation_get_error (mail_operation);
3479                 if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3480                     error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
3481                         g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
3482                         modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
3483                         had_error = TRUE;
3484                 }
3485         }
3486
3487         /* Free data: */
3488         g_free (account_name);
3489         g_object_unref (G_OBJECT (transport_account));
3490         g_object_unref (G_OBJECT (mail_operation));
3491
3492         modest_msg_edit_window_free_msg_data (edit_window, data);
3493
3494         if (!had_error) {
3495                 modest_msg_edit_window_set_sent (edit_window, TRUE);
3496
3497                 /* Save settings and close the window: */
3498                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
3499         }
3500
3501         return !had_error;
3502 }
3503
3504 void
3505 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
3506                                   ModestMsgEditWindow *window)
3507 {
3508         ModestMsgEditFormatState *format_state = NULL;
3509
3510         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3511         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3512
3513         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3514                 return;
3515
3516         format_state = modest_msg_edit_window_get_format_state (window);
3517         g_return_if_fail (format_state != NULL);
3518
3519         format_state->bold = gtk_toggle_action_get_active (action);
3520         modest_msg_edit_window_set_format_state (window, format_state);
3521         g_free (format_state);
3522
3523 }
3524
3525 void
3526 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
3527                                      ModestMsgEditWindow *window)
3528 {
3529         ModestMsgEditFormatState *format_state = NULL;
3530
3531         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3532         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3533
3534         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3535                 return;
3536
3537         format_state = modest_msg_edit_window_get_format_state (window);
3538         g_return_if_fail (format_state != NULL);
3539
3540         format_state->italics = gtk_toggle_action_get_active (action);
3541         modest_msg_edit_window_set_format_state (window, format_state);
3542         g_free (format_state);
3543
3544 }
3545
3546 void
3547 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
3548                                      ModestMsgEditWindow *window)
3549 {
3550         ModestMsgEditFormatState *format_state = NULL;
3551
3552         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3553         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
3554
3555         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3556                 return;
3557
3558         format_state = modest_msg_edit_window_get_format_state (window);
3559         g_return_if_fail (format_state != NULL);
3560
3561         format_state->bullet = gtk_toggle_action_get_active (action);
3562         modest_msg_edit_window_set_format_state (window, format_state);
3563         g_free (format_state);
3564
3565 }
3566
3567 void
3568 modest_ui_actions_on_change_justify (GtkRadioAction *action,
3569                                      GtkRadioAction *selected,
3570                                      ModestMsgEditWindow *window)
3571 {
3572         ModestMsgEditFormatState *format_state = NULL;
3573         GtkJustification value;
3574
3575         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3576
3577         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3578                 return;
3579
3580         value = gtk_radio_action_get_current_value (selected);
3581
3582         format_state = modest_msg_edit_window_get_format_state (window);
3583         g_return_if_fail (format_state != NULL);
3584
3585         format_state->justification = value;
3586         modest_msg_edit_window_set_format_state (window, format_state);
3587         g_free (format_state);
3588 }
3589
3590 void
3591 modest_ui_actions_on_select_editor_color (GtkAction *action,
3592                                           ModestMsgEditWindow *window)
3593 {
3594         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3595         g_return_if_fail (GTK_IS_ACTION (action));
3596
3597         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3598                 return;
3599
3600         modest_msg_edit_window_select_color (window);
3601 }
3602
3603 void
3604 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
3605                                                      ModestMsgEditWindow *window)
3606 {
3607         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3608         g_return_if_fail (GTK_IS_ACTION (action));
3609
3610         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3611                 return;
3612
3613         modest_msg_edit_window_select_background_color (window);
3614 }
3615
3616 void
3617 modest_ui_actions_on_insert_image (GObject *object,
3618                                    ModestMsgEditWindow *window)
3619 {
3620         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3621
3622
3623         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3624                 return;
3625
3626         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3627                 return;
3628
3629         modest_msg_edit_window_insert_image (window);
3630 }
3631
3632 void
3633 modest_ui_actions_on_attach_file (GtkAction *action,
3634                                   ModestMsgEditWindow *window)
3635 {
3636         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3637         g_return_if_fail (GTK_IS_ACTION (action));
3638
3639         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3640                 return;
3641
3642         modest_msg_edit_window_offer_attach_file (window);
3643 }
3644
3645 void
3646 modest_ui_actions_on_remove_attachments (GtkAction *action,
3647                                          ModestMsgEditWindow *window)
3648 {
3649         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3650
3651         modest_msg_edit_window_remove_attachments (window, NULL);
3652 }
3653
3654 static void
3655 do_create_folder_cb (ModestMailOperation *mail_op,
3656                      TnyFolderStore *parent_folder,
3657                      TnyFolder *new_folder,
3658                      gpointer user_data)
3659 {
3660         gchar *suggested_name = (gchar *) user_data;
3661         GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
3662         const GError *error;
3663
3664         error = modest_mail_operation_get_error (mail_op);
3665         if (error) {
3666                 gboolean disk_full = FALSE;
3667                 TnyAccount *account;
3668                 /* Show an error. If there was some problem writing to
3669                    disk, show it, otherwise show the generic folder
3670                    create error. We do it here and not in an error
3671                    handler because the call to do_create_folder will
3672                    stop the main loop in a gtk_dialog_run and then,
3673                    the message won't be shown until that dialog is
3674                    closed */
3675                 account = modest_mail_operation_get_account (mail_op);
3676                 if (account) {
3677                         disk_full =
3678                                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3679                                                                                 (GtkWidget *) source_win,
3680                                                                                 (GError *) error,
3681                                                                                 account,
3682                                                                                 _("mail_in_ui_folder_create_error_memory"));
3683                         g_object_unref (account);
3684                 }
3685                 if (!disk_full) {
3686                         /* Show an error and try again if there is no
3687                            full memory condition */
3688                         modest_platform_information_banner ((GtkWidget *) source_win, NULL,
3689                                                             _("mail_in_ui_folder_create_error"));
3690                         do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
3691                 }
3692
3693         } else {
3694                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
3695                  * FIXME: any other? */
3696                 GtkWidget *folder_view;
3697
3698                 if (MODEST_IS_MAIN_WINDOW(source_win))
3699                         folder_view =
3700                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
3701                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3702                 else
3703                         folder_view = GTK_WIDGET(g_object_get_data (G_OBJECT (source_win),
3704                                                                     MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
3705
3706                 /* Select the newly created folder. It could happen
3707                    that the widget is no longer there (i.e. the window
3708                    has been destroyed, so we need to check this */
3709                 if (folder_view)
3710                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
3711                                                           new_folder, FALSE);
3712                 g_object_unref (new_folder);
3713         }
3714         /* Free. Note that the first time it'll be NULL so noop */
3715         g_free (suggested_name);
3716         g_object_unref (source_win);
3717 }
3718
3719 typedef struct {
3720         gchar *folder_name;
3721         TnyFolderStore *parent;
3722 } CreateFolderConnect;
3723
3724 static void
3725 do_create_folder_performer (gboolean canceled,
3726                          GError *err,
3727                          GtkWindow *parent_window,
3728                          TnyAccount *account,
3729                          gpointer user_data)
3730 {
3731         CreateFolderConnect *helper = (CreateFolderConnect *) user_data;
3732         ModestMailOperation *mail_op;
3733
3734         if (canceled || err) {
3735                 /* In disk full conditions we could get this error here */
3736                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3737                                                                 (GtkWidget *) parent_window, err,
3738                                                                 NULL, _("mail_in_ui_folder_create_error_memory"));
3739
3740                 /* This happens if we have selected the outbox folder
3741                    as the parent */
3742                 if (err && err->code == TNY_SERVICE_ERROR_UNKNOWN &&
3743                     TNY_IS_MERGE_FOLDER (helper->parent)) {
3744                         /* Show an error and retry */
3745                         modest_platform_information_banner ((GtkWidget *) parent_window,
3746                                                             NULL,
3747                                                             _("mail_in_ui_folder_create_error"));
3748
3749                         do_create_folder (parent_window, helper->parent, helper->folder_name);
3750                 }
3751
3752                 goto frees;
3753         }
3754
3755         mail_op  = modest_mail_operation_new ((GObject *) parent_window);
3756         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3757                                          mail_op);
3758         modest_mail_operation_create_folder (mail_op,
3759                                              helper->parent,
3760                                              (const gchar *) helper->folder_name,
3761                                              do_create_folder_cb,
3762                                              g_strdup (helper->folder_name));
3763         g_object_unref (mail_op);
3764
3765  frees:
3766         if (helper->parent)
3767                 g_object_unref (helper->parent);
3768         if (helper->folder_name)
3769                 g_free (helper->folder_name);
3770         g_slice_free (CreateFolderConnect, helper);
3771 }
3772
3773
3774 static void
3775 do_create_folder (GtkWindow *parent_window,
3776                   TnyFolderStore *suggested_parent,
3777                   const gchar *suggested_name)
3778 {
3779         gint result;
3780         gchar *folder_name = NULL;
3781         TnyFolderStore *parent_folder = NULL;
3782
3783         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
3784                                                         suggested_parent,
3785                                                         (gchar *) suggested_name,
3786                                                         &folder_name,
3787                                                         &parent_folder);
3788
3789         if (result == GTK_RESPONSE_ACCEPT && parent_folder) {
3790                 CreateFolderConnect *helper = (CreateFolderConnect *) g_slice_new0 (CreateFolderConnect);
3791                 helper->folder_name = g_strdup (folder_name);
3792                 helper->parent = g_object_ref (parent_folder);
3793
3794                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window),
3795                                                                TRUE,
3796                                                                parent_folder,
3797                                                                do_create_folder_performer,
3798                                                                helper);
3799         }
3800
3801         if (folder_name)
3802                 g_free (folder_name);
3803         if (parent_folder)
3804                 g_object_unref (parent_folder);
3805 }
3806
3807 static void
3808 modest_ui_actions_create_folder(GtkWidget *parent_window,
3809                                 GtkWidget *folder_view,
3810                                 TnyFolderStore *parent_folder)
3811 {
3812         if (!parent_folder) {
3813 #ifdef MODEST_TOOLKIT_HILDON2
3814                 ModestTnyAccountStore *acc_store;
3815
3816                 acc_store = modest_runtime_get_account_store ();
3817
3818                 parent_folder = (TnyFolderStore *)
3819                         modest_tny_account_store_get_local_folders_account (acc_store);
3820 #else
3821                 parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3822 #endif
3823         }
3824
3825         if (parent_folder) {
3826                 do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
3827                 g_object_unref (parent_folder);
3828         }
3829 }
3830
3831 void
3832 modest_ui_actions_on_new_folder (GtkAction *action, ModestWindow *window)
3833 {
3834
3835         g_return_if_fail (MODEST_IS_WINDOW(window));
3836
3837         if (MODEST_IS_MAIN_WINDOW (window)) {
3838                 GtkWidget *folder_view;
3839
3840                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3841                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3842                 if (!folder_view)
3843                         return;
3844
3845                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3846 #ifdef MODEST_TOOLKIT_HILDON2
3847         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
3848                 GtkWidget *folder_view;
3849
3850                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3851                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3852 #endif
3853         } else {
3854                 g_assert_not_reached ();
3855         }
3856 }
3857
3858 static void
3859 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
3860                                                gpointer user_data)
3861 {
3862         const GError *error = NULL;
3863         gchar *message = NULL;
3864         gboolean mem_full;
3865         TnyAccount *account = modest_mail_operation_get_account (mail_op);
3866
3867         /* Get error message */
3868         error = modest_mail_operation_get_error (mail_op);
3869         if (!error)
3870                 g_return_if_reached ();
3871
3872         mem_full = modest_tny_account_store_is_disk_full_error (modest_runtime_get_account_store(),
3873                                                                 (GError *) error, account);
3874         if (mem_full) {
3875                 message = g_strdup_printf (_KR("cerm_device_memory_full"), "");
3876         } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3877                    error->code == MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS) {
3878                 message = _CS("ckdg_ib_folder_already_exists");
3879         } else if (error->domain == TNY_ERROR_DOMAIN &&
3880                    error->code == TNY_SERVICE_ERROR_STATE) {
3881                 /* This means that the folder is already in use (a
3882                    message is opened for example */
3883                 message = _("emev_ni_internal_error");
3884         } else {
3885                 message = _CS("ckdg_ib_unable_to_rename");
3886         }
3887
3888         /* We don't set a parent for the dialog because the dialog
3889            will be destroyed so the banner won't appear */
3890         modest_platform_information_banner (NULL, NULL, message);
3891
3892         if (account)
3893                 g_object_unref (account);
3894         if (mem_full)
3895                 g_free (message);
3896 }
3897
3898 typedef struct {
3899         TnyFolderStore *folder;
3900         gchar *new_name;
3901 } RenameFolderInfo;
3902
3903 static void
3904 on_rename_folder_cb (ModestMailOperation *mail_op,
3905                      TnyFolder *new_folder,
3906                      gpointer user_data)
3907 {
3908         ModestFolderView *folder_view;
3909
3910         /* If the window was closed when renaming a folder, or if
3911          * it's not a main window this will happen */
3912         if (!MODEST_IS_FOLDER_VIEW (user_data))
3913                 return;
3914
3915         folder_view = MODEST_FOLDER_VIEW (user_data);
3916         /* Note that if the rename fails new_folder will be NULL */
3917         if (new_folder) {
3918                 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
3919         } else {
3920                 modest_folder_view_select_first_inbox_or_local (folder_view);
3921         }
3922         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
3923 }
3924
3925 static void
3926 on_rename_folder_performer (gboolean canceled,
3927                             GError *err,
3928                             GtkWindow *parent_window,
3929                             TnyAccount *account,
3930                             gpointer user_data)
3931 {
3932         ModestMailOperation *mail_op = NULL;
3933         GtkTreeSelection *sel = NULL;
3934         GtkWidget *folder_view = NULL;
3935         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
3936
3937         if (canceled || err) {
3938                 /* In disk full conditions we could get this error here */
3939                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3940                                                                 (GtkWidget *) parent_window, err,
3941                                                                 account, NULL);
3942         } else {
3943
3944                 mail_op =
3945                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3946                                         modest_ui_actions_rename_folder_error_handler,
3947                                         parent_window, NULL);
3948
3949                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3950                                 mail_op);
3951
3952                 if (MODEST_IS_MAIN_WINDOW(parent_window)) {
3953
3954                         folder_view = modest_main_window_get_child_widget (
3955                                 MODEST_MAIN_WINDOW (parent_window),
3956                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3957                 }
3958 #ifdef MODEST_TOOLKIT_HILDON2
3959                 else if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3960                         ModestFolderWindow *folder_window = (ModestFolderWindow *) parent_window;
3961                         folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (folder_window));
3962                 }
3963 #endif
3964
3965                 /* Clear the folders view */
3966                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3967                 gtk_tree_selection_unselect_all (sel);
3968
3969                 /* Actually rename the folder */
3970                 modest_mail_operation_rename_folder (mail_op,
3971                                                      TNY_FOLDER (data->folder),
3972                                                      (const gchar *) (data->new_name),
3973                                                      on_rename_folder_cb,
3974                                                      folder_view);
3975                 g_object_unref (mail_op);
3976         }
3977
3978         g_object_unref (data->folder);
3979         g_free (data->new_name);
3980         g_free (data);
3981 }
3982
3983 void
3984 modest_ui_actions_on_rename_folder (GtkAction *action,
3985                                      ModestWindow *window)
3986 {
3987         modest_ui_actions_on_edit_mode_rename_folder (window);
3988 }
3989
3990 gboolean
3991 modest_ui_actions_on_edit_mode_rename_folder (ModestWindow *window)
3992 {
3993         TnyFolderStore *folder;
3994         GtkWidget *folder_view;
3995         gboolean do_rename = TRUE;
3996
3997         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3998
3999         if (MODEST_IS_MAIN_WINDOW (window)) {
4000                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4001                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4002                 if (!folder_view)
4003                         return FALSE;
4004
4005 #ifdef MODEST_TOOLKIT_HILDON2
4006         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
4007                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
4008 #endif
4009         } else {
4010                 return FALSE;
4011         }
4012
4013         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
4014
4015         if (!folder)
4016                 return FALSE;
4017
4018         if (TNY_IS_FOLDER (folder)) {
4019                 gchar *folder_name = NULL;
4020                 gint response;
4021                 const gchar *current_name;
4022                 TnyFolderStore *parent;
4023
4024                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
4025                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
4026                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (window),
4027                                                                      parent, current_name,
4028                                                                      &folder_name);
4029                 g_object_unref (parent);
4030
4031                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
4032                         do_rename = FALSE;
4033                 } else {
4034                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
4035                         rename_folder_data->folder = g_object_ref (folder);
4036                         rename_folder_data->new_name = folder_name;
4037                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(window), TRUE,
4038                                         folder, on_rename_folder_performer, rename_folder_data);
4039                 }
4040         }
4041         g_object_unref (folder);
4042         return do_rename;
4043 }
4044
4045 static void
4046 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
4047                                                gpointer user_data)
4048 {
4049         GObject *win = modest_mail_operation_get_source (mail_op);
4050
4051         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
4052                                                 _("mail_in_ui_folder_delete_error"),
4053                                                 FALSE);
4054         g_object_unref (win);
4055 }
4056
4057 typedef struct {
4058         TnyFolderStore *folder;
4059         gboolean move_to_trash;
4060 } DeleteFolderInfo;
4061
4062 static void
4063 on_delete_folder_cb (gboolean canceled,
4064                   GError *err,
4065                   GtkWindow *parent_window,
4066                   TnyAccount *account,
4067                   gpointer user_data)
4068 {
4069         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
4070         GtkWidget *folder_view;
4071         ModestMailOperation *mail_op;
4072         GtkTreeSelection *sel;
4073
4074         if (!MODEST_IS_WINDOW(parent_window) || canceled || (err!=NULL)) {
4075                 /* Note that the connection process can fail due to
4076                    memory low conditions as it can not successfully
4077                    store the summary */
4078                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
4079                                                                      (GtkWidget*) parent_window, err,
4080                                                                      account, NULL))
4081                         g_debug ("Error connecting when trying to delete a folder");
4082                 g_object_unref (G_OBJECT (info->folder));
4083                 g_free (info);
4084                 return;
4085         }
4086
4087         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
4088                 folder_view = modest_main_window_get_child_widget (
4089                         MODEST_MAIN_WINDOW (parent_window),
4090                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4091 #ifdef MODEST_TOOLKIT_HILDON2
4092         } else if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
4093                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (parent_window)));
4094 #endif
4095         } else {
4096                 g_object_unref (G_OBJECT (info->folder));
4097                 g_free (info);
4098                 return;
4099         }
4100
4101         /* Unselect the folder before deleting it to free the headers */
4102         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
4103         gtk_tree_selection_unselect_all (sel);
4104
4105         /* Create the mail operation */
4106         mail_op =
4107                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
4108                                 modest_ui_actions_delete_folder_error_handler,
4109                                 NULL, NULL);
4110
4111         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4112                         mail_op);
4113         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
4114
4115         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
4116
4117         g_object_unref (mail_op);
4118         g_object_unref (info->folder);
4119         g_free (info);
4120 }
4121
4122 static gboolean
4123 delete_folder (ModestWindow *window, gboolean move_to_trash)
4124 {
4125         TnyFolderStore *folder;
4126         GtkWidget *folder_view;
4127         gint response;
4128         gchar *message;
4129
4130         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
4131
4132         if (MODEST_IS_MAIN_WINDOW (window)) {
4133
4134                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4135                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4136 #ifdef MODEST_TOOLKIT_HILDON2
4137         } else if (MODEST_IS_FOLDER_WINDOW (window)) {
4138                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
4139 #endif
4140         } else {
4141                 return FALSE;
4142         }
4143         if (!folder_view)
4144                 return FALSE;
4145
4146         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4147
4148         if (!folder)
4149                 return FALSE;
4150
4151         /* Show an error if it's an account */
4152         if (!TNY_IS_FOLDER (folder)) {
4153                 modest_platform_run_information_dialog (GTK_WINDOW (window),
4154                                                         _("mail_in_ui_folder_delete_error"),
4155                                                         FALSE);
4156                 g_object_unref (G_OBJECT (folder));
4157                 return FALSE;
4158         }
4159
4160         /* Ask the user */
4161         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"),
4162                                     tny_folder_get_name (TNY_FOLDER (folder)));
4163         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
4164                                                             (const gchar *) message);
4165         g_free (message);
4166
4167         if (response == GTK_RESPONSE_OK) {
4168                 TnyAccount *account = NULL;
4169                 DeleteFolderInfo *info = NULL;
4170                 info = g_new0(DeleteFolderInfo, 1);
4171                 info->folder = g_object_ref (folder);
4172                 info->move_to_trash = move_to_trash;
4173
4174                 account = tny_folder_get_account (TNY_FOLDER (folder));
4175                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (window),
4176                                                                TRUE,
4177                                                                TNY_FOLDER_STORE (account),
4178                                                                on_delete_folder_cb, info);
4179                 g_object_unref (account);
4180                 g_object_unref (folder);
4181                 return TRUE;
4182         } else {
4183                 return FALSE;
4184         }
4185 }
4186
4187 void
4188 modest_ui_actions_on_delete_folder (GtkAction *action,
4189                                     ModestWindow *window)
4190 {
4191         modest_ui_actions_on_edit_mode_delete_folder (window);
4192 }
4193
4194 gboolean
4195 modest_ui_actions_on_edit_mode_delete_folder (ModestWindow *window)
4196 {
4197         g_return_val_if_fail (MODEST_IS_WINDOW(window), TRUE);
4198
4199         return delete_folder (window, FALSE);
4200 }
4201
4202 void
4203 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
4204 {
4205         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4206
4207         delete_folder (MODEST_WINDOW (main_window), TRUE);
4208 }
4209
4210
4211 typedef struct _PasswordDialogFields {
4212         GtkWidget *username;
4213         GtkWidget *password;
4214         GtkWidget *dialog;
4215 } PasswordDialogFields;
4216
4217 static void
4218 password_dialog_check_field (GtkEditable *editable,
4219                              PasswordDialogFields *fields)
4220 {
4221         const gchar *value;
4222         gboolean any_value_empty = FALSE;
4223
4224 #ifdef MODEST_TOOLKIT_HILDON2
4225         value = hildon_entry_get_text (HILDON_ENTRY (fields->username));
4226 #else
4227         value = gtk_entry_get_text (GTK_ENTRY (fields->username));
4228 #endif
4229         if ((value == NULL) || value[0] == '\0') {
4230                 any_value_empty = TRUE;
4231         }
4232 #ifdef MODEST_TOOLKIT_HILDON2
4233         value = hildon_entry_get_text (HILDON_ENTRY (fields->password));
4234 #else
4235         value = gtk_entry_get_text (GTK_ENTRY (fields->password));
4236 #endif
4237         if ((value == NULL) || value[0] == '\0') {
4238                 any_value_empty = TRUE;
4239         }
4240         gtk_dialog_set_response_sensitive (GTK_DIALOG (fields->dialog), GTK_RESPONSE_ACCEPT, !any_value_empty);
4241 }
4242
4243 void
4244 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
4245                                          const gchar* server_account_name,
4246                                          gchar **username,
4247                                          gchar **password,
4248                                          gboolean *cancel,
4249                                          gboolean *remember,
4250                                          ModestMainWindow *main_window)
4251 {
4252         g_return_if_fail(server_account_name);
4253         gboolean completed = FALSE;
4254         PasswordDialogFields *fields = NULL;
4255
4256         /* Initalize output parameters: */
4257         if (cancel)
4258                 *cancel = FALSE;
4259
4260         if (remember)
4261                 *remember = TRUE;
4262
4263 #ifndef MODEST_TOOLKIT_GTK
4264         /* Maemo uses a different (awkward) button order,
4265          * It should probably just use gtk_alternative_dialog_button_order ().
4266          */
4267 #ifdef MODEST_TOOLKIT_HILDON2
4268         GtkWidget *dialog =
4269                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4270                                              NULL,
4271                                              GTK_DIALOG_MODAL,
4272                                              _HL("wdgt_bd_done"),
4273                                              GTK_RESPONSE_ACCEPT,
4274                                              NULL);
4275         gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
4276                                         HILDON_MARGIN_DOUBLE);
4277 #else
4278         GtkWidget *dialog =
4279                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4280                                              NULL,
4281                                              GTK_DIALOG_MODAL,
4282                                              _("mcen_bd_dialog_ok"),
4283                                              GTK_RESPONSE_ACCEPT,
4284                                              _("mcen_bd_dialog_cancel"),
4285                                              GTK_RESPONSE_REJECT,
4286                                              NULL);
4287 #endif /* MODEST_TOOLKIT_HILDON2 */
4288 #else
4289         GtkWidget *dialog =
4290                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
4291                                              NULL,
4292                                              GTK_DIALOG_MODAL,
4293                                              GTK_STOCK_CANCEL,
4294                                              GTK_RESPONSE_REJECT,
4295                                              GTK_STOCK_OK,
4296                                              GTK_RESPONSE_ACCEPT,
4297                                              NULL);
4298 #endif /* MODEST_TOOLKIT_GTK */
4299
4300         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog), NULL);
4301
4302         gchar *server_name = modest_account_mgr_get_server_account_hostname (
4303                 modest_runtime_get_account_mgr(), server_account_name);
4304         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
4305                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
4306                 if (cancel)
4307                         *cancel = TRUE;
4308                 gtk_widget_destroy (dialog);
4309                 return;
4310         }
4311
4312         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
4313         GtkWidget *label = gtk_label_new (txt);
4314         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
4315         g_free (txt);
4316         g_free (server_name);
4317         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label,
4318                             FALSE, FALSE, 0);
4319         server_name = NULL;
4320
4321         /* username: */
4322         gchar *initial_username = modest_account_mgr_get_server_account_username (
4323                 modest_runtime_get_account_mgr(), server_account_name);
4324
4325 #ifdef MODEST_TOOLKIT_HILDON2
4326         GtkWidget *entry_username = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
4327         if (initial_username)
4328                 hildon_entry_set_text (HILDON_ENTRY (entry_username), initial_username);
4329 #else
4330         GtkWidget *entry_username = gtk_entry_new ();
4331         if (initial_username)
4332                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
4333 #endif
4334         /* Dim this if a connection has ever succeeded with this username,
4335          * as per the UI spec: */
4336         /* const gboolean username_known =  */
4337         /*      modest_account_mgr_get_server_account_username_has_succeeded( */
4338         /*              modest_runtime_get_account_mgr(), server_account_name); */
4339         /* gtk_widget_set_sensitive (entry_username, !username_known); */
4340
4341         /* We drop the username sensitive code and disallow changing it here
4342          * as tinymail does not support really changing the username in the callback
4343          */
4344         gtk_widget_set_sensitive (entry_username, FALSE);
4345
4346 #ifndef MODEST_TOOLKIT_GTK
4347         /* Auto-capitalization is the default, so let's turn it off: */
4348         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
4349
4350         /* Create a size group to be used by all captions.
4351          * Note that HildonCaption does not create a default size group if we do not specify one.
4352          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
4353         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
4354
4355 #ifdef MODEST_TOOLKIT_HILDON2
4356         GtkWidget *caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
4357                                                                   _("mail_fi_username"), FALSE,
4358                                                                   entry_username);
4359 #else
4360         GtkWidget *caption = hildon_caption_new (sizegroup,
4361                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
4362 #endif
4363         gtk_widget_show (entry_username);
4364         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
4365                 FALSE, FALSE, MODEST_MARGIN_HALF);
4366         gtk_widget_show (caption);
4367 #else
4368         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
4369                             TRUE, FALSE, 0);
4370 #endif /* !MODEST_TOOLKIT_GTK */
4371
4372         /* password: */
4373 #ifdef MODEST_TOOLKIT_HILDON2
4374         GtkWidget *entry_password = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH);
4375 #else
4376         GtkWidget *entry_password = gtk_entry_new ();
4377 #endif
4378         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
4379         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
4380
4381 #ifndef MODEST_TOOLKIT_GTK
4382         /* Auto-capitalization is the default, so let's turn it off: */
4383         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
4384                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
4385
4386 #ifdef MODEST_TOOLKIT_HILDON2
4387         caption = modest_maemo_utils_create_captioned (sizegroup, NULL,
4388                                                        _("mail_fi_password"), FALSE,
4389                                                        entry_password);
4390 #else
4391         caption = hildon_caption_new (sizegroup,
4392                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
4393 #endif
4394         gtk_widget_show (entry_password);
4395         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
4396                 FALSE, FALSE, MODEST_MARGIN_HALF);
4397         gtk_widget_show (caption);
4398         g_object_unref (sizegroup);
4399 #else
4400         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
4401                             TRUE, FALSE, 0);
4402 #endif /* !MODEST_TOOLKIT_GTK */
4403
4404         if (initial_username != NULL)
4405                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
4406
4407 /* This is not in the Maemo UI spec:
4408         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
4409         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
4410                             TRUE, FALSE, 0);
4411 */
4412
4413         fields = g_slice_new0 (PasswordDialogFields);
4414         fields->username = entry_username;
4415         fields->password = entry_password;
4416         fields->dialog = dialog;
4417
4418         g_signal_connect (entry_username, "changed", G_CALLBACK (password_dialog_check_field), fields);
4419         g_signal_connect (entry_password, "changed", G_CALLBACK (password_dialog_check_field), fields);
4420         password_dialog_check_field (NULL, fields);
4421
4422         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4423
4424         while (!completed) {
4425
4426                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
4427                         if (username) {
4428 #ifdef MODEST_TOOLKIT_HILDON2
4429                                 *username = g_strdup (hildon_entry_get_text (HILDON_ENTRY(entry_username)));
4430 #else
4431                                 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
4432 #endif
4433
4434                                 /* Note that an empty field becomes the "" string */
4435                                 if (*username && strlen (*username) > 0) {
4436                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(),
4437                                                                                         server_account_name,
4438                                                                                         *username);
4439                                         completed = TRUE;
4440
4441                                         const gboolean username_was_changed =
4442                                                 (strcmp (*username, initial_username) != 0);
4443                                         if (username_was_changed) {
4444                                                 g_warning ("%s: tinymail does not yet support changing the "
4445                                                            "username in the get_password() callback.\n", __FUNCTION__);
4446                                         }
4447                                 } else {
4448                                         g_free (*username);
4449                                         *username = NULL;
4450                                         /* Show error */
4451                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL,
4452                                                                             _("mcen_ib_username_pw_incorrect"));
4453                                         completed = FALSE;
4454                                 }
4455                         }
4456
4457                         if (password) {
4458 #ifdef MODEST_TOOLKIT_HILDON2
4459                                 *password = g_strdup (hildon_entry_get_text (HILDON_ENTRY(entry_password)));
4460 #else
4461                                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
4462 #endif
4463
4464                                 /* We do not save the password in the configuration,
4465                                  * because this function is only called for passwords that should
4466                                  * not be remembered:
4467                                  modest_server_account_set_password (
4468                                  modest_runtime_get_account_mgr(), server_account_name,
4469                                  *password);
4470                                  */
4471                         }
4472                         if (cancel)
4473                                 *cancel   = FALSE;
4474                 } else {
4475 #ifndef MODEST_TOOLKIT_HILDON2
4476                         /* Set parent to NULL or the banner will disappear with its parent dialog */
4477                         modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
4478 #endif
4479                         completed = TRUE;
4480                         if (username)
4481                                 *username = NULL;
4482                         if (password)
4483                                 *password = NULL;
4484                         if (cancel)
4485                                 *cancel   = TRUE;
4486                 }
4487         }
4488
4489 /* This is not in the Maemo UI spec:
4490         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
4491                 *remember = TRUE;
4492         else
4493                 *remember = FALSE;
4494 */
4495
4496         g_free (initial_username);
4497         gtk_widget_destroy (dialog);
4498         g_slice_free (PasswordDialogFields, fields);
4499
4500         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
4501 }
4502
4503 void
4504 modest_ui_actions_on_cut (GtkAction *action,
4505                           ModestWindow *window)
4506 {
4507         GtkWidget *focused_widget;
4508         GtkClipboard *clipboard;
4509
4510         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4511         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4512         if (GTK_IS_EDITABLE (focused_widget)) {
4513                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
4514                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4515                 gtk_clipboard_store (clipboard);
4516         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4517                 GtkTextBuffer *buffer;
4518
4519                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4520                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4521                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
4522                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4523                         gtk_clipboard_store (clipboard);
4524                 }
4525         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4526                 TnyList *header_list = modest_header_view_get_selected_headers (
4527                                 MODEST_HEADER_VIEW (focused_widget));
4528                 gboolean continue_download = FALSE;
4529                 gint num_of_unc_msgs;
4530
4531                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4532
4533                 if (num_of_unc_msgs) {
4534                         TnyAccount *account = get_account_from_header_list (header_list);
4535                         if (account) {
4536                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4537                                 g_object_unref (account);
4538                         }
4539                 }
4540
4541                 if (num_of_unc_msgs == 0 || continue_download) {
4542 /*                      modest_platform_information_banner (
4543                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
4544                         modest_header_view_cut_selection (
4545                                         MODEST_HEADER_VIEW (focused_widget));
4546                 }
4547
4548                 g_object_unref (header_list);
4549         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4550                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
4551         }
4552 }
4553
4554 void
4555 modest_ui_actions_on_copy (GtkAction *action,
4556                            ModestWindow *window)
4557 {
4558         GtkClipboard *clipboard;
4559         GtkWidget *focused_widget;
4560         gboolean copied = TRUE;
4561
4562         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4563         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4564
4565         if (GTK_IS_LABEL (focused_widget)) {
4566                 gchar *selection;
4567                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
4568                 gtk_clipboard_set_text (clipboard, selection, -1);
4569                 g_free (selection);
4570                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4571                 gtk_clipboard_store (clipboard);
4572         } else if (GTK_IS_EDITABLE (focused_widget)) {
4573                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
4574                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
4575                 gtk_clipboard_store (clipboard);
4576         } else if (GTK_IS_HTML (focused_widget)) {
4577                 const gchar *sel;
4578                 int len = -1;
4579                 sel = gtk_html_get_selection_html (GTK_HTML (focused_widget), &len);
4580                 if ((sel == NULL) || (sel[0] == '\0')) {
4581                         copied = FALSE;
4582                 } else {
4583                         gtk_html_copy (GTK_HTML (focused_widget));
4584                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4585                         gtk_clipboard_store (clipboard);
4586                 }
4587         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4588                 GtkTextBuffer *buffer;
4589                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4590                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
4591                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
4592                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
4593                         gtk_clipboard_store (clipboard);
4594                 }
4595         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
4596                 TnyList *header_list = modest_header_view_get_selected_headers (
4597                                 MODEST_HEADER_VIEW (focused_widget));
4598                 gboolean continue_download = FALSE;
4599                 gint num_of_unc_msgs;
4600
4601                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
4602
4603                 if (num_of_unc_msgs) {
4604                         TnyAccount *account = get_account_from_header_list (header_list);
4605                         if (account) {
4606                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
4607                                 g_object_unref (account);
4608                         }
4609                 }
4610
4611                 if (num_of_unc_msgs == 0 || continue_download) {
4612                         modest_platform_information_banner (
4613                                         NULL, NULL, _CS("mcen_ib_getting_items"));
4614                         modest_header_view_copy_selection (
4615                                         MODEST_HEADER_VIEW (focused_widget));
4616                 } else
4617                         copied = FALSE;
4618
4619                 g_object_unref (header_list);
4620
4621         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4622                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
4623         }
4624
4625         /* Show information banner if there was a copy to clipboard */
4626         if(copied)
4627                 modest_platform_information_banner (
4628                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
4629 }
4630
4631 void
4632 modest_ui_actions_on_undo (GtkAction *action,
4633                            ModestWindow *window)
4634 {
4635         ModestEmailClipboard *clipboard = NULL;
4636
4637         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4638                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
4639         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4640                 /* Clear clipboard source */
4641                 clipboard = modest_runtime_get_email_clipboard ();
4642                 modest_email_clipboard_clear (clipboard);
4643         }
4644         else {
4645                 g_return_if_reached ();
4646         }
4647 }
4648
4649 void
4650 modest_ui_actions_on_redo (GtkAction *action,
4651                            ModestWindow *window)
4652 {
4653         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4654                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
4655         }
4656         else {
4657                 g_return_if_reached ();
4658         }
4659 }
4660
4661
4662 static void
4663 destroy_information_note (ModestMailOperation *mail_op,
4664                           gpointer user_data)
4665 {
4666         /* destroy information note */
4667         gtk_widget_destroy (GTK_WIDGET(user_data));
4668 }
4669
4670 static void
4671 destroy_folder_information_note (ModestMailOperation *mail_op,
4672                                  TnyFolder *new_folder,
4673                                  gpointer user_data)
4674 {
4675         /* destroy information note */
4676         gtk_widget_destroy (GTK_WIDGET(user_data));
4677 }
4678
4679
4680 static void
4681 paste_as_attachment_free (gpointer data)
4682 {
4683         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
4684
4685         if (helper->banner) {
4686                 gtk_widget_destroy (helper->banner);
4687                 g_object_unref (helper->banner);
4688         }
4689         g_free (helper);
4690 }
4691
4692 static void
4693 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
4694                             TnyHeader *header,
4695                             TnyMsg *msg,
4696                             gpointer userdata)
4697 {
4698         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
4699         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
4700
4701         if (msg == NULL)
4702                 return;
4703
4704         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
4705
4706 }
4707
4708 void
4709 modest_ui_actions_on_paste (GtkAction *action,
4710                             ModestWindow *window)
4711 {
4712         GtkWidget *focused_widget = NULL;
4713         GtkWidget *inf_note = NULL;
4714         ModestMailOperation *mail_op = NULL;
4715
4716         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4717         if (GTK_IS_EDITABLE (focused_widget)) {
4718                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
4719         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4720                 ModestEmailClipboard *e_clipboard = NULL;
4721                 e_clipboard = modest_runtime_get_email_clipboard ();
4722                 if (modest_email_clipboard_cleared (e_clipboard)) {
4723                         GtkTextBuffer *buffer;
4724                         GtkClipboard *clipboard;
4725
4726                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4727                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4728                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
4729                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4730                         ModestMailOperation *mail_op;
4731                         TnyFolder *src_folder = NULL;
4732                         TnyList *data = NULL;
4733                         gboolean delete;
4734                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
4735                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
4736                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4737                                                                            _CS("ckct_nw_pasting"));
4738                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
4739                         mail_op = modest_mail_operation_new (G_OBJECT (window));
4740                         if (helper->banner != NULL) {
4741                                 g_object_ref (G_OBJECT (helper->banner));
4742                                 gtk_widget_show (GTK_WIDGET (helper->banner));
4743                         }
4744
4745                         if (data != NULL) {
4746                                 modest_mail_operation_get_msgs_full (mail_op,
4747                                                                      data,
4748                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
4749                                                                      helper,
4750                                                                      paste_as_attachment_free);
4751                         }
4752                         /* Free */
4753                         if (data)
4754                                 g_object_unref (data);
4755                         if (src_folder)
4756                                 g_object_unref (src_folder);
4757
4758                 }
4759         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4760                 ModestEmailClipboard *clipboard = NULL;
4761                 TnyFolder *src_folder = NULL;
4762                 TnyFolderStore *folder_store = NULL;
4763                 TnyList *data = NULL;
4764                 gboolean delete = FALSE;
4765
4766                 /* Check clipboard source */
4767                 clipboard = modest_runtime_get_email_clipboard ();
4768                 if (modest_email_clipboard_cleared (clipboard))
4769                         return;
4770
4771                 /* Get elements to paste */
4772                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
4773
4774                 /* Create a new mail operation */
4775                 mail_op = modest_mail_operation_new (G_OBJECT(window));
4776
4777                 /* Get destination folder */
4778                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
4779
4780                 /* transfer messages  */
4781                 if (data != NULL) {
4782                         gint response = 0;
4783
4784                         /* Ask for user confirmation */
4785                         response =
4786                                 modest_ui_actions_msgs_move_to_confirmation (window,
4787                                                                              TNY_FOLDER (folder_store),
4788                                                                              delete,
4789                                                                              data);
4790
4791                         if (response == GTK_RESPONSE_OK) {
4792                                 /* Launch notification */
4793                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4794                                                                              _CS("ckct_nw_pasting"));
4795                                 if (inf_note != NULL)  {
4796                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4797                                         gtk_widget_show (GTK_WIDGET(inf_note));
4798                                 }
4799
4800                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4801                                 modest_mail_operation_xfer_msgs (mail_op,
4802                                                                  data,
4803                                                                  TNY_FOLDER (folder_store),
4804                                                                  delete,
4805                                                                  destroy_information_note,
4806                                                                  inf_note);
4807                         } else {
4808                                 g_object_unref (mail_op);
4809                         }
4810
4811                 } else if (src_folder != NULL) {
4812                         /* Launch notification */
4813                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4814                                                                      _CS("ckct_nw_pasting"));
4815                         if (inf_note != NULL)  {
4816                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4817                                 gtk_widget_show (GTK_WIDGET(inf_note));
4818                         }
4819
4820                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4821                         modest_mail_operation_xfer_folder (mail_op,
4822                                                            src_folder,
4823                                                            folder_store,
4824                                                            delete,
4825                                                            destroy_folder_information_note,
4826                                                            inf_note);
4827                 }
4828
4829                 /* Free */
4830                 if (data != NULL)
4831                         g_object_unref (data);
4832                 if (src_folder != NULL)
4833                         g_object_unref (src_folder);
4834                 if (folder_store != NULL)
4835                         g_object_unref (folder_store);
4836         }
4837 }
4838
4839
4840 void
4841 modest_ui_actions_on_select_all (GtkAction *action,
4842                                  ModestWindow *window)
4843 {
4844         GtkWidget *focused_widget;
4845
4846         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4847         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
4848                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
4849         } else if (GTK_IS_LABEL (focused_widget)) {
4850                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
4851         } else if (GTK_IS_EDITABLE (focused_widget)) {
4852                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
4853         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4854                 GtkTextBuffer *buffer;
4855                 GtkTextIter start, end;
4856
4857                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4858                 gtk_text_buffer_get_start_iter (buffer, &start);
4859                 gtk_text_buffer_get_end_iter (buffer, &end);
4860                 gtk_text_buffer_select_range (buffer, &start, &end);
4861         } else if (GTK_IS_HTML (focused_widget)) {
4862                 gtk_html_select_all (GTK_HTML (focused_widget));
4863         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4864                 GtkWidget *header_view = focused_widget;
4865                 GtkTreeSelection *selection = NULL;
4866
4867                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
4868                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4869                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4870                 }
4871
4872                 /* Disable window dimming management */
4873                 modest_window_disable_dimming (MODEST_WINDOW(window));
4874
4875                 /* Select all messages */
4876                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
4877                 gtk_tree_selection_select_all (selection);
4878
4879                 /* Set focuse on header view */
4880                 gtk_widget_grab_focus (header_view);
4881
4882                 /* Enable window dimming management */
4883                 modest_window_enable_dimming (MODEST_WINDOW(window));
4884                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
4885                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
4886         }
4887
4888 }
4889
4890 void
4891 modest_ui_actions_on_mark_as_read (GtkAction *action,
4892                                    ModestWindow *window)
4893 {
4894         g_return_if_fail (MODEST_IS_WINDOW(window));
4895
4896         /* Mark each header as read */
4897         do_headers_action (window, headers_action_mark_as_read, NULL);
4898 }
4899
4900 void
4901 modest_ui_actions_on_mark_as_unread (GtkAction *action,
4902                                      ModestWindow *window)
4903 {
4904         g_return_if_fail (MODEST_IS_WINDOW(window));
4905
4906         /* Mark each header as read */
4907         do_headers_action (window, headers_action_mark_as_unread, NULL);
4908 }
4909
4910 void
4911 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
4912                                   GtkRadioAction *selected,
4913                                   ModestWindow *window)
4914 {
4915         gint value;
4916
4917         value = gtk_radio_action_get_current_value (selected);
4918         if (MODEST_IS_WINDOW (window)) {
4919                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
4920         }
4921 }
4922
4923 void
4924 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
4925                                                GtkRadioAction *selected,
4926                                                ModestWindow *window)
4927 {
4928         TnyHeaderFlags flags;
4929         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4930
4931         flags = gtk_radio_action_get_current_value (selected);
4932         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
4933 }
4934
4935 void
4936 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
4937                                                   GtkRadioAction *selected,
4938                                                   ModestWindow *window)
4939 {
4940         gint file_format;
4941
4942         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4943
4944         file_format = gtk_radio_action_get_current_value (selected);
4945         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
4946 }
4947
4948
4949 void
4950 modest_ui_actions_on_zoom_plus (GtkAction *action,
4951                                 ModestWindow *window)
4952 {
4953         g_return_if_fail (MODEST_IS_WINDOW (window));
4954
4955         modest_window_zoom_plus (MODEST_WINDOW (window));
4956 }
4957
4958 void
4959 modest_ui_actions_on_zoom_minus (GtkAction *action,
4960                                  ModestWindow *window)
4961 {
4962         g_return_if_fail (MODEST_IS_WINDOW (window));
4963
4964         modest_window_zoom_minus (MODEST_WINDOW (window));
4965 }
4966
4967 void
4968 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
4969                                            ModestWindow *window)
4970 {
4971         ModestWindowMgr *mgr;
4972         gboolean fullscreen, active;
4973         g_return_if_fail (MODEST_IS_WINDOW (window));
4974
4975         mgr = modest_runtime_get_window_mgr ();
4976
4977         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4978         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4979
4980         if (active != fullscreen) {
4981                 modest_window_mgr_set_fullscreen_mode (mgr, active);
4982 #ifndef MODEST_TOOLKIT_HILDON2
4983                 gtk_window_present (GTK_WINDOW (window));
4984 #endif
4985         }
4986 }
4987
4988 void
4989 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4990                                         ModestWindow *window)
4991 {
4992         ModestWindowMgr *mgr;
4993         gboolean fullscreen;
4994
4995         g_return_if_fail (MODEST_IS_WINDOW (window));
4996
4997         mgr = modest_runtime_get_window_mgr ();
4998         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4999         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
5000
5001 #ifndef MODEST_TOOLKIT_HILDON2
5002         gtk_window_present (GTK_WINDOW (window));
5003 #endif
5004 }
5005
5006 /*
5007  * Used by modest_ui_actions_on_details to call do_headers_action
5008  */
5009 static void
5010 headers_action_show_details (TnyHeader *header,
5011                              ModestWindow *window,
5012                              gpointer user_data)
5013
5014 {
5015         gboolean async_retrieval;
5016         TnyMsg *msg = NULL;
5017
5018         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5019                 async_retrieval = TRUE;
5020                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (window));
5021                 async_retrieval = !TNY_IS_CAMEL_BS_MSG (msg);
5022         } else {
5023                 async_retrieval = FALSE;
5024         }
5025         modest_platform_run_header_details_dialog (GTK_WINDOW (window), header, async_retrieval, msg);
5026         if (msg)
5027                 g_object_unref (msg);
5028 }
5029
5030 /*
5031  * Show the header details in a ModestDetailsDialog widget
5032  */
5033 void
5034 modest_ui_actions_on_details (GtkAction *action,
5035                               ModestWindow *win)
5036 {
5037         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
5038                 TnyMsg *msg;
5039                 TnyHeader *header;
5040
5041                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
5042                 if (!msg)
5043                         return;
5044
5045                 header = tny_msg_get_header (msg);
5046                 if (header) {
5047                         headers_action_show_details (header, win, NULL);
5048                         g_object_unref (header);
5049                 }
5050                 g_object_unref (msg);
5051
5052         } else if (MODEST_IS_MAIN_WINDOW (win)) {
5053                 GtkWidget *folder_view, *header_view;
5054
5055                 /* Check which widget has the focus */
5056                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5057                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5058                 if (gtk_widget_is_focus (folder_view)) {
5059                         TnyFolderStore *folder_store
5060                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5061                         if (!folder_store) {
5062                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
5063                                 return;
5064                         }
5065                         /* Show only when it's a folder */
5066                         /* This function should not be called for account items,
5067                          * because we dim the menu item for them. */
5068                         if (TNY_IS_FOLDER (folder_store)) {
5069                                 modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
5070                                                                            TNY_FOLDER (folder_store));
5071                         }
5072
5073                         g_object_unref (folder_store);
5074
5075                 } else {
5076                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5077                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5078                         /* Show details of each header */
5079                         do_headers_action (win, headers_action_show_details, header_view);
5080                 }
5081 #ifdef MODEST_TOOLKIT_HILDON2
5082         } else if (MODEST_IS_HEADER_WINDOW (win)) {
5083                 TnyFolder *folder;
5084                 GtkWidget *header_view;
5085
5086                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
5087                 folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
5088                 if (folder) {
5089                         modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
5090                                                                    folder);
5091                         g_object_unref (folder);
5092                 }
5093 #endif
5094         }
5095 }
5096
5097 void
5098 modest_ui_actions_on_limit_error (GtkAction *action,
5099                                   ModestWindow *win)
5100 {
5101         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (win));
5102
5103         modest_platform_information_banner ((GtkWidget *) win, NULL, _CS("ckdg_ib_maximum_characters_reached"));
5104
5105 }
5106
5107 void
5108 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
5109                                      ModestMsgEditWindow *window)
5110 {
5111         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5112
5113         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
5114 }
5115
5116 void
5117 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
5118                                       ModestMsgEditWindow *window)
5119 {
5120         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5121
5122         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
5123 }
5124
5125 void
5126 modest_ui_actions_toggle_folders_view (GtkAction *action,
5127                                        ModestMainWindow *main_window)
5128 {
5129         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
5130
5131         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
5132                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
5133         else
5134                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
5135 }
5136
5137 void
5138 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
5139                                      ModestWindow *window)
5140 {
5141         gboolean active, fullscreen = FALSE;
5142         ModestWindowMgr *mgr;
5143
5144         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
5145
5146         /* Check if we want to toggle the toolbar view in fullscreen
5147            or normal mode */
5148         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
5149                      "ViewShowToolbarFullScreen")) {
5150                 fullscreen = TRUE;
5151         }
5152
5153         /* Toggle toolbar */
5154         mgr = modest_runtime_get_window_mgr ();
5155         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
5156 }
5157
5158 void
5159 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
5160                                            ModestMsgEditWindow *window)
5161 {
5162         modest_msg_edit_window_select_font (window);
5163 }
5164
5165
5166 void
5167 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
5168                                                   const gchar *display_name,
5169                                                   GtkWindow *window)
5170 {
5171         /* don't update the display name if it was already set;
5172          * updating the display name apparently is expensive */
5173         const gchar* old_name = gtk_window_get_title (window);
5174
5175         if (display_name == NULL)
5176                 display_name = " ";
5177
5178         if (old_name && display_name && strcmp (old_name, display_name) == 0)
5179                 return; /* don't do anything */
5180
5181         /* This is usually used to change the title of the main window, which
5182          * is the one that holds the folder view. Note that this change can
5183          * happen even when the widget doesn't have the focus. */
5184         gtk_window_set_title (window, display_name);
5185
5186 }
5187
5188 void
5189 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
5190 {
5191         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5192         modest_msg_edit_window_select_contacts (window);
5193 }
5194
5195 void
5196 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
5197 {
5198         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5199         modest_msg_edit_window_check_names (window, FALSE);
5200 }
5201
5202 #ifndef MODEST_TOOLKIT_HILDON2
5203 /*
5204  * This function is used to track changes in the selection of the
5205  * folder view that is inside the "move to" dialog to enable/disable
5206  * the OK button because we do not want the user to select a disallowed
5207  * destination for a folder.
5208  * The user also not desired to be able to use NEW button on items where
5209  * folder creation is not possibel.
5210  */
5211 static void
5212 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
5213                                             TnyFolderStore *folder_store,
5214                                             gboolean selected,
5215                                             gpointer user_data)
5216 {
5217         GtkWidget *dialog = NULL;
5218         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
5219         gboolean moving_folder = FALSE;
5220         gboolean is_local_account = TRUE;
5221         GtkWidget *folder_view = NULL;
5222         ModestTnyFolderRules rules;
5223
5224         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
5225
5226         if (!selected)
5227                 return;
5228
5229         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
5230         if (!dialog)
5231                 return;
5232
5233         /* check if folder_store is an remote account */
5234         if (TNY_IS_ACCOUNT (folder_store)) {
5235                 TnyAccount *local_account = NULL;
5236                 TnyAccount *mmc_account = NULL;
5237                 ModestTnyAccountStore *account_store = NULL;
5238
5239                 account_store = modest_runtime_get_account_store ();
5240                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
5241                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
5242
5243                 if ((gpointer) local_account != (gpointer) folder_store &&
5244                     (gpointer) mmc_account != (gpointer) folder_store) {
5245                         ModestProtocolType proto;
5246                         proto = modest_tny_account_get_protocol_type (TNY_ACCOUNT (folder_store));
5247                         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
5248                                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
5249                         }
5250                         is_local_account = FALSE;
5251                         /* New button should be dimmed on remote
5252                            POP account root */
5253                         new_sensitive = (modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5254                                                                                          proto,
5255                                                                                          MODEST_PROTOCOL_REGISTRY_STORE_HAS_FOLDERS));
5256                 }
5257                 g_object_unref (local_account);
5258
5259                 /* It could not exist */
5260                 if (mmc_account)
5261                         g_object_unref (mmc_account);
5262         }
5263
5264         /* Check the target folder rules */
5265         if (TNY_IS_FOLDER (folder_store)) {
5266                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
5267                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
5268                         ok_sensitive = FALSE;
5269                         new_sensitive = FALSE;
5270                         goto end;
5271                 }
5272         }
5273
5274         /* Check if we're moving a folder */
5275         if (MODEST_IS_MAIN_WINDOW (user_data)) {
5276                 /* Get the widgets */
5277                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
5278                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5279                 if (gtk_widget_is_focus (folder_view))
5280                         moving_folder = TRUE;
5281         }
5282
5283         if (moving_folder) {
5284                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
5285
5286                 /* Get the folder to move */
5287                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5288
5289                 /* Check that we're not moving to the same folder */
5290                 if (TNY_IS_FOLDER (moved_folder)) {
5291                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
5292                         if (parent == folder_store)
5293                                 ok_sensitive = FALSE;
5294                         g_object_unref (parent);
5295                 }
5296
5297                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
5298                         /* Do not allow to move to an account unless it's the
5299                            local folders account */
5300                         if (!is_local_account)
5301                                 ok_sensitive = FALSE;
5302                 }
5303
5304                 if (ok_sensitive && (moved_folder == folder_store)) {
5305                         /* Do not allow to move to itself */
5306                         ok_sensitive = FALSE;
5307                 }
5308                 g_object_unref (moved_folder);
5309         } else {
5310                 TnyFolder *src_folder = NULL;
5311
5312                 /* Moving a message */
5313                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
5314
5315                         TnyHeader *header = NULL;
5316                         header = modest_msg_view_window_get_header
5317                                 (MODEST_MSG_VIEW_WINDOW (user_data));
5318                         if (!TNY_IS_HEADER(header))
5319                                 g_warning ("%s: could not get source header", __FUNCTION__);
5320                         else
5321                                 src_folder = tny_header_get_folder (header);
5322
5323                         if (header)
5324                                 g_object_unref (header);
5325                 } else {
5326                         src_folder =
5327                                 TNY_FOLDER (modest_folder_view_get_selected
5328                                             (MODEST_FOLDER_VIEW (folder_view)));
5329                 }
5330
5331                 if (TNY_IS_FOLDER(src_folder)) {
5332                         /* Do not allow to move the msg to the same folder */
5333                         /* Do not allow to move the msg to an account */
5334                         if ((gpointer) src_folder == (gpointer) folder_store ||
5335                             TNY_IS_ACCOUNT (folder_store))
5336                                 ok_sensitive = FALSE;
5337                         g_object_unref (src_folder);
5338                 } else
5339                         g_warning ("%s: could not get source folder", __FUNCTION__);
5340         }
5341
5342  end:
5343         /* Set sensitivity of the OK and NEW button */
5344         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK, ok_sensitive);
5345         gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), MODEST_GTK_RESPONSE_NEW_FOLDER, new_sensitive);
5346 }
5347 #endif
5348
5349 static void
5350 on_move_to_dialog_response (GtkDialog *dialog,
5351                             gint       response,
5352                             gpointer   user_data)
5353 {
5354         GtkWidget *parent_win;
5355         MoveToInfo *helper = NULL;
5356         ModestFolderView *folder_view;
5357         gboolean unset_edit_mode = FALSE;
5358
5359         helper = (MoveToInfo *) user_data;
5360
5361         parent_win = (GtkWidget *) helper->win;
5362         folder_view = MODEST_FOLDER_VIEW (g_object_get_data (G_OBJECT (dialog),
5363                                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
5364         switch (response) {
5365                 TnyFolderStore *dst_folder;
5366                 TnyFolderStore *selected;
5367
5368         case MODEST_GTK_RESPONSE_NEW_FOLDER:
5369                 selected = modest_folder_view_get_selected (folder_view);
5370                 modest_ui_actions_create_folder (GTK_WIDGET (dialog), GTK_WIDGET (folder_view), selected);
5371                 g_object_unref (selected);
5372                 return;
5373         case GTK_RESPONSE_NONE:
5374         case GTK_RESPONSE_CANCEL:
5375         case GTK_RESPONSE_DELETE_EVENT:
5376                 break;
5377         case GTK_RESPONSE_OK:
5378                 dst_folder = modest_folder_view_get_selected (folder_view);
5379
5380                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
5381                         /* Clean list to move used for filtering */
5382                         modest_folder_view_set_list_to_move (folder_view, NULL);
5383
5384                         modest_ui_actions_on_main_window_move_to (NULL,
5385                                                                   GTK_WIDGET (folder_view),
5386                                                                   dst_folder,
5387                                                                   MODEST_MAIN_WINDOW (parent_win));
5388 #ifdef MODEST_TOOLKIT_HILDON2
5389                 } else if (MODEST_IS_FOLDER_WINDOW (parent_win)) {
5390                         /* Clean list to move used for filtering */
5391                         modest_folder_view_set_list_to_move (folder_view, NULL);
5392
5393                         modest_ui_actions_on_folder_window_move_to (GTK_WIDGET (folder_view),
5394                                                                     dst_folder,
5395                                                                     helper->list,
5396                                                                     GTK_WINDOW (parent_win));
5397 #endif
5398                 } else {
5399                         /* if the user selected a root folder
5400                            (account) then do not perform any action */
5401                         if (TNY_IS_ACCOUNT (dst_folder)) {
5402                                 g_signal_stop_emission_by_name (dialog, "response");
5403                                 return;
5404                         }
5405
5406                         /* Clean list to move used for filtering */
5407                         modest_folder_view_set_list_to_move (folder_view, NULL);
5408
5409                         /* Moving from headers window in edit mode */
5410                         modest_ui_actions_on_window_move_to (NULL, helper->list,
5411                                                              dst_folder,
5412                                                              MODEST_WINDOW (parent_win));
5413                 }
5414
5415                 if (dst_folder)
5416                         g_object_unref (dst_folder);
5417
5418                 unset_edit_mode = TRUE;
5419                 break;
5420         default:
5421                 g_warning ("%s unexpected response id %d", __FUNCTION__, response);
5422         }
5423
5424         /* Free the helper and exit */
5425         if (helper->list)
5426                 g_object_unref (helper->list);
5427         if (unset_edit_mode) {
5428 #ifdef MODEST_TOOLKIT_HILDON2
5429                 modest_hildon2_window_unset_edit_mode (MODEST_HILDON2_WINDOW (helper->win));
5430 #endif
5431         }
5432         g_slice_free (MoveToInfo, helper);
5433         gtk_widget_destroy (GTK_WIDGET (dialog));
5434 }
5435
5436 static GtkWidget*
5437 create_move_to_dialog (GtkWindow *win,
5438                        GtkWidget *folder_view,
5439                        TnyList *list_to_move)
5440 {
5441         GtkWidget *dialog, *tree_view = NULL;
5442
5443         dialog = modest_platform_create_move_to_dialog (win, &tree_view);
5444
5445 #ifndef MODEST_TOOLKIT_HILDON2
5446         /* Track changes in the selection to
5447          * disable the OK button whenever "Move to" is not possible
5448          * disbale NEW button whenever New is not possible */
5449         g_signal_connect (tree_view,
5450                           "folder_selection_changed",
5451                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
5452                           win);
5453 #endif
5454
5455         /* It could happen that we're trying to move a message from a
5456            window (msg window for example) after the main window was
5457            closed, so we can not just get the model of the folder
5458            view */
5459         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
5460                 const gchar *visible_id = NULL;
5461
5462                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5463                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5464                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
5465                                                MODEST_FOLDER_VIEW(tree_view));
5466
5467                 visible_id =
5468                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
5469
5470                 /* Show the same account than the one that is shown in the main window */
5471                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(tree_view),
5472                                                                              visible_id);
5473         } else {
5474                 const gchar *active_account_name = NULL;
5475                 ModestAccountMgr *mgr = NULL;
5476                 ModestAccountSettings *settings = NULL;
5477                 ModestServerAccountSettings *store_settings = NULL;
5478
5479                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
5480                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
5481
5482                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
5483                 mgr = modest_runtime_get_account_mgr ();
5484                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
5485
5486                 if (settings) {
5487                         const gchar *store_account_name;
5488                         store_settings = modest_account_settings_get_store_settings (settings);
5489                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
5490
5491                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (tree_view),
5492                                                                                      store_account_name);
5493                         g_object_unref (store_settings);
5494                         g_object_unref (settings);
5495                 }
5496         }
5497
5498         /* we keep a pointer to the embedded folder view, so we can
5499          *   retrieve it with get_folder_view_from_move_to_dialog (see
5500          *   above) later (needed for focus handling)
5501          */
5502         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, tree_view);
5503
5504         /* Hide special folders */
5505 #ifndef MODEST_TOOLKIT_HILDON2
5506         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (tree_view), FALSE);
5507 #endif
5508         if (list_to_move)
5509                 modest_folder_view_set_list_to_move (MODEST_FOLDER_VIEW (tree_view), list_to_move);
5510 #ifndef MODEST_TOOLKIT_HILDON2
5511         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5512 #endif
5513
5514         gtk_widget_show (GTK_WIDGET (tree_view));
5515
5516         return dialog;
5517 }
5518
5519 /*
5520  * Shows a confirmation dialog to the user when we're moving messages
5521  * from a remote server to the local storage. Returns the dialog
5522  * response. If it's other kind of movement then it always returns
5523  * GTK_RESPONSE_OK
5524  *
5525  * This one is used by the next functions:
5526  *      modest_ui_actions_on_paste                      - commented out
5527  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
5528  */
5529 gint
5530 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
5531                                              TnyFolder *dest_folder,
5532                                              gboolean delete,
5533                                              TnyList *headers)
5534 {
5535         gint response = GTK_RESPONSE_OK;
5536         TnyAccount *account = NULL;
5537         TnyFolder *src_folder = NULL;
5538         TnyIterator *iter = NULL;
5539         TnyHeader *header = NULL;
5540
5541         /* return with OK if the destination is a remote folder */
5542         if (modest_tny_folder_is_remote_folder (dest_folder))
5543                 return GTK_RESPONSE_OK;
5544
5545         /* Get source folder */
5546         iter = tny_list_create_iterator (headers);
5547         header = TNY_HEADER (tny_iterator_get_current (iter));
5548         if (header) {
5549                 src_folder = tny_header_get_folder (header);
5550                 g_object_unref (header);
5551         }
5552         g_object_unref (iter);
5553
5554         /* if no src_folder, message may be an attahcment */
5555         if (src_folder == NULL)
5556                 return GTK_RESPONSE_CANCEL;
5557
5558         /* If the source is a local or MMC folder */
5559         if (!modest_tny_folder_is_remote_folder (src_folder)) {
5560                 g_object_unref (src_folder);
5561                 return GTK_RESPONSE_OK;
5562         }
5563
5564         /* Get the account */
5565         account = tny_folder_get_account (src_folder);
5566
5567         /* now if offline we ask the user */
5568         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
5569                 response = GTK_RESPONSE_OK;
5570         else
5571                 response = GTK_RESPONSE_CANCEL;
5572
5573         /* Frees */
5574         g_object_unref (src_folder);
5575         g_object_unref (account);
5576
5577         return response;
5578 }
5579
5580 static void
5581 move_to_helper_destroyer (gpointer user_data)
5582 {
5583         MoveToHelper *helper = (MoveToHelper *) user_data;
5584
5585         /* Close the "Pasting" information banner */
5586         if (helper->banner) {
5587                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
5588                 g_object_unref (helper->banner);
5589         }
5590         if (gtk_tree_row_reference_valid (helper->reference)) {
5591                 gtk_tree_row_reference_free (helper->reference);
5592                 helper->reference = NULL;
5593         }
5594         g_free (helper);
5595 }
5596
5597 static void
5598 move_to_cb (ModestMailOperation *mail_op,
5599             gpointer user_data)
5600 {
5601         MoveToHelper *helper = (MoveToHelper *) user_data;
5602         GObject *object = modest_mail_operation_get_source (mail_op);
5603
5604         /* Note that the operation could have failed, in that case do
5605            nothing */
5606         if (modest_mail_operation_get_status (mail_op) !=
5607             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5608                 goto frees;
5609
5610         if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
5611                 ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
5612
5613                 if (!modest_msg_view_window_select_next_message (self) &&
5614                     !modest_msg_view_window_select_previous_message (self)) {
5615                         /* No more messages to view, so close this window */
5616                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
5617                 }
5618         } else if (MODEST_IS_MAIN_WINDOW (object) &&
5619                    gtk_tree_row_reference_valid (helper->reference)) {
5620                 GtkWidget *header_view;
5621                 GtkTreePath *path;
5622                 GtkTreeSelection *sel;
5623
5624                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5625                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5626                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
5627                 path = gtk_tree_row_reference_get_path (helper->reference);
5628                 /* We need to unselect the previous one
5629                    because we could be copying instead of
5630                    moving */
5631                 gtk_tree_selection_unselect_all (sel);
5632                 gtk_tree_selection_select_path (sel, path);
5633                 gtk_tree_path_free (path);
5634         }
5635         g_object_unref (object);
5636
5637  frees:
5638         /* Destroy the helper */
5639         move_to_helper_destroyer (helper);
5640 }
5641
5642 static void
5643 folder_move_to_cb (ModestMailOperation *mail_op,
5644                    TnyFolder *new_folder,
5645                    gpointer user_data)
5646 {
5647         GtkWidget *folder_view;
5648         GObject *object;
5649
5650         object = modest_mail_operation_get_source (mail_op);
5651         if (MODEST_IS_MAIN_WINDOW (object)) {
5652                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
5653                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5654                 g_object_ref (folder_view);
5655                 g_object_unref (object);
5656                 move_to_cb (mail_op, user_data);
5657                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
5658                 g_object_unref (folder_view);
5659         } else {
5660                 move_to_cb (mail_op, user_data);
5661         }
5662 }
5663
5664 static void
5665 msgs_move_to_cb (ModestMailOperation *mail_op,
5666                  gpointer user_data)
5667 {
5668         move_to_cb (mail_op, user_data);
5669 }
5670
5671 void
5672 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
5673                                              gpointer user_data)
5674 {
5675         GObject *win = NULL;
5676         const GError *error;
5677         TnyAccount *account = NULL;
5678
5679 #ifndef MODEST_TOOLKIT_HILDON2
5680         ModestWindow *main_window = NULL;
5681
5682         /* Disable next automatic folder selection */
5683         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5684                                                          FALSE); /* don't create */
5685
5686         /* Show notification dialog only if the main window exists */
5687         if (main_window) {
5688                 GtkWidget *folder_view = NULL;
5689
5690                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
5691                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5692                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
5693
5694                 if (user_data && TNY_IS_FOLDER (user_data)) {
5695                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
5696                                                           TNY_FOLDER (user_data), FALSE);
5697                 }
5698         }
5699 #endif
5700         win = modest_mail_operation_get_source (mail_op);
5701         error = modest_mail_operation_get_error (mail_op);
5702
5703         if (TNY_IS_FOLDER (user_data))
5704                 account = modest_tny_folder_get_account (TNY_FOLDER (user_data));
5705         else if (TNY_IS_ACCOUNT (user_data))
5706                 account = g_object_ref (user_data);
5707
5708         /* If it's not a disk full error then show a generic error */
5709         if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5710                                                              (GtkWidget *) win, (GError *) error,
5711                                                              account, NULL))
5712                 modest_platform_run_information_dialog ((GtkWindow *) win,
5713                                                         _("mail_in_ui_folder_move_target_error"),
5714                                                         FALSE);
5715         if (account)
5716                 g_object_unref (account);
5717         if (win)
5718                 g_object_unref (win);
5719 }
5720
5721 static void
5722 open_msg_for_purge_cb (ModestMailOperation *mail_op,
5723                        TnyHeader *header,
5724                        gboolean canceled,
5725                        TnyMsg *msg,
5726                        GError *err,
5727                        gpointer user_data)
5728 {
5729         TnyList *parts;
5730         TnyIterator *iter;
5731         gint pending_purges = 0;
5732         gboolean some_purged = FALSE;
5733         ModestWindow *win = MODEST_WINDOW (user_data);
5734         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
5735
5736         /* If there was any error */
5737         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
5738                 modest_window_mgr_unregister_header (mgr, header);
5739                 return;
5740         }
5741
5742         /* Once the message has been retrieved for purging, we check if
5743          * it's all ok for purging */
5744
5745         parts = tny_simple_list_new ();
5746         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
5747         iter = tny_list_create_iterator (parts);
5748
5749         while (!tny_iterator_is_done (iter)) {
5750                 TnyMimePart *part;
5751                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5752                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
5753                         if (tny_mime_part_is_purged (part))
5754                                 some_purged = TRUE;
5755                         else
5756                                 pending_purges++;
5757                 }
5758
5759                 if (part)
5760                         g_object_unref (part);
5761
5762                 tny_iterator_next (iter);
5763         }
5764         g_object_unref (iter);
5765
5766
5767         if (pending_purges>0) {
5768                 gint response;
5769                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
5770
5771                 if (response == GTK_RESPONSE_OK) {
5772                         GtkWidget *info;
5773                         info =
5774                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_me_inbox_remove_attachments"));
5775                         iter = tny_list_create_iterator (parts);
5776                         while (!tny_iterator_is_done (iter)) {
5777                                 TnyMimePart *part;
5778
5779                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5780                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
5781                                         tny_mime_part_set_purged (part);
5782
5783                                 if (part)
5784                                         g_object_unref (part);
5785
5786                                 tny_iterator_next (iter);
5787                         }
5788                         g_object_unref (iter);
5789
5790                         tny_msg_rewrite_cache (msg);
5791
5792                         gtk_widget_destroy (info);
5793                 }
5794         }
5795
5796         modest_window_mgr_unregister_header (mgr, header);
5797
5798         g_object_unref (parts);
5799 }
5800
5801 static void
5802 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
5803                                                      ModestMainWindow *win)
5804 {
5805         GtkWidget *header_view;
5806         TnyList *header_list;
5807         TnyHeader *header;
5808         TnyHeaderFlags flags;
5809         ModestWindow *msg_view_window =  NULL;
5810         gboolean found;
5811
5812         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5813
5814         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5815                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5816
5817         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5818         if (!header_list) {
5819                 g_warning ("%s: no header selected", __FUNCTION__);
5820                 return;
5821         }
5822
5823         if (tny_list_get_length (header_list) == 1) {
5824                 TnyIterator *iter = tny_list_create_iterator (header_list);
5825                 header = TNY_HEADER (tny_iterator_get_current (iter));
5826                 g_object_unref (iter);
5827         } else
5828                 return;
5829
5830         if (!header || !TNY_IS_HEADER(header)) {
5831                 g_warning ("%s: header is not valid", __FUNCTION__);
5832                 return;
5833         }
5834
5835         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
5836                                                           header, &msg_view_window);
5837         flags = tny_header_get_flags (header);
5838         if (!(flags & TNY_HEADER_FLAG_CACHED))
5839                 return;
5840         if (found) {
5841                 if (msg_view_window != NULL)
5842                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
5843                 else {
5844                         /* do nothing; uid was registered before, so window is probably on it's way */
5845                         g_debug ("header %p has already been registered", header);
5846                 }
5847         } else {
5848                 ModestMailOperation *mail_op = NULL;
5849                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
5850                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
5851                                                                          modest_ui_actions_disk_operations_error_handler,
5852                                                                          NULL, NULL);
5853                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5854                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
5855
5856                 g_object_unref (mail_op);
5857         }
5858         if (header)
5859                 g_object_unref (header);
5860         if (header_list)
5861                 g_object_unref (header_list);
5862 }
5863
5864 /*
5865  * Checks if we need a connection to do the transfer and if the user
5866  * wants to connect to complete it
5867  */
5868 static void
5869 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5870                                        TnyFolderStore *src_folder,
5871                                        TnyList *headers,
5872                                        TnyFolder *dst_folder,
5873                                        gboolean delete_originals,
5874                                        gboolean *need_connection,
5875                                        gboolean *do_xfer)
5876 {
5877         TnyAccount *src_account;
5878         gint uncached_msgs = 0;
5879
5880         /* We don't need any further check if
5881          *
5882          * 1- the source folder is local OR
5883          * 2- the device is already online
5884          */
5885         if (!modest_tny_folder_store_is_remote (src_folder) ||
5886             tny_device_is_online (modest_runtime_get_device())) {
5887                 *need_connection = FALSE;
5888                 *do_xfer = TRUE;
5889                 return;
5890         }
5891
5892         /* We must ask for a connection when
5893          *
5894          *   - the message(s) is not already cached   OR
5895          *   - the message(s) is cached but the leave_on_server setting
5896          * is FALSE (because we need to sync the source folder to
5897          * delete the message from the server (for IMAP we could do it
5898          * offline, it'll take place the next time we get a
5899          * connection)
5900          */
5901         uncached_msgs = header_list_count_uncached_msgs (headers);
5902         src_account = get_account_from_folder_store (src_folder);
5903         if (uncached_msgs > 0) {
5904                 guint num_headers;
5905                 const gchar *msg;
5906
5907                 *need_connection = TRUE;
5908                 num_headers = tny_list_get_length (headers);
5909                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
5910
5911                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
5912                     GTK_RESPONSE_CANCEL) {
5913                         *do_xfer = FALSE;
5914                 } else {
5915                         *do_xfer = TRUE;
5916                 }
5917         } else {
5918                 /* The transfer is possible and the user wants to */
5919                 *do_xfer = TRUE;
5920
5921                 if (remote_folder_has_leave_on_server (src_folder) && delete_originals) {
5922                         const gchar *account_name;
5923                         gboolean leave_on_server;
5924
5925                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
5926                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
5927                                                                                   account_name);
5928
5929                         if (leave_on_server == TRUE) {
5930                                 *need_connection = FALSE;
5931                         } else {
5932                                 *need_connection = TRUE;
5933                         }
5934                 } else {
5935                         *need_connection = FALSE;
5936                 }
5937         }
5938
5939         /* Frees */
5940         g_object_unref (src_account);
5941 }
5942
5943 static void
5944 xfer_messages_error_handler (ModestMailOperation *mail_op,
5945                              gpointer user_data)
5946 {
5947         GObject *win;
5948         const GError *error;
5949         TnyAccount *account;
5950
5951         win = modest_mail_operation_get_source (mail_op);
5952         error = modest_mail_operation_get_error (mail_op);
5953
5954         /* We cannot get the account from the mail op as that is the
5955            source account and for checking memory full conditions we
5956            need the destination one */
5957         account = TNY_ACCOUNT (user_data);
5958
5959         if (error &&
5960             !modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5961                                                              (GtkWidget *) win, (GError*) error,
5962                                                              account, _KR("cerm_memory_card_full"))) {
5963                 modest_platform_run_information_dialog ((GtkWindow *) win,
5964                                                         _("mail_in_ui_folder_move_target_error"),
5965                                                         FALSE);
5966         }
5967         if (win)
5968                 g_object_unref (win);
5969 }
5970
5971 typedef struct {
5972         TnyFolderStore *dst_folder;
5973         TnyList *headers;
5974 } XferMsgsHelper;
5975
5976 /**
5977  * Utility function that transfer messages from both the main window
5978  * and the msg view window when using the "Move to" dialog
5979  */
5980 static void
5981 xfer_messages_performer  (gboolean canceled,
5982                           GError *err,
5983                           GtkWindow *parent_window,
5984                           TnyAccount *account,
5985                           gpointer user_data)
5986 {
5987         ModestWindow *win = MODEST_WINDOW (parent_window);
5988         TnyAccount *dst_account = NULL;
5989         gboolean dst_forbids_message_add = FALSE;
5990         XferMsgsHelper *helper;
5991         MoveToHelper *movehelper;
5992         ModestMailOperation *mail_op;
5993
5994         helper = (XferMsgsHelper *) user_data;
5995
5996         if (canceled || err) {
5997                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5998                                                                      (GtkWidget *) parent_window, err,
5999                                                                      account, NULL)) {
6000                         /* Show the proper error message */
6001                         modest_ui_actions_on_account_connection_error (parent_window, account);
6002                 }
6003                 goto end;
6004         }
6005
6006         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
6007
6008         /* tinymail will return NULL for local folders it seems */
6009         dst_forbids_message_add = modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
6010                                                                                   modest_tny_account_get_protocol_type (dst_account),
6011                                                                                   MODEST_PROTOCOL_REGISTRY_STORE_FORBID_INCOMING_XFERS);
6012
6013         if (dst_forbids_message_add) {
6014                 modest_platform_information_banner (GTK_WIDGET (win),
6015                                                     NULL,
6016                                                     ngettext("mail_in_ui_folder_move_target_error",
6017                                                              "mail_in_ui_folder_move_targets_error",
6018                                                              tny_list_get_length (helper->headers)));
6019                 goto end;
6020         }
6021
6022         movehelper = g_new0 (MoveToHelper, 1);
6023
6024 #ifndef MODEST_TOOLKIT_HILDON2
6025         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
6026                                                                _CS("ckct_nw_pasting"));
6027         if (movehelper->banner != NULL)  {
6028                 g_object_ref (movehelper->banner);
6029                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
6030         }
6031 #endif
6032
6033         if (MODEST_IS_MAIN_WINDOW (win)) {
6034                 GtkWidget *header_view =
6035                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
6036                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6037                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
6038         }
6039
6040         /* Perform the mail operation */
6041         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
6042                                                                  xfer_messages_error_handler,
6043                                                                  g_object_ref (dst_account),
6044                                                                  g_object_unref);
6045         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
6046                                          mail_op);
6047
6048         modest_mail_operation_xfer_msgs (mail_op,
6049                                          helper->headers,
6050                                          TNY_FOLDER (helper->dst_folder),
6051                                          TRUE,
6052                                          msgs_move_to_cb,
6053                                          movehelper);
6054
6055         g_object_unref (G_OBJECT (mail_op));
6056  end:
6057         if (dst_account)
6058                 g_object_unref (dst_account);
6059         g_object_unref (helper->dst_folder);
6060         g_object_unref (helper->headers);
6061         g_slice_free (XferMsgsHelper, helper);
6062 }
6063
6064 typedef struct {
6065         TnyFolder *src_folder;
6066         TnyFolderStore *dst_folder;
6067         gboolean delete_original;
6068         GtkWidget *folder_view;
6069 } MoveFolderInfo;
6070
6071 static void
6072 on_move_folder_cb (gboolean canceled,
6073                    GError *err,
6074                    GtkWindow *parent_window,
6075                    TnyAccount *account,
6076                    gpointer user_data)
6077 {
6078         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
6079         GtkTreeSelection *sel;
6080         ModestMailOperation *mail_op = NULL;
6081
6082         if (canceled || err || !MODEST_IS_WINDOW (parent_window)) {
6083                 /* Note that the connection process can fail due to
6084                    memory low conditions as it can not successfully
6085                    store the summary */
6086                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
6087                                                                      (GtkWidget*) parent_window, err,
6088                                                                      account, NULL))
6089                         g_debug ("Error connecting when trying to move a folder");
6090
6091                 g_object_unref (G_OBJECT (info->src_folder));
6092                 g_object_unref (G_OBJECT (info->dst_folder));
6093                 g_free (info);
6094                 return;
6095         }
6096
6097         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
6098 #ifndef MODEST_TOOLKIT_HILDON2
6099         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
6100                         _CS("ckct_nw_pasting"));
6101         if (helper->banner != NULL)  {
6102                 g_object_ref (helper->banner);
6103                 gtk_widget_show (GTK_WIDGET(helper->banner));
6104         }
6105 #endif
6106         /* Clean folder on header view before moving it */
6107         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
6108         gtk_tree_selection_unselect_all (sel);
6109
6110         /* Let gtk events run. We need that the folder
6111            view frees its reference to the source
6112            folder *before* issuing the mail operation
6113            so we need the signal handler of selection
6114            changed to happen before the mail
6115            operation
6116         while (gtk_events_pending ())
6117                 gtk_main_iteration ();   */
6118
6119         mail_op =
6120                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
6121                                                                modest_ui_actions_move_folder_error_handler,
6122                                                                g_object_ref (info->dst_folder), g_object_unref);
6123         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
6124                                          mail_op);
6125
6126         if (MODEST_IS_MAIN_WINDOW (parent_window)) {
6127                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
6128                                                   TNY_FOLDER (info->dst_folder), TRUE);
6129         }
6130         modest_mail_operation_xfer_folder (mail_op,
6131                         TNY_FOLDER (info->src_folder),
6132                         info->dst_folder,
6133                         info->delete_original,
6134                         folder_move_to_cb,
6135                         helper);
6136         g_object_unref (G_OBJECT (info->src_folder));
6137
6138         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
6139         /* } */
6140
6141         /* Unref mail operation */
6142         g_object_unref (G_OBJECT (mail_op));
6143         g_object_unref (G_OBJECT (info->dst_folder));
6144         g_free (user_data);
6145 }
6146
6147 static TnyAccount *
6148 get_account_from_folder_store (TnyFolderStore *folder_store)
6149 {
6150         if (TNY_IS_ACCOUNT (folder_store))
6151                 return g_object_ref (folder_store);
6152         else
6153                 return tny_folder_get_account (TNY_FOLDER (folder_store));
6154 }
6155
6156 /*
6157  * UI handler for the "Move to" action when invoked from the
6158  * ModestMainWindow
6159  */
6160 static void
6161 modest_ui_actions_on_main_window_move_to (GtkAction *action,
6162                                           GtkWidget *folder_view,
6163                                           TnyFolderStore *dst_folder,
6164                                           ModestMainWindow *win)
6165 {
6166         ModestHeaderView *header_view = NULL;
6167         TnyFolderStore *src_folder = NULL;
6168
6169         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
6170
6171         /* Get the source folder */
6172         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6173
6174         /* Get header view */
6175         header_view = (ModestHeaderView *)
6176                 modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6177
6178         /* Get folder or messages to transfer */
6179         if (gtk_widget_is_focus (folder_view)) {
6180                 gboolean do_xfer = TRUE;
6181
6182                 /* Allow only to transfer folders to the local root folder */
6183                 if (TNY_IS_ACCOUNT (dst_folder) &&
6184                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
6185                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
6186                         do_xfer = FALSE;
6187                 } else if (!TNY_IS_FOLDER (src_folder)) {
6188                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
6189                         do_xfer = FALSE;
6190                 }
6191
6192                 if (do_xfer) {
6193                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
6194                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
6195
6196                         info->src_folder = g_object_ref (src_folder);
6197                         info->dst_folder = g_object_ref (dst_folder);
6198                         info->delete_original = TRUE;
6199                         info->folder_view = folder_view;
6200
6201                         connect_info->callback = on_move_folder_cb;
6202                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
6203                         connect_info->data = info;
6204
6205                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
6206                                                                    TNY_FOLDER_STORE (src_folder),
6207                                                                    connect_info);
6208                 }
6209         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
6210                 TnyList *headers;
6211
6212                 headers = modest_header_view_get_selected_headers(header_view);
6213
6214                 /* Transfer the messages */
6215                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder),
6216                                                             headers, TNY_FOLDER (dst_folder));
6217
6218                 g_object_unref (headers);
6219         }
6220
6221         /* Frees */
6222         g_object_unref (src_folder);
6223 }
6224
6225 #ifdef MODEST_TOOLKIT_HILDON2
6226 /*
6227  * UI handler for the "Move to" action when invoked from the
6228  * ModestFolderWindow
6229  */
6230 static void
6231 modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
6232                                             TnyFolderStore *dst_folder,
6233                                             TnyList *selection,
6234                                             GtkWindow *win)
6235 {
6236         TnyFolderStore *src_folder = NULL;
6237         TnyIterator *iterator;
6238
6239         if (tny_list_get_length (selection) != 1)
6240                 return;
6241
6242         iterator = tny_list_create_iterator (selection);
6243         src_folder = TNY_FOLDER_STORE (tny_iterator_get_current (iterator));
6244         g_object_unref (iterator);
6245
6246
6247         gboolean do_xfer = TRUE;
6248
6249         /* Allow only to transfer folders to the local root folder */
6250         if (TNY_IS_ACCOUNT (dst_folder) &&
6251             !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
6252             !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
6253                 do_xfer = FALSE;
6254                 /* Show an error */
6255                 modest_platform_run_information_dialog (win,
6256                                                         _("mail_in_ui_folder_move_target_error"),
6257                                                         FALSE);
6258         } else if (!TNY_IS_FOLDER (src_folder)) {
6259                 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
6260                 do_xfer = FALSE;
6261         }
6262
6263         if (do_xfer) {
6264                 MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
6265                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
6266
6267                 info->src_folder = g_object_ref (src_folder);
6268                 info->dst_folder = g_object_ref (dst_folder);
6269                 info->delete_original = TRUE;
6270                 info->folder_view = folder_view;
6271
6272                 connect_info->callback = on_move_folder_cb;
6273                 connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
6274                 connect_info->data = info;
6275
6276                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
6277                                                            TNY_FOLDER_STORE (src_folder),
6278                                                            connect_info);
6279         }
6280
6281         /* Frees */
6282         g_object_unref (src_folder);
6283 }
6284 #endif
6285
6286
6287 void
6288 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
6289                                             TnyFolder *src_folder,
6290                                             TnyList *headers,
6291                                             TnyFolder *dst_folder)
6292 {
6293         gboolean need_connection = TRUE;
6294         gboolean do_xfer = TRUE;
6295         XferMsgsHelper *helper;
6296
6297         g_return_if_fail (TNY_IS_FOLDER (src_folder));
6298         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
6299         g_return_if_fail (TNY_IS_LIST (headers));
6300
6301         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder),
6302                                                headers, TNY_FOLDER (dst_folder),
6303                                                TRUE, &need_connection,
6304                                                &do_xfer);
6305
6306         /* If we don't want to transfer just return */
6307         if (!do_xfer)
6308                 return;
6309
6310         /* Create the helper */
6311         helper = g_slice_new (XferMsgsHelper);
6312         helper->dst_folder = g_object_ref (dst_folder);
6313         helper->headers = g_object_ref (headers);
6314
6315         if (need_connection) {
6316                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
6317                 connect_info->callback = xfer_messages_performer;
6318                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
6319                 connect_info->data = helper;
6320
6321                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
6322                                                            TNY_FOLDER_STORE (src_folder),
6323                                                            connect_info);
6324         } else {
6325                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
6326                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
6327                                          src_account, helper);
6328                 g_object_unref (src_account);
6329         }
6330 }
6331
6332 /*
6333  * UI handler for the "Move to" action when invoked from the
6334  * ModestMsgViewWindow
6335  */
6336 static void
6337 modest_ui_actions_on_window_move_to (GtkAction *action,
6338                                      TnyList *headers,
6339                                      TnyFolderStore *dst_folder,
6340                                      ModestWindow *win)
6341 {
6342         TnyFolder *src_folder = NULL;
6343
6344         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
6345
6346         if (headers) {
6347                 TnyHeader *header = NULL;
6348                 TnyIterator *iter;
6349
6350                 iter = tny_list_create_iterator (headers);
6351                 header = (TnyHeader *) tny_iterator_get_current (iter);
6352                 src_folder = tny_header_get_folder (header);
6353
6354                 /* Transfer the messages */
6355                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder,
6356                                                             headers,
6357                                                             TNY_FOLDER (dst_folder));
6358
6359                 /* Frees */
6360                 g_object_unref (header);
6361                 g_object_unref (iter);
6362                 g_object_unref (src_folder);
6363         }
6364 }
6365
6366 void
6367 modest_ui_actions_on_move_to (GtkAction *action,
6368                               ModestWindow *win)
6369 {
6370         modest_ui_actions_on_edit_mode_move_to (win);
6371 }
6372
6373 gboolean
6374 modest_ui_actions_on_edit_mode_move_to (ModestWindow *win)
6375 {
6376         GtkWidget *dialog = NULL;
6377         MoveToInfo *helper = NULL;
6378         TnyList *list_to_move;
6379
6380         g_return_val_if_fail (MODEST_IS_WINDOW (win), FALSE);
6381
6382 #ifndef MODEST_TOOLKIT_HILDON2
6383         /* Get the main window if exists */
6384         ModestMainWindow *main_window;
6385         if (MODEST_IS_MAIN_WINDOW (win))
6386                 main_window = MODEST_MAIN_WINDOW (win);
6387         else
6388                 main_window =
6389                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
6390                                                                                FALSE)); /* don't create */
6391 #endif
6392
6393         list_to_move = modest_platform_get_list_to_move (MODEST_WINDOW (win));
6394
6395         if (!list_to_move)
6396                 return FALSE;
6397
6398         if (tny_list_get_length (list_to_move) < 1) {
6399                 g_object_unref (list_to_move);
6400                 return FALSE;
6401         }
6402
6403         /* Create and run the dialog */
6404         dialog = create_move_to_dialog (GTK_WINDOW (win), NULL, list_to_move);
6405         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
6406                                      GTK_WINDOW (dialog),
6407                                      (GtkWindow *) win);
6408
6409         /* Create helper */
6410         helper = g_slice_new0 (MoveToInfo);
6411         helper->list = list_to_move;
6412         helper->win = win;
6413
6414         /* Listen to response signal */
6415         g_signal_connect (dialog, "response", G_CALLBACK (on_move_to_dialog_response), helper);
6416
6417         /* Show the dialog */
6418         gtk_widget_show (dialog);
6419
6420         return FALSE;
6421 }
6422
6423 /*
6424  * Calls #HeadersFunc for each header already selected in the main
6425  * window or the message currently being shown in the msg view window
6426  */
6427 static void
6428 do_headers_action (ModestWindow *win,
6429                    HeadersFunc func,
6430                    gpointer user_data)
6431 {
6432         TnyList *headers_list = NULL;
6433         TnyIterator *iter = NULL;
6434         TnyHeader *header = NULL;
6435         TnyFolder *folder = NULL;
6436
6437         /* Get headers */
6438         headers_list = get_selected_headers (win);
6439         if (!headers_list)
6440                 return;
6441
6442         /* Get the folder */
6443         iter = tny_list_create_iterator (headers_list);
6444         header = TNY_HEADER (tny_iterator_get_current (iter));
6445         if (header) {
6446                 folder = tny_header_get_folder (header);
6447                 g_object_unref (header);
6448         }
6449
6450         /* Call the function for each header */
6451         while (!tny_iterator_is_done (iter)) {
6452                 header = TNY_HEADER (tny_iterator_get_current (iter));
6453                 func (header, win, user_data);
6454                 g_object_unref (header);
6455                 tny_iterator_next (iter);
6456         }
6457
6458         /* Trick: do a poke status in order to speed up the signaling
6459            of observers */
6460         if (folder) {
6461                 tny_folder_poke_status (folder);
6462                 g_object_unref (folder);
6463         }
6464
6465         /* Frees */
6466         g_object_unref (iter);
6467         g_object_unref (headers_list);
6468 }
6469
6470 void
6471 modest_ui_actions_view_attachment (GtkAction *action,
6472                                    ModestWindow *window)
6473 {
6474         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6475                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
6476         } else {
6477                 /* not supported window for this action */
6478                 g_return_if_reached ();
6479         }
6480 }
6481
6482 void
6483 modest_ui_actions_save_attachments (GtkAction *action,
6484                                     ModestWindow *window)
6485 {
6486         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6487
6488                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
6489                         return;
6490
6491                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
6492         } else {
6493                 /* not supported window for this action */
6494                 g_return_if_reached ();
6495         }
6496 }
6497
6498 void
6499 modest_ui_actions_remove_attachments (GtkAction *action,
6500                                       ModestWindow *window)
6501 {
6502         if (MODEST_IS_MAIN_WINDOW (window)) {
6503                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
6504         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
6505                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
6506         } else {
6507                 /* not supported window for this action */
6508                 g_return_if_reached ();
6509         }
6510 }
6511
6512 void
6513 modest_ui_actions_on_settings (GtkAction *action,
6514                                ModestWindow *win)
6515 {
6516         GtkWidget *dialog;
6517
6518         dialog = modest_platform_get_global_settings_dialog ();
6519         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
6520         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
6521         gtk_widget_show_all (dialog);
6522
6523         gtk_dialog_run (GTK_DIALOG (dialog));
6524
6525         gtk_widget_destroy (dialog);
6526 }
6527
6528 void
6529 modest_ui_actions_on_help (GtkAction *action,
6530                            GtkWindow *win)
6531 {
6532         /* Help app is not available at all in fremantle */
6533 #ifndef MODEST_TOOLKIT_HILDON2
6534         const gchar *help_id;
6535
6536         g_return_if_fail (win && GTK_IS_WINDOW(win));
6537
6538         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
6539
6540         if (help_id)
6541                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6542 #endif
6543 }
6544
6545 void
6546 modest_ui_actions_on_csm_help (GtkAction *action,
6547                                GtkWindow *win)
6548 {
6549         /* Help app is not available at all in fremantle */
6550 #ifndef MODEST_TOOLKIT_HILDON2
6551
6552         const gchar* help_id = NULL;
6553         GtkWidget *folder_view;
6554         TnyFolderStore *folder_store;
6555
6556         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
6557
6558         /* Get selected folder */
6559         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
6560                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6561         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6562
6563         /* Switch help_id */
6564         if (folder_store && TNY_IS_FOLDER (folder_store))
6565                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
6566
6567         if (folder_store)
6568                 g_object_unref (folder_store);
6569
6570         if (help_id)
6571                 modest_platform_show_help (GTK_WINDOW (win), help_id);
6572         else
6573                 modest_ui_actions_on_help (action, win);
6574 #endif
6575 }
6576
6577 static void
6578 retrieve_contents_cb (ModestMailOperation *mail_op,
6579                       TnyHeader *header,
6580                       gboolean canceled,
6581                       TnyMsg *msg,
6582                       GError *err,
6583                       gpointer user_data)
6584 {
6585         /* We only need this callback to show an error in case of
6586            memory low condition */
6587         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
6588                 g_debug ("%s: message failed to retrieve. Memory low?", __FUNCTION__);
6589         }
6590 }
6591
6592 static void
6593 retrieve_msg_contents_performer (gboolean canceled,
6594                                  GError *err,
6595                                  GtkWindow *parent_window,
6596                                  TnyAccount *account,
6597                                  gpointer user_data)
6598 {
6599         ModestMailOperation *mail_op;
6600         TnyList *headers = TNY_LIST (user_data);
6601
6602         if (err || canceled) {
6603                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
6604                                                                 (GtkWidget *) parent_window, err,
6605                                                                 account, NULL);
6606                 goto out;
6607         }
6608
6609         /* Create mail operation */
6610         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
6611                                                                  modest_ui_actions_disk_operations_error_handler,
6612                                                                  NULL, NULL);
6613         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
6614         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
6615
6616         /* Frees */
6617         g_object_unref (mail_op);
6618  out:
6619         g_object_unref (headers);
6620         g_object_unref (account);
6621 }
6622
6623 void
6624 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
6625                                             ModestWindow *window)
6626 {
6627         TnyList *headers = NULL;
6628         TnyAccount *account = NULL;
6629         TnyIterator *iter = NULL;
6630         TnyHeader *header = NULL;
6631         TnyFolder *folder = NULL;
6632
6633         /* Get headers */
6634         headers = get_selected_headers (window);
6635         if (!headers)
6636                 return;
6637
6638         /* Pick the account */
6639         iter = tny_list_create_iterator (headers);
6640         header = TNY_HEADER (tny_iterator_get_current (iter));
6641         folder = tny_header_get_folder (header);
6642         account = tny_folder_get_account (folder);
6643         g_object_unref (folder);
6644         g_object_unref (header);
6645         g_object_unref (iter);
6646
6647         /* Connect and perform the message retrieval */
6648         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
6649                                              g_object_ref (account),
6650                                              retrieve_msg_contents_performer,
6651                                              g_object_ref (headers));
6652
6653         /* Frees */
6654         g_object_unref (account);
6655         g_object_unref (headers);
6656 }
6657
6658 void
6659 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
6660 {
6661         g_return_if_fail (MODEST_IS_WINDOW (window));
6662
6663         /* Update dimmed */
6664         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
6665 }
6666
6667 void
6668 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
6669 {
6670         g_return_if_fail (MODEST_IS_WINDOW (window));
6671
6672         /* Update dimmed */
6673         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
6674 }
6675
6676 void
6677 modest_ui_actions_on_email_menu_activated (GtkAction *action,
6678                                           ModestWindow *window)
6679 {
6680         g_return_if_fail (MODEST_IS_WINDOW (window));
6681
6682         /* Update dimmed */
6683         modest_ui_actions_check_menu_dimming_rules (window);
6684 }
6685
6686 void
6687 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
6688                                           ModestWindow *window)
6689 {
6690         g_return_if_fail (MODEST_IS_WINDOW (window));
6691
6692         /* Update dimmed */
6693         modest_ui_actions_check_menu_dimming_rules (window);
6694 }
6695
6696 void
6697 modest_ui_actions_on_view_menu_activated (GtkAction *action,
6698                                           ModestWindow *window)
6699 {
6700         g_return_if_fail (MODEST_IS_WINDOW (window));
6701
6702         /* Update dimmed */
6703         modest_ui_actions_check_menu_dimming_rules (window);
6704 }
6705
6706 void
6707 modest_ui_actions_on_format_menu_activated (GtkAction *action,
6708                                             ModestWindow *window)
6709 {
6710         g_return_if_fail (MODEST_IS_WINDOW (window));
6711
6712         /* Update dimmed */
6713         modest_ui_actions_check_menu_dimming_rules (window);
6714 }
6715
6716 void
6717 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
6718                                           ModestWindow *window)
6719 {
6720         g_return_if_fail (MODEST_IS_WINDOW (window));
6721
6722         /* Update dimmed */
6723         modest_ui_actions_check_menu_dimming_rules (window);
6724 }
6725
6726 void
6727 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
6728                                           ModestWindow *window)
6729 {
6730         g_return_if_fail (MODEST_IS_WINDOW (window));
6731
6732         /* Update dimmed */
6733         modest_ui_actions_check_menu_dimming_rules (window);
6734 }
6735
6736 void
6737 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
6738                                                  ModestWindow *window)
6739 {
6740         g_return_if_fail (MODEST_IS_WINDOW (window));
6741
6742         /* Update dimmed */
6743         modest_ui_actions_check_menu_dimming_rules (window);
6744 }
6745
6746 void
6747 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
6748                                                      ModestWindow *window)
6749 {
6750         g_return_if_fail (MODEST_IS_WINDOW (window));
6751
6752         /* Update dimmed */
6753         modest_ui_actions_check_menu_dimming_rules (window);
6754 }
6755
6756 void
6757 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
6758                                                      ModestWindow *window)
6759 {
6760         g_return_if_fail (MODEST_IS_WINDOW (window));
6761
6762         /* Update dimmed */
6763         modest_ui_actions_check_menu_dimming_rules (window);
6764 }
6765
6766 void
6767 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
6768 {
6769         g_return_if_fail (MODEST_IS_WINDOW (window));
6770
6771         /* we check for low-mem; in that case, show a warning, and don't allow
6772          * searching
6773          */
6774         if (modest_platform_check_memory_low (window, TRUE))
6775                 return;
6776
6777         modest_platform_show_search_messages (GTK_WINDOW (window));
6778 }
6779
6780 void
6781 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
6782 {
6783         g_return_if_fail (MODEST_IS_WINDOW (win));
6784
6785
6786         /* we check for low-mem; in that case, show a warning, and don't allow
6787          * for the addressbook
6788          */
6789         if (modest_platform_check_memory_low (win, TRUE))
6790                 return;
6791
6792
6793         modest_platform_show_addressbook (GTK_WINDOW (win));
6794 }
6795
6796
6797 void
6798 modest_ui_actions_on_toggle_find_in_page (GtkAction *action,
6799                                           ModestWindow *window)
6800 {
6801         gboolean active;
6802         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
6803
6804         if (GTK_IS_TOGGLE_ACTION (action))
6805                 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
6806         else
6807                 active = TRUE;
6808
6809         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window),
6810                                                     active);
6811 }
6812
6813 static void
6814 on_send_receive_finished (ModestMailOperation  *mail_op,
6815                            gpointer user_data)
6816 {
6817         GtkWidget *header_view, *folder_view;
6818         TnyFolderStore *folder_store;
6819         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
6820
6821         /* Set send/receive operation finished */
6822         modest_main_window_notify_send_receive_completed (main_win);
6823
6824         /* Don't refresh the current folder if there were any errors */
6825         if (modest_mail_operation_get_status (mail_op) !=
6826             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
6827                 return;
6828
6829         /* Refresh the current folder if we're viewing a window. We do
6830            this because the user won't be able to see the new mails in
6831            the selected folder after a Send&Receive because it only
6832            performs a poke_status, i.e, only the number of read/unread
6833            messages is updated, but the new headers are not
6834            downloaded */
6835         folder_view = modest_main_window_get_child_widget (main_win,
6836                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6837         if (!folder_view)
6838                 return;
6839
6840         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6841
6842         /* Do not need to refresh INBOX again because the
6843            update_account does it always automatically */
6844         if (folder_store && TNY_IS_FOLDER (folder_store) &&
6845             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
6846                 ModestMailOperation *refresh_op;
6847
6848                 header_view = modest_main_window_get_child_widget (main_win,
6849                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6850
6851                 /* We do not need to set the contents style
6852                    because it hasn't changed. We also do not
6853                    need to save the widget status. Just force
6854                    a refresh */
6855                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
6856                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
6857                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
6858                                                       folder_refreshed_cb, main_win);
6859                 g_object_unref (refresh_op);
6860         }
6861
6862         if (folder_store)
6863                 g_object_unref (folder_store);
6864 }
6865
6866
6867 void
6868 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self,
6869                                                 TnyHeader *header,
6870                                                 TnyMsg *msg,
6871                                                 GError *err,
6872                                                 gpointer user_data)
6873 {
6874         const gchar* server_name = NULL;
6875         TnyTransportAccount *transport;
6876         gchar *message = NULL;
6877         ModestProtocol *protocol;
6878
6879         /* Don't show anything if the user cancelled something or the
6880          * send receive request is not interactive. Authentication
6881          * errors are managed by the account store so no need to show
6882          * a dialog here again */
6883         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
6884             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
6885             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
6886                 return;
6887
6888
6889         /* Get the server name. Note that we could be using a
6890            connection specific transport account */
6891         transport = (TnyTransportAccount *)
6892                 tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self));
6893         if (transport) {
6894                 ModestTnyAccountStore *acc_store;
6895                 const gchar *acc_name;
6896                 TnyTransportAccount *conn_specific;
6897
6898                 acc_store = modest_runtime_get_account_store();
6899                 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT (transport));
6900                 conn_specific = (TnyTransportAccount *)
6901                         modest_tny_account_store_get_transport_account_for_open_connection (acc_store, acc_name);
6902                 if (conn_specific) {
6903                         server_name = tny_account_get_hostname (TNY_ACCOUNT (conn_specific));
6904                         g_object_unref (conn_specific);
6905                 } else {
6906                         server_name = tny_account_get_hostname (TNY_ACCOUNT (transport));
6907                 }
6908                 g_object_unref (transport);
6909         }
6910
6911         /* Get protocol */
6912         protocol = modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
6913                                                                   MODEST_PROTOCOL_REGISTRY_TRANSPORT_STORE_PROTOCOLS,
6914                                                                   tny_account_get_proto (TNY_ACCOUNT (transport)));
6915         if (!protocol) {
6916                 g_warning ("%s: Account with no proto", __FUNCTION__);
6917                 return;
6918         }
6919
6920         /* Show the appropriate message text for the GError: */
6921         switch (err->code) {
6922         case TNY_SERVICE_ERROR_CONNECT:
6923                 message = modest_protocol_get_translation (protocol,
6924                                                            MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR,
6925                                                            server_name);
6926                 break;
6927         case TNY_SERVICE_ERROR_SEND:
6928                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6929                 break;
6930         case TNY_SERVICE_ERROR_UNAVAILABLE:
6931                 message = modest_protocol_get_translation (protocol,
6932                                                            MODEST_PROTOCOL_TRANSLATION_CONNECT_ERROR,
6933                                                            server_name);
6934                 break;
6935         default:
6936                 g_warning ("%s: unexpected ERROR %d",
6937                            __FUNCTION__, err->code);
6938                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
6939                 break;
6940         }
6941
6942         modest_platform_run_information_dialog (NULL, message, FALSE);
6943         g_free (message);
6944 }
6945
6946 void
6947 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
6948                                                 gchar *msg_id,
6949                                                 guint status,
6950                                                 gpointer user_data)
6951 {
6952         ModestWindow *top_window = NULL;
6953         ModestWindowMgr *mgr = NULL;
6954         GtkWidget *header_view = NULL;
6955         TnyFolder *selected_folder = NULL;
6956         TnyFolderType folder_type;
6957
6958         mgr = modest_runtime_get_window_mgr ();
6959         top_window = modest_window_mgr_get_current_top (mgr);
6960
6961         if (!top_window)
6962                 return;
6963
6964 #ifndef MODEST_TOOLKIT_HILDON2
6965         if (MODEST_IS_MAIN_WINDOW (top_window)) {
6966                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (top_window),
6967                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6968         }
6969 #else
6970         if (MODEST_IS_HEADER_WINDOW (top_window)) {
6971                 header_view = (GtkWidget *)
6972                         modest_header_window_get_header_view (MODEST_HEADER_WINDOW (top_window));
6973         }
6974 #endif
6975
6976         /* Get selected folder */
6977         if (header_view)
6978                 selected_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
6979         if (!selected_folder)
6980                 return;
6981
6982         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
6983 #if GTK_CHECK_VERSION(2, 8, 0)
6984         folder_type = modest_tny_folder_guess_folder_type (selected_folder);
6985         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {
6986                 GtkTreeViewColumn *tree_column;
6987
6988                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view),
6989                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
6990                 if (tree_column)
6991                         gtk_tree_view_column_queue_resize (tree_column);
6992                 }
6993 #else /* #if GTK_CHECK_VERSION(2, 8, 0) */
6994         gtk_widget_queue_draw (header_view);
6995 #endif
6996
6997 #ifndef MODEST_TOOLKIT_HILDON2
6998         /* Rerun dimming rules, because the message could become deletable for example */
6999         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
7000                                                  MODEST_DIMMING_RULES_TOOLBAR);
7001         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
7002                                                  MODEST_DIMMING_RULES_MENU);
7003 #endif
7004
7005         /* Free */
7006         g_object_unref (selected_folder);
7007 }
7008
7009 void
7010 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
7011                                                TnyAccount *account)
7012 {
7013         ModestProtocolType protocol_type;
7014         ModestProtocol *protocol;
7015         gchar *error_note = NULL;
7016
7017         protocol_type = modest_tny_account_get_protocol_type (account);
7018         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
7019                                                                   protocol_type);
7020
7021         error_note = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR, tny_account_get_hostname (account));
7022         if (error_note == NULL) {
7023                 g_warning ("%s: This should not be reached", __FUNCTION__);
7024         } else {
7025                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
7026                 g_free (error_note);
7027         }
7028 }
7029
7030 gchar *
7031 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
7032 {
7033         gchar *msg = NULL;
7034         gchar *subject;
7035         TnyFolderStore *folder = NULL;
7036         TnyAccount *account = NULL;
7037         ModestProtocolType proto;
7038         ModestProtocol *protocol;
7039         TnyHeader *header = NULL;
7040
7041         if (MODEST_IS_MAIN_WINDOW (win)) {
7042                 GtkWidget *header_view;
7043                 TnyList* headers = NULL;
7044                 TnyIterator *iter;
7045                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
7046                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
7047                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
7048                 if (!headers || tny_list_get_length (headers) == 0) {
7049                         if (headers)
7050                                 g_object_unref (headers);
7051                         return NULL;
7052                 }
7053                 iter = tny_list_create_iterator (headers);
7054                 header = TNY_HEADER (tny_iterator_get_current (iter));
7055                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
7056                 g_object_unref (iter);
7057                 g_object_unref (headers);
7058 #ifdef MODEST_TOOLKIT_HILDON2
7059         } else if (MODEST_IS_HEADER_WINDOW (win)) {
7060                 GtkWidget *header_view;
7061                 TnyList* headers = NULL;
7062                 TnyIterator *iter;
7063                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
7064                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
7065                 if (!headers || tny_list_get_length (headers) == 0) {
7066                         if (headers)
7067                                 g_object_unref (headers);
7068                         return NULL;
7069                 }
7070                 iter = tny_list_create_iterator (headers);
7071                 header = TNY_HEADER (tny_iterator_get_current (iter));
7072                 if (header) {
7073                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
7074                 } else {
7075                         g_warning ("List should contain headers");
7076                 }
7077                 g_object_unref (iter);
7078                 g_object_unref (headers);
7079 #endif
7080         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
7081                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
7082                 if (header)
7083                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
7084         }
7085
7086         if (!header || !folder)
7087                 goto frees;
7088
7089         /* Get the account type */
7090         account = tny_folder_get_account (TNY_FOLDER (folder));
7091         proto = modest_tny_account_get_protocol_type (account);
7092         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
7093                                                                   proto);
7094
7095         subject = tny_header_dup_subject (header);
7096         msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
7097         if (subject)
7098                 g_free (subject);
7099         if (msg == NULL) {
7100                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
7101         }
7102
7103  frees:
7104         /* Frees */
7105         if (account)
7106                 g_object_unref (account);
7107         if (folder)
7108                 g_object_unref (folder);
7109         if (header)
7110                 g_object_unref (header);
7111
7112         return msg;
7113 }
7114
7115 gboolean
7116 modest_ui_actions_on_delete_account (GtkWindow *parent_window,
7117                                      const gchar *account_name,
7118                                      const gchar *account_title)
7119 {
7120         ModestAccountMgr *account_mgr;
7121         gchar *txt = NULL;
7122         gint response;
7123         ModestProtocol *protocol;
7124         gboolean removed = FALSE;
7125
7126         g_return_val_if_fail (account_name, FALSE);
7127         g_return_val_if_fail (account_title, FALSE);
7128
7129         account_mgr = modest_runtime_get_account_mgr();
7130
7131         /* The warning text depends on the account type: */
7132         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
7133                                                                   modest_account_mgr_get_store_protocol (account_mgr,
7134                                                                                                          account_name));
7135         txt = modest_protocol_get_translation (protocol,
7136                                                MODEST_PROTOCOL_TRANSLATION_DELETE_MAILBOX,
7137                                                account_title);
7138         if (txt == NULL)
7139                 txt = g_strdup_printf (_("emev_nc_delete_mailbox"), account_title);
7140
7141         response = modest_platform_run_confirmation_dialog (parent_window, txt);
7142         g_free (txt);
7143         txt = NULL;
7144
7145         if (response == GTK_RESPONSE_OK) {
7146                 /* Remove account. If it succeeds then it also removes
7147                    the account from the ModestAccountView: */
7148                 gboolean is_default = FALSE;
7149                 gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr);
7150                 if (default_account_name && (strcmp (default_account_name, account_name) == 0))
7151                         is_default = TRUE;
7152                 g_free (default_account_name);
7153
7154                 removed = modest_account_mgr_remove_account (account_mgr, account_name);
7155                 if (removed) {
7156 #ifdef MODEST_TOOLKIT_HILDON2
7157                         hildon_gtk_window_take_screenshot (parent_window, FALSE);
7158 #endif
7159                         /* Close all email notifications, we cannot
7160                            distinguish if the notification belongs to
7161                            this account or not, so for safety reasons
7162                            we remove them all */
7163                         modest_platform_remove_new_mail_notifications (FALSE, account_name);
7164                 } else {
7165                         g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__);
7166                 }
7167         }
7168         return removed;
7169 }
7170
7171 static void
7172 on_fetch_images_performer (gboolean canceled,
7173                            GError *err,
7174                            GtkWindow *parent_window,
7175                            TnyAccount *account,
7176                            gpointer user_data)
7177 {
7178         if (err || canceled) {
7179                 /* Show an unable to retrieve images ??? */
7180                 return;
7181         }
7182
7183         /* Note that the user could have closed the window while connecting */
7184         if (GTK_WIDGET_VISIBLE (parent_window))
7185                 modest_msg_view_window_fetch_images ((ModestMsgViewWindow *) parent_window);
7186         g_object_unref ((GObject *) user_data);
7187 }
7188
7189 void
7190 modest_ui_actions_on_fetch_images (GtkAction *action,
7191                                    ModestWindow *window)
7192 {
7193         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
7194
7195         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE, 
7196                                              NULL,
7197                                              on_fetch_images_performer, 
7198                                              g_object_ref (window));
7199 }
7200
7201 void
7202 modest_ui_actions_on_reload_message (const gchar *msg_id)
7203 {
7204         ModestWindow *window = NULL;
7205
7206         g_return_if_fail (msg_id && msg_id[0] != '\0');
7207         if (!modest_window_mgr_find_registered_message_uid (modest_runtime_get_window_mgr (),
7208                                                             msg_id,
7209                                                             &window))
7210                 return;
7211
7212
7213         if (window == NULL || !MODEST_IS_MSG_VIEW_WINDOW (window))
7214                 return;
7215
7216         modest_msg_view_window_reload (MODEST_MSG_VIEW_WINDOW (window));
7217 }
7218
7219 /** Check whether any connections are active, and cancel them if 
7220  * the user wishes.
7221  * Returns TRUE is there was no problem, 
7222  * or if an operation was cancelled so we can continue.
7223  * Returns FALSE if the user chose to cancel his request instead.
7224  */
7225
7226 gboolean
7227 modest_ui_actions_check_for_active_account (ModestWindow *self,
7228                                             const gchar* account_name)
7229 {
7230         ModestTnySendQueue *send_queue;
7231         ModestTnyAccountStore *acc_store;
7232         ModestMailOperationQueue* queue;
7233         TnyConnectionStatus store_conn_status;
7234         TnyAccount *store_account = NULL, *transport_account = NULL;
7235         gboolean retval = TRUE, sending = FALSE;
7236
7237         acc_store = modest_runtime_get_account_store ();
7238         queue = modest_runtime_get_mail_operation_queue ();
7239
7240         store_account = 
7241                 modest_tny_account_store_get_server_account (acc_store,
7242                                                              account_name,
7243                                                              TNY_ACCOUNT_TYPE_STORE);
7244
7245         /* This could happen if the account was deleted before the
7246            call to this function */
7247         if (!store_account)
7248                 return FALSE;
7249
7250         transport_account = 
7251                 modest_tny_account_store_get_server_account (acc_store,
7252                                                              account_name,
7253                                                              TNY_ACCOUNT_TYPE_TRANSPORT);
7254
7255         /* This could happen if the account was deleted before the
7256            call to this function */
7257         if (!transport_account) {
7258                 g_object_unref (store_account);
7259                 return FALSE;
7260         }
7261
7262         /* If the transport account was not used yet, then the send
7263            queue could not exist (it's created on demand) */
7264         send_queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (transport_account), FALSE);
7265         if (TNY_IS_SEND_QUEUE (send_queue))
7266                 sending = modest_tny_send_queue_sending_in_progress (send_queue);
7267
7268         store_conn_status = tny_account_get_connection_status (store_account);
7269         if (store_conn_status == TNY_CONNECTION_STATUS_CONNECTED || sending) {
7270                 gint response;
7271
7272                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (self), 
7273                                                                 _("emev_nc_disconnect_account"));
7274                 if (response == GTK_RESPONSE_OK) {
7275                         retval = TRUE;
7276                 } else {
7277                         retval = FALSE;
7278                 }
7279         }
7280
7281         if (retval) {
7282
7283                 /* FIXME: We should only cancel those of this account */
7284                 modest_mail_operation_queue_cancel_all (queue);
7285
7286                 /* Also disconnect the account */
7287                 if ((tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED) &&
7288                     (tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED_BROKEN)) {
7289                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (store_account),
7290                                                       FALSE, NULL, NULL);
7291                 }
7292                 if (sending) {
7293                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (transport_account),
7294                                                       FALSE, NULL, NULL);
7295                 }
7296         }
7297                 
7298         /* Frees */
7299         g_object_unref (store_account);
7300         g_object_unref (transport_account);
7301         
7302         return retval;
7303 }