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