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