Fix modest_utils_show_dialog_and_forget for gtk and modest shell
[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 (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 (GTK_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 (source_win, parent_folder, (const gchar *) suggested_name);
2905                 }
2906
2907         } else {
2908                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
2909                  * FIXME: any other? */
2910                 GtkWidget *folder_view;
2911
2912                         folder_view = GTK_WIDGET(g_object_get_data (G_OBJECT (source_win),
2913                                                                     MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
2914
2915                 /* Select the newly created folder. It could happen
2916                    that the widget is no longer there (i.e. the window
2917                    has been destroyed, so we need to check this */
2918                 if (folder_view)
2919                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
2920                                                           new_folder, FALSE);
2921                 g_object_unref (new_folder);
2922         }
2923         /* Free. Note that the first time it'll be NULL so noop */
2924         g_free (suggested_name);
2925         g_object_unref (source_win);
2926 }
2927
2928 typedef struct {
2929         gchar *folder_name;
2930         TnyFolderStore *parent;
2931 } CreateFolderConnect;
2932
2933 static void
2934 do_create_folder_performer (gboolean canceled,
2935                          GError *err,
2936                          GtkWindow *parent_window,
2937                          TnyAccount *account,
2938                          gpointer user_data)
2939 {
2940         CreateFolderConnect *helper = (CreateFolderConnect *) user_data;
2941         ModestMailOperation *mail_op;
2942
2943         if (canceled || err) {
2944                 /* In disk full conditions we could get this error here */
2945                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
2946                                                                 (GtkWidget *) parent_window, err,
2947                                                                 NULL, _("mail_in_ui_folder_create_error_memory"));
2948
2949                 /* This happens if we have selected the outbox folder
2950                    as the parent */
2951                 if (err && err->code == TNY_SERVICE_ERROR_UNKNOWN &&
2952                     TNY_IS_MERGE_FOLDER (helper->parent)) {
2953                         /* Show an error and retry */
2954                         modest_platform_information_banner ((GtkWidget *) parent_window,
2955                                                             NULL,
2956                                                             _("mail_in_ui_folder_create_error"));
2957
2958                         do_create_folder (parent_window, helper->parent, helper->folder_name);
2959                 }
2960
2961                 goto frees;
2962         }
2963
2964         mail_op  = modest_mail_operation_new ((GObject *) parent_window);
2965         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2966                                          mail_op);
2967         modest_mail_operation_create_folder (mail_op,
2968                                              helper->parent,
2969                                              (const gchar *) helper->folder_name,
2970                                              do_create_folder_cb,
2971                                              g_strdup (helper->folder_name));
2972         g_object_unref (mail_op);
2973
2974  frees:
2975         if (helper->parent)
2976                 g_object_unref (helper->parent);
2977         if (helper->folder_name)
2978                 g_free (helper->folder_name);
2979         g_slice_free (CreateFolderConnect, helper);
2980 }
2981
2982
2983 static void
2984 do_create_folder (GtkWindow *parent_window,
2985                   TnyFolderStore *suggested_parent,
2986                   const gchar *suggested_name)
2987 {
2988         gint result;
2989         gchar *folder_name = NULL;
2990         TnyFolderStore *parent_folder = NULL;
2991
2992         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2993                                                         suggested_parent,
2994                                                         (gchar *) suggested_name,
2995                                                         &folder_name,
2996                                                         &parent_folder);
2997
2998         if (result == GTK_RESPONSE_ACCEPT && parent_folder) {
2999                 CreateFolderConnect *helper = (CreateFolderConnect *) g_slice_new0 (CreateFolderConnect);
3000                 helper->folder_name = g_strdup (folder_name);
3001                 helper->parent = g_object_ref (parent_folder);
3002
3003                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window),
3004                                                                TRUE,
3005                                                                parent_folder,
3006                                                                do_create_folder_performer,
3007                                                                helper);
3008         }
3009
3010         if (folder_name)
3011                 g_free (folder_name);
3012         if (parent_folder)
3013                 g_object_unref (parent_folder);
3014 }
3015
3016 static void
3017 modest_ui_actions_create_folder(GtkWidget *parent_window,
3018                                 GtkWidget *folder_view,
3019                                 TnyFolderStore *parent_folder)
3020 {
3021         if (!parent_folder) {
3022                 ModestTnyAccountStore *acc_store;
3023
3024                 acc_store = modest_runtime_get_account_store ();
3025
3026                 parent_folder = (TnyFolderStore *)
3027                         modest_tny_account_store_get_local_folders_account (acc_store);
3028         }
3029
3030         if (parent_folder) {
3031                 do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
3032                 g_object_unref (parent_folder);
3033         }
3034 }
3035
3036 void
3037 modest_ui_actions_on_new_folder (GtkAction *action, ModestWindow *window)
3038 {
3039
3040         g_return_if_fail (MODEST_IS_WINDOW(window));
3041
3042         if (MODEST_IS_FOLDER_WINDOW (window)) {
3043                 GtkWidget *folder_view;
3044
3045                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3046                 modest_ui_actions_create_folder (GTK_WIDGET (window), folder_view, NULL);
3047         } else {
3048                 g_assert_not_reached ();
3049         }
3050 }
3051
3052 static void
3053 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
3054                                                gpointer user_data)
3055 {
3056         const GError *error = NULL;
3057         gchar *message = NULL;
3058         gboolean mem_full;
3059         TnyAccount *account = modest_mail_operation_get_account (mail_op);
3060
3061         /* Get error message */
3062         error = modest_mail_operation_get_error (mail_op);
3063         if (!error)
3064                 g_return_if_reached ();
3065
3066         mem_full = modest_tny_account_store_is_disk_full_error (modest_runtime_get_account_store(),
3067                                                                 (GError *) error, account);
3068         if (mem_full) {
3069                 message = g_strdup_printf (_KR("cerm_device_memory_full"), "");
3070         } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3071                    error->code == MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS) {
3072                 message = _CS("ckdg_ib_folder_already_exists");
3073         } else if (error->domain == TNY_ERROR_DOMAIN &&
3074                    error->code == TNY_SERVICE_ERROR_STATE) {
3075                 /* This means that the folder is already in use (a
3076                    message is opened for example */
3077                 message = _("emev_ni_internal_error");
3078         } else {
3079                 message = _CS("ckdg_ib_unable_to_rename");
3080         }
3081
3082         /* We don't set a parent for the dialog because the dialog
3083            will be destroyed so the banner won't appear */
3084         modest_platform_information_banner (NULL, NULL, message);
3085
3086         if (account)
3087                 g_object_unref (account);
3088         if (mem_full)
3089                 g_free (message);
3090 }
3091
3092 typedef struct {
3093         TnyFolderStore *folder;
3094         gchar *new_name;
3095 } RenameFolderInfo;
3096
3097 static void
3098 on_rename_folder_cb (ModestMailOperation *mail_op,
3099                      TnyFolder *new_folder,
3100                      gpointer user_data)
3101 {
3102         ModestFolderView *folder_view;
3103
3104         /* If the window was closed when renaming a folder, or if
3105          * it's not a main window this will happen */
3106         if (!MODEST_IS_FOLDER_VIEW (user_data))
3107                 return;
3108
3109         folder_view = MODEST_FOLDER_VIEW (user_data);
3110         /* Note that if the rename fails new_folder will be NULL */
3111         if (new_folder) {
3112                 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
3113         }
3114         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
3115 }
3116
3117 static void
3118 on_rename_folder_performer (gboolean canceled,
3119                             GError *err,
3120                             GtkWindow *parent_window,
3121                             TnyAccount *account,
3122                             gpointer user_data)
3123 {
3124         ModestMailOperation *mail_op = NULL;
3125         GtkTreeSelection *sel = NULL;
3126         GtkWidget *folder_view = NULL;
3127         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
3128
3129         if (canceled || err) {
3130                 /* In disk full conditions we could get this error here */
3131                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3132                                                                 (GtkWidget *) parent_window, err,
3133                                                                 account, NULL);
3134         } else {
3135
3136                 mail_op =
3137                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3138                                         modest_ui_actions_rename_folder_error_handler,
3139                                         parent_window, NULL);
3140
3141                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3142                                 mail_op);
3143                 if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3144                         ModestFolderWindow *folder_window = (ModestFolderWindow *) parent_window;
3145                         folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (folder_window));
3146                 }
3147
3148                 /* Clear the folders view */
3149                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3150                 gtk_tree_selection_unselect_all (sel);
3151
3152                 /* Actually rename the folder */
3153                 modest_mail_operation_rename_folder (mail_op,
3154                                                      TNY_FOLDER (data->folder),
3155                                                      (const gchar *) (data->new_name),
3156                                                      on_rename_folder_cb,
3157                                                      folder_view);
3158                 g_object_unref (mail_op);
3159         }
3160
3161         g_object_unref (data->folder);
3162         g_free (data->new_name);
3163         g_free (data);
3164 }
3165
3166 void
3167 modest_ui_actions_on_rename_folder (GtkAction *action,
3168                                      ModestWindow *window)
3169 {
3170         modest_ui_actions_on_edit_mode_rename_folder (window);
3171 }
3172
3173 gboolean
3174 modest_ui_actions_on_edit_mode_rename_folder (ModestWindow *window)
3175 {
3176         TnyFolderStore *folder;
3177         GtkWidget *folder_view;
3178         gboolean do_rename = TRUE;
3179
3180         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3181
3182         if (MODEST_IS_FOLDER_WINDOW (window)) {
3183                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3184         } else {
3185                 return FALSE;
3186         }
3187
3188         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3189
3190         if (!folder)
3191                 return FALSE;
3192
3193         if (TNY_IS_FOLDER (folder)) {
3194                 gchar *folder_name = NULL;
3195                 gint response;
3196                 const gchar *current_name;
3197                 TnyFolderStore *parent;
3198
3199                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
3200                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
3201                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (window),
3202                                                                      parent, current_name,
3203                                                                      &folder_name);
3204                 g_object_unref (parent);
3205
3206                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
3207                         do_rename = FALSE;
3208                 } else {
3209                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
3210                         rename_folder_data->folder = g_object_ref (folder);
3211                         rename_folder_data->new_name = folder_name;
3212                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(window), TRUE,
3213                                         folder, on_rename_folder_performer, rename_folder_data);
3214                 }
3215         }
3216         g_object_unref (folder);
3217         return do_rename;
3218 }
3219
3220 static void
3221 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3222                                                gpointer user_data)
3223 {
3224         GObject *win = modest_mail_operation_get_source (mail_op);
3225
3226         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3227                                                 _("mail_in_ui_folder_delete_error"),
3228                                                 FALSE);
3229         g_object_unref (win);
3230 }
3231
3232 typedef struct {
3233         TnyFolderStore *folder;
3234         gboolean move_to_trash;
3235 } DeleteFolderInfo;
3236
3237 static void
3238 on_delete_folder_cb (gboolean canceled,
3239                   GError *err,
3240                   GtkWindow *parent_window,
3241                   TnyAccount *account,
3242                   gpointer user_data)
3243 {
3244         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3245         GtkWidget *folder_view;
3246         ModestMailOperation *mail_op;
3247         GtkTreeSelection *sel;
3248
3249         if (!MODEST_IS_WINDOW(parent_window) || canceled || (err!=NULL)) {
3250                 /* Note that the connection process can fail due to
3251                    memory low conditions as it can not successfully
3252                    store the summary */
3253                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
3254                                                                      (GtkWidget*) parent_window, err,
3255                                                                      account, NULL))
3256                         g_debug ("Error connecting when trying to delete a folder");
3257                 g_object_unref (G_OBJECT (info->folder));
3258                 g_free (info);
3259                 return;
3260         }
3261
3262         if (MODEST_IS_FOLDER_WINDOW (parent_window)) {
3263                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (parent_window)));
3264         } else {
3265                 g_object_unref (G_OBJECT (info->folder));
3266                 g_free (info);
3267                 return;
3268         }
3269
3270         /* Unselect the folder before deleting it to free the headers */
3271         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3272         gtk_tree_selection_unselect_all (sel);
3273
3274         /* Create the mail operation */
3275         mail_op =
3276                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3277                                 modest_ui_actions_delete_folder_error_handler,
3278                                 NULL, NULL);
3279
3280         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3281                         mail_op);
3282         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3283
3284         g_object_unref (mail_op);
3285         g_object_unref (info->folder);
3286         g_free (info);
3287 }
3288
3289 static gboolean
3290 delete_folder (ModestWindow *window, gboolean move_to_trash)
3291 {
3292         TnyFolderStore *folder;
3293         GtkWidget *folder_view;
3294         gint response;
3295         gchar *message;
3296
3297         g_return_val_if_fail (MODEST_IS_WINDOW(window), FALSE);
3298
3299         if (MODEST_IS_FOLDER_WINDOW (window)) {
3300                 folder_view = GTK_WIDGET (modest_folder_window_get_folder_view (MODEST_FOLDER_WINDOW (window)));
3301         } else {
3302                 return FALSE;
3303         }
3304         if (!folder_view)
3305                 return FALSE;
3306
3307         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3308
3309         if (!folder)
3310                 return FALSE;
3311
3312         /* Show an error if it's an account */
3313         if (!TNY_IS_FOLDER (folder)) {
3314                 modest_platform_run_information_dialog (GTK_WINDOW (window),
3315                                                         _("mail_in_ui_folder_delete_error"),
3316                                                         FALSE);
3317                 g_object_unref (G_OBJECT (folder));
3318                 return FALSE;
3319         }
3320
3321         /* Ask the user */
3322         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"),
3323                                     tny_folder_get_name (TNY_FOLDER (folder)));
3324         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (window),
3325                                                             (const gchar *) message);
3326         g_free (message);
3327
3328         if (response == GTK_RESPONSE_OK) {
3329                 TnyAccount *account = NULL;
3330                 DeleteFolderInfo *info = NULL;
3331                 info = g_new0(DeleteFolderInfo, 1);
3332                 info->folder = g_object_ref (folder);
3333                 info->move_to_trash = move_to_trash;
3334
3335                 account = tny_folder_get_account (TNY_FOLDER (folder));
3336                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (window),
3337                                                                TRUE,
3338                                                                TNY_FOLDER_STORE (account),
3339                                                                on_delete_folder_cb, info);
3340                 g_object_unref (account);
3341                 g_object_unref (folder);
3342                 return TRUE;
3343         } else {
3344                 return FALSE;
3345         }
3346 }
3347
3348 void
3349 modest_ui_actions_on_delete_folder (GtkAction *action,
3350                                     ModestWindow *window)
3351 {
3352         modest_ui_actions_on_edit_mode_delete_folder (window);
3353 }
3354
3355 gboolean
3356 modest_ui_actions_on_edit_mode_delete_folder (ModestWindow *window)
3357 {
3358         g_return_val_if_fail (MODEST_IS_WINDOW(window), TRUE);
3359
3360         return delete_folder (window, FALSE);
3361 }
3362
3363
3364 typedef struct _PasswordDialogFields {
3365         GtkWidget *username;
3366         GtkWidget *password;
3367         GtkWidget *dialog;
3368 } PasswordDialogFields;
3369
3370 static void
3371 password_dialog_check_field (GtkEditable *editable,
3372                              PasswordDialogFields *fields)
3373 {
3374         const gchar *value;
3375         gboolean any_value_empty = FALSE;
3376
3377         value = modest_entry_get_text (fields->username);
3378         if ((value == NULL) || value[0] == '\0') {
3379                 any_value_empty = TRUE;
3380         }
3381         value = modest_entry_get_text (fields->password);
3382         if ((value == NULL) || value[0] == '\0') {
3383                 any_value_empty = TRUE;
3384         }
3385         gtk_dialog_set_response_sensitive (GTK_DIALOG (fields->dialog), GTK_RESPONSE_ACCEPT, !any_value_empty);
3386 }
3387
3388 void
3389 modest_ui_actions_on_password_requested (TnyAccountStore *account_store,
3390                                          const gchar* server_account_name,
3391                                          gchar **username,
3392                                          gchar **password,
3393                                          gboolean *cancel,
3394                                          gboolean *remember,
3395                                          ModestMainWindow *main_window)
3396 {
3397         g_return_if_fail(server_account_name);
3398         gboolean completed = FALSE;
3399         PasswordDialogFields *fields = NULL;
3400
3401         /* Initalize output parameters: */
3402         if (cancel)
3403                 *cancel = FALSE;
3404
3405         if (remember)
3406                 *remember = TRUE;
3407
3408 #ifndef MODEST_TOOLKIT_GTK
3409         /* Maemo uses a different (awkward) button order,
3410          * It should probably just use gtk_alternative_dialog_button_order ().
3411          */
3412 #ifdef MODEST_TOOLKIT_HILDON2
3413         GtkWidget *dialog =
3414                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3415                                              NULL,
3416                                              GTK_DIALOG_MODAL,
3417                                              _HL("wdgt_bd_done"),
3418                                              GTK_RESPONSE_ACCEPT,
3419                                              NULL);
3420         gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox),
3421                                         HILDON_MARGIN_DOUBLE);
3422 #else
3423         GtkWidget *dialog =
3424                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3425                                              NULL,
3426                                              GTK_DIALOG_MODAL,
3427                                              _("mcen_bd_dialog_ok"),
3428                                              GTK_RESPONSE_ACCEPT,
3429                                              _("mcen_bd_dialog_cancel"),
3430                                              GTK_RESPONSE_REJECT,
3431                                              NULL);
3432 #endif /* MODEST_TOOLKIT_HILDON2 */
3433 #else
3434         GtkWidget *dialog =
3435                 gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3436                                              NULL,
3437                                              GTK_DIALOG_MODAL,
3438                                              GTK_STOCK_CANCEL,
3439                                              GTK_RESPONSE_REJECT,
3440                                              GTK_STOCK_OK,
3441                                              GTK_RESPONSE_ACCEPT,
3442                                              NULL);
3443 #endif /* MODEST_TOOLKIT_GTK */
3444
3445         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog), NULL);
3446
3447         gchar *server_name = modest_account_mgr_get_server_account_hostname (
3448                 modest_runtime_get_account_mgr(), server_account_name);
3449         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3450                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3451                 if (cancel)
3452                         *cancel = TRUE;
3453                 gtk_widget_destroy (dialog);
3454                 return;
3455         }
3456
3457         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
3458         GtkWidget *label = gtk_label_new (txt);
3459         gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
3460         g_free (txt);
3461         g_free (server_name);
3462         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), label,
3463                             FALSE, FALSE, 0);
3464         server_name = NULL;
3465
3466         /* username: */
3467         gchar *initial_username = modest_account_mgr_get_server_account_username (
3468                 modest_runtime_get_account_mgr(), server_account_name);
3469
3470         GtkWidget *entry_username = modest_toolkit_factory_create_entry (modest_runtime_get_toolkit_factory ());
3471         if (initial_username)
3472                 modest_entry_set_text (entry_username, initial_username);
3473
3474         /* Dim this if a connection has ever succeeded with this username,
3475          * as per the UI spec: */
3476         /* const gboolean username_known =  */
3477         /*      modest_account_mgr_get_server_account_username_has_succeeded( */
3478         /*              modest_runtime_get_account_mgr(), server_account_name); */
3479         /* gtk_widget_set_sensitive (entry_username, !username_known); */
3480
3481         /* We drop the username sensitive code and disallow changing it here
3482          * as tinymail does not support really changing the username in the callback
3483          */
3484         gtk_widget_set_sensitive (entry_username, FALSE);
3485
3486         /* Auto-capitalization is the default, so let's turn it off: */
3487 #ifdef MAEMO_CHANGES
3488         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
3489 #endif
3490
3491         /* Create a size group to be used by all captions.
3492          * Note that HildonCaption does not create a default size group if we do not specify one.
3493          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
3494         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3495
3496         GtkWidget *caption = modest_toolkit_utils_create_captioned (sizegroup, NULL,
3497                                                                     _("mail_fi_username"), FALSE,
3498                                                                     entry_username);
3499         gtk_widget_show (entry_username);
3500         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
3501                 FALSE, FALSE, MODEST_MARGIN_HALF);
3502         gtk_widget_show (caption);
3503
3504         /* password: */
3505         GtkWidget *entry_password = modest_toolkit_factory_create_entry (modest_runtime_get_toolkit_factory ());
3506         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
3507         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
3508
3509         /* Auto-capitalization is the default, so let's turn it off: */
3510 #ifdef MAEMO_CHANGES
3511         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password),
3512                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
3513 #endif
3514
3515         caption = modest_toolkit_utils_create_captioned (sizegroup, NULL,
3516                                                          _("mail_fi_password"), FALSE,
3517                                                          entry_password);
3518         gtk_widget_show (entry_password);
3519         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption,
3520                 FALSE, FALSE, MODEST_MARGIN_HALF);
3521         gtk_widget_show (caption);
3522         g_object_unref (sizegroup);
3523
3524         if (initial_username != NULL)
3525                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
3526
3527 /* This is not in the Maemo UI spec:
3528         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
3529         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
3530                             TRUE, FALSE, 0);
3531 */
3532
3533         fields = g_slice_new0 (PasswordDialogFields);
3534         fields->username = entry_username;
3535         fields->password = entry_password;
3536         fields->dialog = dialog;
3537
3538         g_signal_connect (entry_username, "changed", G_CALLBACK (password_dialog_check_field), fields);
3539         g_signal_connect (entry_password, "changed", G_CALLBACK (password_dialog_check_field), fields);
3540         password_dialog_check_field (NULL, fields);
3541
3542         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3543
3544         while (!completed) {
3545
3546                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
3547                         if (username) {
3548                                 *username = g_strdup (modest_entry_get_text (entry_username));
3549
3550                                 /* Note that an empty field becomes the "" string */
3551                                 if (*username && strlen (*username) > 0) {
3552                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(),
3553                                                                                         server_account_name,
3554                                                                                         *username);
3555                                         completed = TRUE;
3556
3557                                         const gboolean username_was_changed =
3558                                                 (strcmp (*username, initial_username) != 0);
3559                                         if (username_was_changed) {
3560                                                 g_warning ("%s: tinymail does not yet support changing the "
3561                                                            "username in the get_password() callback.\n", __FUNCTION__);
3562                                         }
3563                                 } else {
3564                                         g_free (*username);
3565                                         *username = NULL;
3566                                         /* Show error */
3567                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL,
3568                                                                             _("mcen_ib_username_pw_incorrect"));
3569                                         completed = FALSE;
3570                                 }
3571                         }
3572
3573                         if (password) {
3574                                 *password = g_strdup (modest_entry_get_text (entry_password));
3575
3576                                 /* We do not save the password in the configuration,
3577                                  * because this function is only called for passwords that should
3578                                  * not be remembered:
3579                                  modest_server_account_set_password (
3580                                  modest_runtime_get_account_mgr(), server_account_name,
3581                                  *password);
3582                                  */
3583                         }
3584                         if (cancel)
3585                                 *cancel   = FALSE;
3586                 } else {
3587                         completed = TRUE;
3588                         if (username)
3589                                 *username = NULL;
3590                         if (password)
3591                                 *password = NULL;
3592                         if (cancel)
3593                                 *cancel   = TRUE;
3594                 }
3595         }
3596
3597 /* This is not in the Maemo UI spec:
3598         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
3599                 *remember = TRUE;
3600         else
3601                 *remember = FALSE;
3602 */
3603
3604         g_free (initial_username);
3605         gtk_widget_destroy (dialog);
3606         g_slice_free (PasswordDialogFields, fields);
3607
3608         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
3609 }
3610
3611 void
3612 modest_ui_actions_on_cut (GtkAction *action,
3613                           ModestWindow *window)
3614 {
3615         GtkWidget *focused_widget;
3616         GtkClipboard *clipboard;
3617
3618         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3619         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3620         if (GTK_IS_EDITABLE (focused_widget)) {
3621                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3622                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3623                 gtk_clipboard_store (clipboard);
3624         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3625                 GtkTextBuffer *buffer;
3626
3627                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3628                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3629                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3630                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3631                         gtk_clipboard_store (clipboard);
3632                 }
3633         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3634                 TnyList *header_list = modest_header_view_get_selected_headers (
3635                                 MODEST_HEADER_VIEW (focused_widget));
3636                 gboolean continue_download = FALSE;
3637                 gint num_of_unc_msgs;
3638
3639                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3640
3641                 if (num_of_unc_msgs) {
3642                         TnyAccount *account = get_account_from_header_list (header_list);
3643                         if (account) {
3644                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3645                                 g_object_unref (account);
3646                         }
3647                 }
3648
3649                 if (num_of_unc_msgs == 0 || continue_download) {
3650 /*                      modest_platform_information_banner (
3651                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
3652                         modest_header_view_cut_selection (
3653                                         MODEST_HEADER_VIEW (focused_widget));
3654                 }
3655
3656                 g_object_unref (header_list);
3657         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3658                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3659         }
3660 }
3661
3662 void
3663 modest_ui_actions_on_copy (GtkAction *action,
3664                            ModestWindow *window)
3665 {
3666         GtkClipboard *clipboard;
3667         GtkWidget *focused_widget;
3668         gboolean copied = TRUE;
3669
3670         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3671         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3672
3673         if (GTK_IS_LABEL (focused_widget)) {
3674                 gchar *selection;
3675                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
3676                 gtk_clipboard_set_text (clipboard, selection, -1);
3677                 g_free (selection);
3678                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3679                 gtk_clipboard_store (clipboard);
3680         } else if (GTK_IS_EDITABLE (focused_widget)) {
3681                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3682                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3683                 gtk_clipboard_store (clipboard);
3684         } else if (GTK_IS_HTML (focused_widget)) {
3685                 const gchar *sel;
3686                 int len = -1;
3687                 sel = gtk_html_get_selection_html (GTK_HTML (focused_widget), &len);
3688                 if ((sel == NULL) || (sel[0] == '\0')) {
3689                         copied = FALSE;
3690                 } else {
3691                         gtk_html_copy (GTK_HTML (focused_widget));
3692                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3693                         gtk_clipboard_store (clipboard);
3694                 }
3695         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3696                 GtkTextBuffer *buffer;
3697                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3698                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3699                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
3700                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3701                         gtk_clipboard_store (clipboard);
3702                 }
3703         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3704                 TnyList *header_list = modest_header_view_get_selected_headers (
3705                                 MODEST_HEADER_VIEW (focused_widget));
3706                 gboolean continue_download = FALSE;
3707                 gint num_of_unc_msgs;
3708
3709                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3710
3711                 if (num_of_unc_msgs) {
3712                         TnyAccount *account = get_account_from_header_list (header_list);
3713                         if (account) {
3714                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3715                                 g_object_unref (account);
3716                         }
3717                 }
3718
3719                 if (num_of_unc_msgs == 0 || continue_download) {
3720                         modest_platform_information_banner (
3721                                         NULL, NULL, _CS("mcen_ib_getting_items"));
3722                         modest_header_view_copy_selection (
3723                                         MODEST_HEADER_VIEW (focused_widget));
3724                 } else
3725                         copied = FALSE;
3726
3727                 g_object_unref (header_list);
3728
3729         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3730                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3731         }
3732
3733         /* Show information banner if there was a copy to clipboard */
3734         if(copied)
3735                 modest_platform_information_banner (
3736                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3737 }
3738
3739 void
3740 modest_ui_actions_on_undo (GtkAction *action,
3741                            ModestWindow *window)
3742 {
3743         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3744                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3745         } else {
3746                 g_return_if_reached ();
3747         }
3748 }
3749
3750 void
3751 modest_ui_actions_on_redo (GtkAction *action,
3752                            ModestWindow *window)
3753 {
3754         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3755                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3756         }
3757         else {
3758                 g_return_if_reached ();
3759         }
3760 }
3761
3762
3763 static void
3764 destroy_information_note (ModestMailOperation *mail_op,
3765                           gpointer user_data)
3766 {
3767         /* destroy information note */
3768         gtk_widget_destroy (GTK_WIDGET(user_data));
3769 }
3770
3771 static void
3772 destroy_folder_information_note (ModestMailOperation *mail_op,
3773                                  TnyFolder *new_folder,
3774                                  gpointer user_data)
3775 {
3776         /* destroy information note */
3777         gtk_widget_destroy (GTK_WIDGET(user_data));
3778 }
3779
3780
3781 static void
3782 paste_as_attachment_free (gpointer data)
3783 {
3784         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3785
3786         if (helper->banner) {
3787                 gtk_widget_destroy (helper->banner);
3788                 g_object_unref (helper->banner);
3789         }
3790         g_free (helper);
3791 }
3792
3793 static void
3794 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3795                             TnyHeader *header,
3796                             TnyMsg *msg,
3797                             gpointer userdata)
3798 {
3799         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3800         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3801
3802         if (msg == NULL)
3803                 return;
3804
3805         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3806
3807 }
3808
3809 void
3810 modest_ui_actions_on_paste (GtkAction *action,
3811                             ModestWindow *window)
3812 {
3813         GtkWidget *focused_widget = NULL;
3814         GtkWidget *inf_note = NULL;
3815         ModestMailOperation *mail_op = NULL;
3816
3817         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3818         if (GTK_IS_EDITABLE (focused_widget)) {
3819                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3820         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3821                 ModestEmailClipboard *e_clipboard = NULL;
3822                 e_clipboard = modest_runtime_get_email_clipboard ();
3823                 if (modest_email_clipboard_cleared (e_clipboard)) {
3824                         GtkTextBuffer *buffer;
3825                         GtkClipboard *clipboard;
3826
3827                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3828                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3829                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3830                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3831                         ModestMailOperation *mail_op;
3832                         TnyFolder *src_folder = NULL;
3833                         TnyList *data = NULL;
3834                         gboolean delete;
3835                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3836                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3837                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3838                                                                            _CS("ckct_nw_pasting"));
3839                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3840                         mail_op = modest_mail_operation_new (G_OBJECT (window));
3841                         if (helper->banner != NULL) {
3842                                 g_object_ref (G_OBJECT (helper->banner));
3843                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3844                         }
3845
3846                         if (data != NULL) {
3847                                 modest_mail_operation_get_msgs_full (mail_op,
3848                                                                      data,
3849                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3850                                                                      helper,
3851                                                                      paste_as_attachment_free);
3852                         }
3853                         /* Free */
3854                         if (data)
3855                                 g_object_unref (data);
3856                         if (src_folder)
3857                                 g_object_unref (src_folder);
3858
3859                 }
3860         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3861                 ModestEmailClipboard *clipboard = NULL;
3862                 TnyFolder *src_folder = NULL;
3863                 TnyFolderStore *folder_store = NULL;
3864                 TnyList *data = NULL;
3865                 gboolean delete = FALSE;
3866
3867                 /* Check clipboard source */
3868                 clipboard = modest_runtime_get_email_clipboard ();
3869                 if (modest_email_clipboard_cleared (clipboard))
3870                         return;
3871
3872                 /* Get elements to paste */
3873                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3874
3875                 /* Create a new mail operation */
3876                 mail_op = modest_mail_operation_new (G_OBJECT(window));
3877
3878                 /* Get destination folder */
3879                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3880
3881                 /* transfer messages  */
3882                 if (data != NULL) {
3883                         gint response = 0;
3884
3885                         /* Ask for user confirmation */
3886                         response =
3887                                 modest_ui_actions_msgs_move_to_confirmation (window,
3888                                                                              TNY_FOLDER (folder_store),
3889                                                                              delete,
3890                                                                              data);
3891
3892                         if (response == GTK_RESPONSE_OK) {
3893                                 /* Launch notification */
3894                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3895                                                                              _CS("ckct_nw_pasting"));
3896                                 if (inf_note != NULL)  {
3897                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3898                                         gtk_widget_show (GTK_WIDGET(inf_note));
3899                                 }
3900
3901                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3902                                 modest_mail_operation_xfer_msgs (mail_op,
3903                                                                  data,
3904                                                                  TNY_FOLDER (folder_store),
3905                                                                  delete,
3906                                                                  destroy_information_note,
3907                                                                  inf_note);
3908                         } else {
3909                                 g_object_unref (mail_op);
3910                         }
3911
3912                 } else if (src_folder != NULL) {
3913                         /* Launch notification */
3914                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3915                                                                      _CS("ckct_nw_pasting"));
3916                         if (inf_note != NULL)  {
3917                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3918                                 gtk_widget_show (GTK_WIDGET(inf_note));
3919                         }
3920
3921                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3922                         modest_mail_operation_xfer_folder (mail_op,
3923                                                            src_folder,
3924                                                            folder_store,
3925                                                            delete,
3926                                                            destroy_folder_information_note,
3927                                                            inf_note);
3928                 }
3929
3930                 /* Free */
3931                 if (data != NULL)
3932                         g_object_unref (data);
3933                 if (src_folder != NULL)
3934                         g_object_unref (src_folder);
3935                 if (folder_store != NULL)
3936                         g_object_unref (folder_store);
3937         }
3938 }
3939
3940
3941 void
3942 modest_ui_actions_on_select_all (GtkAction *action,
3943                                  ModestWindow *window)
3944 {
3945         GtkWidget *focused_widget;
3946
3947         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3948         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3949                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3950         } else if (GTK_IS_LABEL (focused_widget)) {
3951                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3952         } else if (GTK_IS_EDITABLE (focused_widget)) {
3953                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3954         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3955                 GtkTextBuffer *buffer;
3956                 GtkTextIter start, end;
3957
3958                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3959                 gtk_text_buffer_get_start_iter (buffer, &start);
3960                 gtk_text_buffer_get_end_iter (buffer, &end);
3961                 gtk_text_buffer_select_range (buffer, &start, &end);
3962         } else if (GTK_IS_HTML (focused_widget)) {
3963                 gtk_html_select_all (GTK_HTML (focused_widget));
3964         }
3965
3966 }
3967
3968 void
3969 modest_ui_actions_on_mark_as_read (GtkAction *action,
3970                                    ModestWindow *window)
3971 {
3972         g_return_if_fail (MODEST_IS_WINDOW(window));
3973
3974         /* Mark each header as read */
3975         do_headers_action (window, headers_action_mark_as_read, NULL);
3976 }
3977
3978 void
3979 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3980                                      ModestWindow *window)
3981 {
3982         g_return_if_fail (MODEST_IS_WINDOW(window));
3983
3984         /* Mark each header as read */
3985         do_headers_action (window, headers_action_mark_as_unread, NULL);
3986 }
3987
3988 void
3989 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3990                                   GtkRadioAction *selected,
3991                                   ModestWindow *window)
3992 {
3993         gint value;
3994
3995         value = gtk_radio_action_get_current_value (selected);
3996         if (MODEST_IS_WINDOW (window)) {
3997                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3998         }
3999 }
4000
4001 void
4002 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
4003                                                GtkRadioAction *selected,
4004                                                ModestWindow *window)
4005 {
4006         TnyHeaderFlags flags;
4007         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4008
4009         flags = gtk_radio_action_get_current_value (selected);
4010         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
4011 }
4012
4013 void
4014 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
4015                                                   GtkRadioAction *selected,
4016                                                   ModestWindow *window)
4017 {
4018         gint file_format;
4019
4020         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4021
4022         file_format = gtk_radio_action_get_current_value (selected);
4023         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
4024 }
4025
4026
4027 void
4028 modest_ui_actions_on_zoom_plus (GtkAction *action,
4029                                 ModestWindow *window)
4030 {
4031         g_return_if_fail (MODEST_IS_WINDOW (window));
4032
4033         modest_window_zoom_plus (MODEST_WINDOW (window));
4034 }
4035
4036 void
4037 modest_ui_actions_on_zoom_minus (GtkAction *action,
4038                                  ModestWindow *window)
4039 {
4040         g_return_if_fail (MODEST_IS_WINDOW (window));
4041
4042         modest_window_zoom_minus (MODEST_WINDOW (window));
4043 }
4044
4045 void
4046 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
4047                                            ModestWindow *window)
4048 {
4049         ModestWindowMgr *mgr;
4050         gboolean fullscreen, active;
4051         g_return_if_fail (MODEST_IS_WINDOW (window));
4052
4053         mgr = modest_runtime_get_window_mgr ();
4054
4055         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4056         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4057
4058         if (active != fullscreen) {
4059                 modest_window_mgr_set_fullscreen_mode (mgr, active);
4060 #ifndef MODEST_TOOLKIT_HILDON2
4061                 gtk_window_present (GTK_WINDOW (window));
4062 #endif
4063         }
4064 }
4065
4066 void
4067 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4068                                         ModestWindow *window)
4069 {
4070         ModestWindowMgr *mgr;
4071         gboolean fullscreen;
4072
4073         g_return_if_fail (MODEST_IS_WINDOW (window));
4074
4075         mgr = modest_runtime_get_window_mgr ();
4076         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4077         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4078
4079 #ifndef MODEST_TOOLKIT_HILDON2
4080         gtk_window_present (GTK_WINDOW (window));
4081 #endif
4082 }
4083
4084 /*
4085  * Used by modest_ui_actions_on_details to call do_headers_action
4086  */
4087 static void
4088 headers_action_show_details (TnyHeader *header,
4089                              ModestWindow *window,
4090                              gpointer user_data)
4091
4092 {
4093         gboolean async_retrieval;
4094         TnyMsg *msg = NULL;
4095
4096         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
4097                 async_retrieval = TRUE;
4098                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (window));
4099         } else {
4100                 async_retrieval = FALSE;
4101         }
4102         modest_platform_run_header_details_dialog (GTK_WINDOW (window), header, async_retrieval, msg);
4103         if (msg)
4104                 g_object_unref (msg);
4105 }
4106
4107 /*
4108  * Show the header details in a ModestDetailsDialog widget
4109  */
4110 void
4111 modest_ui_actions_on_details (GtkAction *action,
4112                               ModestWindow *win)
4113 {
4114         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4115                 TnyMsg *msg;
4116                 TnyHeader *header;
4117
4118                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4119                 if (!msg)
4120                         return;
4121
4122                 header = tny_msg_get_header (msg);
4123                 if (header) {
4124                         headers_action_show_details (header, win, NULL);
4125                         g_object_unref (header);
4126                 }
4127                 g_object_unref (msg);
4128         } else if (MODEST_IS_HEADER_WINDOW (win)) {
4129                 TnyFolder *folder;
4130                 GtkWidget *header_view;
4131
4132                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
4133                 folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
4134                 if (folder) {
4135                         modest_platform_run_folder_details_dialog (GTK_WINDOW (win),
4136                                                                    folder);
4137                         g_object_unref (folder);
4138                 }
4139         }
4140 }
4141
4142 void
4143 modest_ui_actions_on_limit_error (GtkAction *action,
4144                                   ModestWindow *win)
4145 {
4146         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (win));
4147
4148         modest_platform_information_banner ((GtkWidget *) win, NULL, _CS("ckdg_ib_maximum_characters_reached"));
4149
4150 }
4151
4152 void
4153 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4154                                      ModestMsgEditWindow *window)
4155 {
4156         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4157
4158         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4159 }
4160
4161 void
4162 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4163                                       ModestMsgEditWindow *window)
4164 {
4165         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4166
4167         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4168 }
4169
4170
4171 void
4172 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle,
4173                                      ModestWindow *window)
4174 {
4175         gboolean active, fullscreen = FALSE;
4176         ModestWindowMgr *mgr;
4177
4178         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4179
4180         /* Check if we want to toggle the toolbar view in fullscreen
4181            or normal mode */
4182         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)),
4183                      "ViewShowToolbarFullScreen")) {
4184                 fullscreen = TRUE;
4185         }
4186
4187         /* Toggle toolbar */
4188         mgr = modest_runtime_get_window_mgr ();
4189         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4190 }
4191
4192 void
4193 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4194                                            ModestMsgEditWindow *window)
4195 {
4196         modest_msg_edit_window_select_font (window);
4197 }
4198
4199
4200 void
4201 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4202                                                   const gchar *display_name,
4203                                                   GtkWindow *window)
4204 {
4205         /* don't update the display name if it was already set;
4206          * updating the display name apparently is expensive */
4207         const gchar* old_name = gtk_window_get_title (window);
4208
4209         if (display_name == NULL)
4210                 display_name = " ";
4211
4212         if (old_name && display_name && strcmp (old_name, display_name) == 0)
4213                 return; /* don't do anything */
4214
4215         /* This is usually used to change the title of the main window, which
4216          * is the one that holds the folder view. Note that this change can
4217          * happen even when the widget doesn't have the focus. */
4218         gtk_window_set_title (window, display_name);
4219
4220 }
4221
4222 void
4223 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4224 {
4225         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4226         modest_msg_edit_window_select_contacts (window);
4227 }
4228
4229 void
4230 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4231 {
4232         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4233         modest_msg_edit_window_check_names (window, FALSE);
4234 }
4235
4236
4237 static void
4238 on_move_to_dialog_response (GtkDialog *dialog,
4239                             gint       response,
4240                             gpointer   user_data)
4241 {
4242         GtkWidget *parent_win;
4243         MoveToInfo *helper = NULL;
4244         ModestFolderView *folder_view;
4245         gboolean unset_edit_mode = FALSE;
4246
4247         helper = (MoveToInfo *) user_data;
4248
4249         parent_win = (GtkWidget *) helper->win;
4250         folder_view = MODEST_FOLDER_VIEW (g_object_get_data (G_OBJECT (dialog),
4251                                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4252         switch (response) {
4253                 TnyFolderStore *dst_folder;
4254                 TnyFolderStore *selected;
4255
4256         case MODEST_GTK_RESPONSE_NEW_FOLDER:
4257                 selected = modest_folder_view_get_selected (folder_view);
4258                 modest_ui_actions_create_folder (GTK_WIDGET (dialog), GTK_WIDGET (folder_view), selected);
4259                 g_object_unref (selected);
4260                 return;
4261         case GTK_RESPONSE_NONE:
4262         case GTK_RESPONSE_CANCEL:
4263         case GTK_RESPONSE_DELETE_EVENT:
4264                 break;
4265         case GTK_RESPONSE_OK:
4266                 dst_folder = modest_folder_view_get_selected (folder_view);
4267
4268                 if (MODEST_IS_FOLDER_WINDOW (parent_win)) {
4269                         /* Clean list to move used for filtering */
4270                         modest_folder_view_set_list_to_move (folder_view, NULL);
4271
4272                         modest_ui_actions_on_folder_window_move_to (GTK_WIDGET (folder_view),
4273                                                                     dst_folder,
4274                                                                     helper->list,
4275                                                                     GTK_WINDOW (parent_win));
4276                 } else {
4277                         /* if the user selected a root folder
4278                            (account) then do not perform any action */
4279                         if (TNY_IS_ACCOUNT (dst_folder)) {
4280                                 g_signal_stop_emission_by_name (dialog, "response");
4281                                 return;
4282                         }
4283
4284                         /* Clean list to move used for filtering */
4285                         modest_folder_view_set_list_to_move (folder_view, NULL);
4286
4287                         /* Moving from headers window in edit mode */
4288                         modest_ui_actions_on_window_move_to (NULL, helper->list,
4289                                                              dst_folder,
4290                                                              MODEST_WINDOW (parent_win));
4291                 }
4292
4293                 if (dst_folder)
4294                         g_object_unref (dst_folder);
4295
4296                 unset_edit_mode = TRUE;
4297                 break;
4298         default:
4299                 g_warning ("%s unexpected response id %d", __FUNCTION__, response);
4300         }
4301
4302         /* Free the helper and exit */
4303         if (helper->list)
4304                 g_object_unref (helper->list);
4305         if (unset_edit_mode) {
4306 #ifdef MODEST_TOOLKIT_HILDON2
4307                 modest_hildon2_window_unset_edit_mode (MODEST_HILDON2_WINDOW (helper->win));
4308 #endif
4309         }
4310         g_slice_free (MoveToInfo, helper);
4311         gtk_widget_destroy (GTK_WIDGET (dialog));
4312 }
4313
4314 static GtkWidget*
4315 create_move_to_dialog (GtkWindow *win,
4316                        GtkWidget *folder_view,
4317                        TnyList *list_to_move)
4318 {
4319         GtkWidget *dialog, *tree_view = NULL;
4320
4321         dialog = modest_platform_create_move_to_dialog (win, &tree_view);
4322
4323
4324         /* It could happen that we're trying to move a message from a
4325            window (msg window for example) after the main window was
4326            closed, so we can not just get the model of the folder
4327            view */
4328         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
4329                 const gchar *visible_id = NULL;
4330
4331                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
4332                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4333                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view),
4334                                                MODEST_FOLDER_VIEW(tree_view));
4335
4336                 visible_id =
4337                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
4338
4339                 /* Show the same account than the one that is shown in the main window */
4340                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(tree_view),
4341                                                                              visible_id);
4342         } else {
4343                 const gchar *active_account_name = NULL;
4344                 ModestAccountMgr *mgr = NULL;
4345                 ModestAccountSettings *settings = NULL;
4346                 ModestServerAccountSettings *store_settings = NULL;
4347
4348                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (tree_view),
4349                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4350                 /* modest_folder_view_update_model (MODEST_FOLDER_VIEW (tree_view), */
4351                 /*                               TNY_ACCOUNT_STORE (modest_runtime_get_account_store ())); */
4352
4353                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
4354                 mgr = modest_runtime_get_account_mgr ();
4355                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
4356
4357                 if (settings) {
4358                         const gchar *store_account_name;
4359                         store_settings = modest_account_settings_get_store_settings (settings);
4360                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
4361
4362                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (tree_view),
4363                                                                                      store_account_name);
4364                         g_object_unref (store_settings);
4365                         g_object_unref (settings);
4366                 }
4367         }
4368
4369         /* we keep a pointer to the embedded folder view, so we can
4370          *   retrieve it with get_folder_view_from_move_to_dialog (see
4371          *   above) later (needed for focus handling)
4372          */
4373         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, tree_view);
4374
4375         /* Hide special folders */
4376         if (list_to_move)
4377                 modest_folder_view_set_list_to_move (MODEST_FOLDER_VIEW (tree_view), list_to_move);
4378
4379         gtk_widget_show (GTK_WIDGET (tree_view));
4380
4381         return dialog;
4382 }
4383
4384 /*
4385  * Shows a confirmation dialog to the user when we're moving messages
4386  * from a remote server to the local storage. Returns the dialog
4387  * response. If it's other kind of movement then it always returns
4388  * GTK_RESPONSE_OK
4389  *
4390  * This one is used by the next functions:
4391  *      modest_ui_actions_on_paste                      - commented out
4392  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4393  */
4394 gint
4395 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4396                                              TnyFolder *dest_folder,
4397                                              gboolean delete,
4398                                              TnyList *headers)
4399 {
4400         gint response = GTK_RESPONSE_OK;
4401         TnyAccount *account = NULL;
4402         TnyFolder *src_folder = NULL;
4403         TnyIterator *iter = NULL;
4404         TnyHeader *header = NULL;
4405
4406         /* return with OK if the destination is a remote folder */
4407         if (modest_tny_folder_is_remote_folder (dest_folder))
4408                 return GTK_RESPONSE_OK;
4409
4410         /* Get source folder */
4411         iter = tny_list_create_iterator (headers);
4412         header = TNY_HEADER (tny_iterator_get_current (iter));
4413         if (header) {
4414                 src_folder = tny_header_get_folder (header);
4415                 g_object_unref (header);
4416         }
4417         g_object_unref (iter);
4418
4419         /* if no src_folder, message may be an attahcment */
4420         if (src_folder == NULL)
4421                 return GTK_RESPONSE_CANCEL;
4422
4423         /* If the source is a local or MMC folder */
4424         if (!modest_tny_folder_is_remote_folder (src_folder)) {
4425                 g_object_unref (src_folder);
4426                 return GTK_RESPONSE_OK;
4427         }
4428
4429         /* Get the account */
4430         account = tny_folder_get_account (src_folder);
4431
4432         /* now if offline we ask the user */
4433         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4434                 response = GTK_RESPONSE_OK;
4435         else
4436                 response = GTK_RESPONSE_CANCEL;
4437
4438         /* Frees */
4439         g_object_unref (src_folder);
4440         g_object_unref (account);
4441
4442         return response;
4443 }
4444
4445 static void
4446 move_to_helper_destroyer (gpointer user_data)
4447 {
4448         MoveToHelper *helper = (MoveToHelper *) user_data;
4449
4450         /* Close the "Pasting" information banner */
4451         if (helper->banner) {
4452                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
4453                 g_object_unref (helper->banner);
4454         }
4455         if (gtk_tree_row_reference_valid (helper->reference)) {
4456                 gtk_tree_row_reference_free (helper->reference);
4457                 helper->reference = NULL;
4458         }
4459         g_free (helper);
4460 }
4461
4462 static void
4463 move_to_cb (ModestMailOperation *mail_op,
4464             gpointer user_data)
4465 {
4466         MoveToHelper *helper = (MoveToHelper *) user_data;
4467         GObject *object = modest_mail_operation_get_source (mail_op);
4468
4469         /* Note that the operation could have failed, in that case do
4470            nothing */
4471         if (modest_mail_operation_get_status (mail_op) !=
4472             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
4473                 goto frees;
4474
4475         if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4476                 ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4477
4478                 if (!modest_msg_view_window_select_next_message (self) &&
4479                     !modest_msg_view_window_select_previous_message (self)) {
4480                         /* No more messages to view, so close this window */
4481                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4482                 }
4483         }
4484         g_object_unref (object);
4485
4486  frees:
4487         /* Destroy the helper */
4488         move_to_helper_destroyer (helper);
4489 }
4490
4491 static void
4492 folder_move_to_cb (ModestMailOperation *mail_op,
4493                    TnyFolder *new_folder,
4494                    gpointer user_data)
4495 {
4496         GObject *object;
4497
4498         object = modest_mail_operation_get_source (mail_op);
4499         {
4500                 move_to_cb (mail_op, user_data);
4501         }
4502 }
4503
4504 static void
4505 msgs_move_to_cb (ModestMailOperation *mail_op,
4506                  gpointer user_data)
4507 {
4508         move_to_cb (mail_op, user_data);
4509 }
4510
4511 void
4512 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op,
4513                                              gpointer user_data)
4514 {
4515         GObject *win = NULL;
4516         const GError *error;
4517         TnyAccount *account = NULL;
4518
4519         win = modest_mail_operation_get_source (mail_op);
4520         error = modest_mail_operation_get_error (mail_op);
4521
4522         if (TNY_IS_FOLDER (user_data))
4523                 account = modest_tny_folder_get_account (TNY_FOLDER (user_data));
4524         else if (TNY_IS_ACCOUNT (user_data))
4525                 account = g_object_ref (user_data);
4526
4527         /* If it's not a disk full error then show a generic error */
4528         if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
4529                                                              (GtkWidget *) win, (GError *) error,
4530                                                              account, NULL))
4531                 modest_platform_run_information_dialog ((GtkWindow *) win,
4532                                                         _("mail_in_ui_folder_move_target_error"),
4533                                                         FALSE);
4534         if (account)
4535                 g_object_unref (account);
4536         if (win)
4537                 g_object_unref (win);
4538 }
4539
4540
4541 /*
4542  * Checks if we need a connection to do the transfer and if the user
4543  * wants to connect to complete it
4544  */
4545 static void
4546 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
4547                                        TnyFolderStore *src_folder,
4548                                        TnyList *headers,
4549                                        TnyFolder *dst_folder,
4550                                        gboolean delete_originals,
4551                                        gboolean *need_connection,
4552                                        gboolean *do_xfer)
4553 {
4554         TnyAccount *src_account;
4555         gint uncached_msgs = 0;
4556
4557         /* We don't need any further check if
4558          *
4559          * 1- the source folder is local OR
4560          * 2- the device is already online
4561          */
4562         if (!modest_tny_folder_store_is_remote (src_folder) ||
4563             tny_device_is_online (modest_runtime_get_device())) {
4564                 *need_connection = FALSE;
4565                 *do_xfer = TRUE;
4566                 return;
4567         }
4568
4569         /* We must ask for a connection when
4570          *
4571          *   - the message(s) is not already cached   OR
4572          *   - the message(s) is cached but the leave_on_server setting
4573          * is FALSE (because we need to sync the source folder to
4574          * delete the message from the server (for IMAP we could do it
4575          * offline, it'll take place the next time we get a
4576          * connection)
4577          */
4578         uncached_msgs = header_list_count_uncached_msgs (headers);
4579         src_account = get_account_from_folder_store (src_folder);
4580         if (uncached_msgs > 0) {
4581                 guint num_headers;
4582                 const gchar *msg;
4583
4584                 *need_connection = TRUE;
4585                 num_headers = tny_list_get_length (headers);
4586                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
4587
4588                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
4589                     GTK_RESPONSE_CANCEL) {
4590                         *do_xfer = FALSE;
4591                 } else {
4592                         *do_xfer = TRUE;
4593                 }
4594         } else {
4595                 /* The transfer is possible and the user wants to */
4596                 *do_xfer = TRUE;
4597
4598                 if (remote_folder_has_leave_on_server (src_folder) && delete_originals) {
4599                         const gchar *account_name;
4600                         gboolean leave_on_server;
4601
4602                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
4603                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
4604                                                                                   account_name);
4605
4606                         if (leave_on_server == TRUE) {
4607                                 *need_connection = FALSE;
4608                         } else {
4609                                 *need_connection = TRUE;
4610                         }
4611                 } else {
4612                         *need_connection = FALSE;
4613                 }
4614         }
4615
4616         /* Frees */
4617         g_object_unref (src_account);
4618 }
4619
4620 static void
4621 xfer_messages_error_handler (ModestMailOperation *mail_op,
4622                              gpointer user_data)
4623 {
4624         GObject *win;
4625         const GError *error;
4626         TnyAccount *account;
4627
4628         win = modest_mail_operation_get_source (mail_op);
4629         error = modest_mail_operation_get_error (mail_op);
4630
4631         /* We cannot get the account from the mail op as that is the
4632            source account and for checking memory full conditions we
4633            need the destination one */
4634         account = TNY_ACCOUNT (user_data);
4635
4636         if (error &&
4637             !modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
4638                                                              (GtkWidget *) win, (GError*) error,
4639                                                              account, _KR("cerm_memory_card_full"))) {
4640                 modest_platform_run_information_dialog ((GtkWindow *) win,
4641                                                         _("mail_in_ui_folder_move_target_error"),
4642                                                         FALSE);
4643         }
4644         if (win)
4645                 g_object_unref (win);
4646 }
4647
4648 typedef struct {
4649         TnyFolderStore *dst_folder;
4650         TnyList *headers;
4651 } XferMsgsHelper;
4652
4653 /**
4654  * Utility function that transfer messages from both the main window
4655  * and the msg view window when using the "Move to" dialog
4656  */
4657 static void
4658 xfer_messages_performer  (gboolean canceled,
4659                           GError *err,
4660                           GtkWindow *parent_window,
4661                           TnyAccount *account,
4662                           gpointer user_data)
4663 {
4664         ModestWindow *win = MODEST_WINDOW (parent_window);
4665         TnyAccount *dst_account = NULL;
4666         gboolean dst_forbids_message_add = FALSE;
4667         XferMsgsHelper *helper;
4668         MoveToHelper *movehelper;
4669         ModestMailOperation *mail_op;
4670
4671         helper = (XferMsgsHelper *) user_data;
4672
4673         if (canceled || err) {
4674                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
4675                                                                      (GtkWidget *) parent_window, err,
4676                                                                      account, NULL)) {
4677                         /* Show the proper error message */
4678                         modest_ui_actions_on_account_connection_error (parent_window, account);
4679                 }
4680                 goto end;
4681         }
4682
4683         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
4684
4685         /* tinymail will return NULL for local folders it seems */
4686         dst_forbids_message_add = modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
4687                                                                                   modest_tny_account_get_protocol_type (dst_account),
4688                                                                                   MODEST_PROTOCOL_REGISTRY_STORE_FORBID_INCOMING_XFERS);
4689
4690         if (dst_forbids_message_add) {
4691                 modest_platform_information_banner (GTK_WIDGET (win),
4692                                                     NULL,
4693                                                     ngettext("mail_in_ui_folder_move_target_error",
4694                                                              "mail_in_ui_folder_move_targets_error",
4695                                                              tny_list_get_length (helper->headers)));
4696                 goto end;
4697         }
4698
4699         movehelper = g_new0 (MoveToHelper, 1);
4700
4701
4702         /* Perform the mail operation */
4703         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
4704                                                                  xfer_messages_error_handler,
4705                                                                  g_object_ref (dst_account),
4706                                                                  g_object_unref);
4707         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4708                                          mail_op);
4709
4710         modest_mail_operation_xfer_msgs (mail_op,
4711                                          helper->headers,
4712                                          TNY_FOLDER (helper->dst_folder),
4713                                          TRUE,
4714                                          msgs_move_to_cb,
4715                                          movehelper);
4716
4717         g_object_unref (G_OBJECT (mail_op));
4718  end:
4719         if (dst_account)
4720                 g_object_unref (dst_account);
4721         g_object_unref (helper->dst_folder);
4722         g_object_unref (helper->headers);
4723         g_slice_free (XferMsgsHelper, helper);
4724 }
4725
4726 typedef struct {
4727         TnyFolder *src_folder;
4728         TnyFolderStore *dst_folder;
4729         gboolean delete_original;
4730         GtkWidget *folder_view;
4731 } MoveFolderInfo;
4732
4733 static void
4734 on_move_folder_cb (gboolean canceled,
4735                    GError *err,
4736                    GtkWindow *parent_window,
4737                    TnyAccount *account,
4738                    gpointer user_data)
4739 {
4740         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
4741         GtkTreeSelection *sel;
4742         ModestMailOperation *mail_op = NULL;
4743
4744         if (canceled || err || !MODEST_IS_WINDOW (parent_window)) {
4745                 /* Note that the connection process can fail due to
4746                    memory low conditions as it can not successfully
4747                    store the summary */
4748                 if (!modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
4749                                                                      (GtkWidget*) parent_window, err,
4750                                                                      account, NULL))
4751                         g_debug ("Error connecting when trying to move a folder");
4752
4753                 g_object_unref (G_OBJECT (info->src_folder));
4754                 g_object_unref (G_OBJECT (info->dst_folder));
4755                 g_free (info);
4756                 return;
4757         }
4758
4759         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4760 #ifndef MODEST_TOOLKIT_HILDON2
4761         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
4762                         _CS("ckct_nw_pasting"));
4763         if (helper->banner != NULL)  {
4764                 g_object_ref (helper->banner);
4765                 gtk_widget_show (GTK_WIDGET(helper->banner));
4766         }
4767 #endif
4768         /* Clean folder on header view before moving it */
4769         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
4770         gtk_tree_selection_unselect_all (sel);
4771
4772         /* Let gtk events run. We need that the folder
4773            view frees its reference to the source
4774            folder *before* issuing the mail operation
4775            so we need the signal handler of selection
4776            changed to happen before the mail
4777            operation
4778         while (gtk_events_pending ())
4779                 gtk_main_iteration ();   */
4780
4781         mail_op =
4782                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
4783                                                                modest_ui_actions_move_folder_error_handler,
4784                                                                g_object_ref (info->dst_folder), g_object_unref);
4785         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4786                                          mail_op);
4787
4788         modest_mail_operation_xfer_folder (mail_op,
4789                         TNY_FOLDER (info->src_folder),
4790                         info->dst_folder,
4791                         info->delete_original,
4792                         folder_move_to_cb,
4793                         helper);
4794         g_object_unref (G_OBJECT (info->src_folder));
4795
4796         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
4797         /* } */
4798
4799         /* Unref mail operation */
4800         g_object_unref (G_OBJECT (mail_op));
4801         g_object_unref (G_OBJECT (info->dst_folder));
4802         g_free (user_data);
4803 }
4804
4805 static TnyAccount *
4806 get_account_from_folder_store (TnyFolderStore *folder_store)
4807 {
4808         if (TNY_IS_ACCOUNT (folder_store))
4809                 return g_object_ref (folder_store);
4810         else
4811                 return tny_folder_get_account (TNY_FOLDER (folder_store));
4812 }
4813
4814 /*
4815  * UI handler for the "Move to" action when invoked from the
4816  * ModestFolderWindow
4817  */
4818 static void
4819 modest_ui_actions_on_folder_window_move_to (GtkWidget *folder_view,
4820                                             TnyFolderStore *dst_folder,
4821                                             TnyList *selection,
4822                                             GtkWindow *win)
4823 {
4824         TnyFolderStore *src_folder = NULL;
4825         TnyIterator *iterator;
4826
4827         if (tny_list_get_length (selection) != 1)
4828                 return;
4829
4830         iterator = tny_list_create_iterator (selection);
4831         src_folder = TNY_FOLDER_STORE (tny_iterator_get_current (iterator));
4832         g_object_unref (iterator);
4833
4834
4835         gboolean do_xfer = TRUE;
4836
4837         /* Allow only to transfer folders to the local root folder */
4838         if (TNY_IS_ACCOUNT (dst_folder) &&
4839             !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
4840             !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
4841                 do_xfer = FALSE;
4842                 /* Show an error */
4843                 modest_platform_run_information_dialog (win,
4844                                                         _("mail_in_ui_folder_move_target_error"),
4845                                                         FALSE);
4846         } else if (!TNY_IS_FOLDER (src_folder)) {
4847                 g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
4848                 do_xfer = FALSE;
4849         }
4850
4851         if (do_xfer) {
4852                 MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
4853                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
4854
4855                 info->src_folder = g_object_ref (src_folder);
4856                 info->dst_folder = g_object_ref (dst_folder);
4857                 info->delete_original = TRUE;
4858                 info->folder_view = folder_view;
4859
4860                 connect_info->callback = on_move_folder_cb;
4861                 connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
4862                 connect_info->data = info;
4863
4864                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
4865                                                            TNY_FOLDER_STORE (src_folder),
4866                                                            connect_info);
4867         }
4868
4869         /* Frees */
4870         g_object_unref (src_folder);
4871 }
4872
4873
4874 void
4875 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
4876                                             TnyFolder *src_folder,
4877                                             TnyList *headers,
4878                                             TnyFolder *dst_folder)
4879 {
4880         gboolean need_connection = TRUE;
4881         gboolean do_xfer = TRUE;
4882         XferMsgsHelper *helper;
4883
4884         g_return_if_fail (TNY_IS_FOLDER (src_folder));
4885         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
4886         g_return_if_fail (TNY_IS_LIST (headers));
4887
4888         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder),
4889                                                headers, TNY_FOLDER (dst_folder),
4890                                                TRUE, &need_connection,
4891                                                &do_xfer);
4892
4893         /* If we don't want to transfer just return */
4894         if (!do_xfer)
4895                 return;
4896
4897         /* Create the helper */
4898         helper = g_slice_new (XferMsgsHelper);
4899         helper->dst_folder = g_object_ref (dst_folder);
4900         helper->headers = g_object_ref (headers);
4901
4902         if (need_connection) {
4903                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
4904                 connect_info->callback = xfer_messages_performer;
4905                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4906                 connect_info->data = helper;
4907
4908                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
4909                                                            TNY_FOLDER_STORE (src_folder),
4910                                                            connect_info);
4911         } else {
4912                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
4913                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
4914                                          src_account, helper);
4915                 g_object_unref (src_account);
4916         }
4917 }
4918
4919 /*
4920  * UI handler for the "Move to" action when invoked from the
4921  * ModestMsgViewWindow
4922  */
4923 static void
4924 modest_ui_actions_on_window_move_to (GtkAction *action,
4925                                      TnyList *headers,
4926                                      TnyFolderStore *dst_folder,
4927                                      ModestWindow *win)
4928 {
4929         TnyFolder *src_folder = NULL;
4930
4931         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
4932
4933         if (headers) {
4934                 TnyHeader *header = NULL;
4935                 TnyIterator *iter;
4936
4937                 iter = tny_list_create_iterator (headers);
4938                 header = (TnyHeader *) tny_iterator_get_current (iter);
4939                 src_folder = tny_header_get_folder (header);
4940
4941                 /* Transfer the messages */
4942                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder,
4943                                                             headers,
4944                                                             TNY_FOLDER (dst_folder));
4945
4946                 /* Frees */
4947                 g_object_unref (header);
4948                 g_object_unref (iter);
4949                 g_object_unref (src_folder);
4950         }
4951 }
4952
4953 void
4954 modest_ui_actions_on_move_to (GtkAction *action,
4955                               ModestWindow *win)
4956 {
4957         modest_ui_actions_on_edit_mode_move_to (win);
4958 }
4959
4960 gboolean
4961 modest_ui_actions_on_edit_mode_move_to (ModestWindow *win)
4962 {
4963         GtkWidget *dialog = NULL;
4964         MoveToInfo *helper = NULL;
4965         TnyList *list_to_move;
4966
4967         g_return_val_if_fail (MODEST_IS_WINDOW (win), FALSE);
4968
4969
4970         list_to_move = modest_platform_get_list_to_move (MODEST_WINDOW (win));
4971
4972         if (!list_to_move)
4973                 return FALSE;
4974
4975         if (tny_list_get_length (list_to_move) < 1) {
4976                 g_object_unref (list_to_move);
4977                 return FALSE;
4978         }
4979
4980         /* Create and run the dialog */
4981         dialog = create_move_to_dialog (GTK_WINDOW (win), NULL, list_to_move);
4982         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (),
4983                                      GTK_WINDOW (dialog),
4984                                      (GtkWindow *) win);
4985
4986         /* Create helper */
4987         helper = g_slice_new0 (MoveToInfo);
4988         helper->list = list_to_move;
4989         helper->win = win;
4990
4991         /* Listen to response signal */
4992         g_signal_connect (dialog, "response", G_CALLBACK (on_move_to_dialog_response), helper);
4993
4994         /* Show the dialog */
4995         gtk_widget_show (dialog);
4996
4997         return FALSE;
4998 }
4999
5000 /*
5001  * Calls #HeadersFunc for each header already selected in the main
5002  * window or the message currently being shown in the msg view window
5003  */
5004 static void
5005 do_headers_action (ModestWindow *win,
5006                    HeadersFunc func,
5007                    gpointer user_data)
5008 {
5009         TnyList *headers_list = NULL;
5010         TnyIterator *iter = NULL;
5011         TnyHeader *header = NULL;
5012         TnyFolder *folder = NULL;
5013
5014         /* Get headers */
5015         headers_list = get_selected_headers (win);
5016         if (!headers_list)
5017                 return;
5018
5019         /* Get the folder */
5020         iter = tny_list_create_iterator (headers_list);
5021         header = TNY_HEADER (tny_iterator_get_current (iter));
5022         if (header) {
5023                 folder = tny_header_get_folder (header);
5024                 g_object_unref (header);
5025         }
5026
5027         /* Call the function for each header */
5028         while (!tny_iterator_is_done (iter)) {
5029                 header = TNY_HEADER (tny_iterator_get_current (iter));
5030                 func (header, win, user_data);
5031                 g_object_unref (header);
5032                 tny_iterator_next (iter);
5033         }
5034
5035         /* Trick: do a poke status in order to speed up the signaling
5036            of observers */
5037         if (folder) {
5038                 tny_folder_poke_status (folder);
5039                 g_object_unref (folder);
5040         }
5041
5042         /* Frees */
5043         g_object_unref (iter);
5044         g_object_unref (headers_list);
5045 }
5046
5047 void
5048 modest_ui_actions_view_attachment (GtkAction *action,
5049                                    ModestWindow *window)
5050 {
5051         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5052                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
5053         } else {
5054                 /* not supported window for this action */
5055                 g_return_if_reached ();
5056         }
5057 }
5058
5059 void
5060 modest_ui_actions_save_attachments (GtkAction *action,
5061                                     ModestWindow *window)
5062 {
5063         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5064
5065                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
5066                         return;
5067
5068                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
5069         } else {
5070                 /* not supported window for this action */
5071                 g_return_if_reached ();
5072         }
5073 }
5074
5075 void
5076 modest_ui_actions_remove_attachments (GtkAction *action,
5077                                       ModestWindow *window)
5078 {
5079         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5080                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
5081         } else {
5082                 /* not supported window for this action */
5083                 g_return_if_reached ();
5084         }
5085 }
5086
5087 void
5088 modest_ui_actions_on_settings (GtkAction *action,
5089                                ModestWindow *win)
5090 {
5091         GtkWidget *dialog;
5092
5093         dialog = modest_platform_get_global_settings_dialog ();
5094         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
5095         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5096         gtk_widget_show_all (dialog);
5097
5098         gtk_dialog_run (GTK_DIALOG (dialog));
5099
5100         gtk_widget_destroy (dialog);
5101 }
5102
5103 void
5104 modest_ui_actions_on_help (GtkAction *action,
5105                            GtkWindow *win)
5106 {
5107         /* Help app is not available at all in fremantle */
5108 #ifndef MODEST_TOOLKIT_HILDON2
5109         const gchar *help_id;
5110
5111         g_return_if_fail (win && GTK_IS_WINDOW(win));
5112
5113         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
5114
5115         if (help_id)
5116                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5117 #endif
5118 }
5119
5120 void
5121 modest_ui_actions_on_csm_help (GtkAction *action,
5122                                GtkWindow *win)
5123 {
5124         /* Help app is not available at all in fremantle */
5125 }
5126
5127 static void
5128 retrieve_contents_cb (ModestMailOperation *mail_op,
5129                       TnyHeader *header,
5130                       gboolean canceled,
5131                       TnyMsg *msg,
5132                       GError *err,
5133                       gpointer user_data)
5134 {
5135         /* We only need this callback to show an error in case of
5136            memory low condition */
5137         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
5138                 g_debug ("%s: message failed to retrieve. Memory low?", __FUNCTION__);
5139         }
5140 }
5141
5142 static void
5143 retrieve_msg_contents_performer (gboolean canceled,
5144                                  GError *err,
5145                                  GtkWindow *parent_window,
5146                                  TnyAccount *account,
5147                                  gpointer user_data)
5148 {
5149         ModestMailOperation *mail_op;
5150         TnyList *headers = TNY_LIST (user_data);
5151
5152         if (err || canceled) {
5153                 modest_tny_account_store_check_disk_full_error (modest_runtime_get_account_store(),
5154                                                                 (GtkWidget *) parent_window, err,
5155                                                                 account, NULL);
5156                 goto out;
5157         }
5158
5159         /* Create mail operation */
5160         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
5161                                                                  modest_ui_actions_disk_operations_error_handler,
5162                                                                  NULL, NULL);
5163         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5164         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
5165
5166         /* Frees */
5167         g_object_unref (mail_op);
5168  out:
5169         g_object_unref (headers);
5170         g_object_unref (account);
5171 }
5172
5173 void
5174 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
5175                                             ModestWindow *window)
5176 {
5177         TnyList *headers = NULL;
5178         TnyAccount *account = NULL;
5179         TnyIterator *iter = NULL;
5180         TnyHeader *header = NULL;
5181         TnyFolder *folder = NULL;
5182
5183         /* Get headers */
5184         headers = get_selected_headers (window);
5185         if (!headers)
5186                 return;
5187
5188         /* Pick the account */
5189         iter = tny_list_create_iterator (headers);
5190         header = TNY_HEADER (tny_iterator_get_current (iter));
5191         folder = tny_header_get_folder (header);
5192         account = tny_folder_get_account (folder);
5193         g_object_unref (folder);
5194         g_object_unref (header);
5195         g_object_unref (iter);
5196
5197         /* Connect and perform the message retrieval */
5198         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
5199                                              g_object_ref (account),
5200                                              retrieve_msg_contents_performer,
5201                                              g_object_ref (headers));
5202
5203         /* Frees */
5204         g_object_unref (account);
5205         g_object_unref (headers);
5206 }
5207
5208 void
5209 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
5210 {
5211         g_return_if_fail (MODEST_IS_WINDOW (window));
5212
5213         /* Update dimmed */
5214         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
5215 }
5216
5217 void
5218 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
5219 {
5220         g_return_if_fail (MODEST_IS_WINDOW (window));
5221
5222         /* Update dimmed */
5223         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
5224 }
5225
5226 void
5227 modest_ui_actions_on_email_menu_activated (GtkAction *action,
5228                                           ModestWindow *window)
5229 {
5230         g_return_if_fail (MODEST_IS_WINDOW (window));
5231
5232         /* Update dimmed */
5233         modest_ui_actions_check_menu_dimming_rules (window);
5234 }
5235
5236 void
5237 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
5238                                           ModestWindow *window)
5239 {
5240         g_return_if_fail (MODEST_IS_WINDOW (window));
5241
5242         /* Update dimmed */
5243         modest_ui_actions_check_menu_dimming_rules (window);
5244 }
5245
5246 void
5247 modest_ui_actions_on_view_menu_activated (GtkAction *action,
5248                                           ModestWindow *window)
5249 {
5250         g_return_if_fail (MODEST_IS_WINDOW (window));
5251
5252         /* Update dimmed */
5253         modest_ui_actions_check_menu_dimming_rules (window);
5254 }
5255
5256 void
5257 modest_ui_actions_on_format_menu_activated (GtkAction *action,
5258                                             ModestWindow *window)
5259 {
5260         g_return_if_fail (MODEST_IS_WINDOW (window));
5261
5262         /* Update dimmed */
5263         modest_ui_actions_check_menu_dimming_rules (window);
5264 }
5265
5266 void
5267 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
5268                                           ModestWindow *window)
5269 {
5270         g_return_if_fail (MODEST_IS_WINDOW (window));
5271
5272         /* Update dimmed */
5273         modest_ui_actions_check_menu_dimming_rules (window);
5274 }
5275
5276 void
5277 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
5278                                           ModestWindow *window)
5279 {
5280         g_return_if_fail (MODEST_IS_WINDOW (window));
5281
5282         /* Update dimmed */
5283         modest_ui_actions_check_menu_dimming_rules (window);
5284 }
5285
5286 void
5287 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
5288                                                  ModestWindow *window)
5289 {
5290         g_return_if_fail (MODEST_IS_WINDOW (window));
5291
5292         /* Update dimmed */
5293         modest_ui_actions_check_menu_dimming_rules (window);
5294 }
5295
5296 void
5297 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
5298                                                      ModestWindow *window)
5299 {
5300         g_return_if_fail (MODEST_IS_WINDOW (window));
5301
5302         /* Update dimmed */
5303         modest_ui_actions_check_menu_dimming_rules (window);
5304 }
5305
5306 void
5307 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
5308                                                      ModestWindow *window)
5309 {
5310         g_return_if_fail (MODEST_IS_WINDOW (window));
5311
5312         /* Update dimmed */
5313         modest_ui_actions_check_menu_dimming_rules (window);
5314 }
5315
5316 void
5317 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
5318 {
5319         g_return_if_fail (MODEST_IS_WINDOW (window));
5320
5321         /* we check for low-mem; in that case, show a warning, and don't allow
5322          * searching
5323          */
5324         if (modest_platform_check_memory_low (window, TRUE))
5325                 return;
5326
5327         modest_platform_show_search_messages (GTK_WINDOW (window));
5328 }
5329
5330 void
5331 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
5332 {
5333         g_return_if_fail (MODEST_IS_WINDOW (win));
5334
5335
5336         /* we check for low-mem; in that case, show a warning, and don't allow
5337          * for the addressbook
5338          */
5339         if (modest_platform_check_memory_low (win, TRUE))
5340                 return;
5341
5342
5343         modest_platform_show_addressbook (GTK_WINDOW (win));
5344 }
5345
5346
5347 void
5348 modest_ui_actions_on_toggle_find_in_page (GtkAction *action,
5349                                           ModestWindow *window)
5350 {
5351         gboolean active;
5352         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5353
5354         if (GTK_IS_TOGGLE_ACTION (action))
5355                 active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action));
5356         else
5357                 active = TRUE;
5358
5359         modest_msg_edit_window_toggle_isearch_toolbar (MODEST_MSG_EDIT_WINDOW (window),
5360                                                        active);
5361 }
5362
5363
5364 void
5365 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self,
5366                                                 TnyHeader *header,
5367                                                 TnyMsg *msg,
5368                                                 GError *err,
5369                                                 gpointer user_data)
5370 {
5371         const gchar* server_name = NULL;
5372         TnyTransportAccount *transport;
5373         gchar *message = NULL;
5374         ModestProtocol *protocol;
5375
5376         /* Don't show anything if the user cancelled something or the
5377          * send receive request is not interactive. Authentication
5378          * errors are managed by the account store so no need to show
5379          * a dialog here again */
5380         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
5381             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
5382             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
5383                 return;
5384
5385
5386         /* Get the server name. Note that we could be using a
5387            connection specific transport account */
5388         transport = (TnyTransportAccount *)
5389                 tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self));
5390         if (transport) {
5391                 ModestTnyAccountStore *acc_store;
5392                 const gchar *acc_name;
5393                 TnyTransportAccount *conn_specific;
5394
5395                 acc_store = modest_runtime_get_account_store();
5396                 acc_name = modest_tny_account_get_parent_modest_account_name_for_server_account (TNY_ACCOUNT (transport));
5397                 conn_specific = (TnyTransportAccount *)
5398                         modest_tny_account_store_get_transport_account_for_open_connection (acc_store, acc_name);
5399                 if (conn_specific) {
5400                         server_name = tny_account_get_hostname (TNY_ACCOUNT (conn_specific));
5401                         g_object_unref (conn_specific);
5402                 } else {
5403                         server_name = tny_account_get_hostname (TNY_ACCOUNT (transport));
5404                 }
5405                 g_object_unref (transport);
5406         }
5407
5408         /* Get protocol */
5409         protocol = modest_protocol_registry_get_protocol_by_name (modest_runtime_get_protocol_registry (),
5410                                                                   MODEST_PROTOCOL_REGISTRY_TRANSPORT_STORE_PROTOCOLS,
5411                                                                   tny_account_get_proto (TNY_ACCOUNT (transport)));
5412         if (!protocol) {
5413                 g_warning ("%s: Account with no proto", __FUNCTION__);
5414                 return;
5415         }
5416
5417         /* Show the appropriate message text for the GError: */
5418         switch (err->code) {
5419         case TNY_SERVICE_ERROR_CONNECT:
5420                 message = modest_protocol_get_translation (protocol,
5421                                                            MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR,
5422                                                            server_name);
5423                 break;
5424         case TNY_SERVICE_ERROR_SEND:
5425                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
5426                 break;
5427         case TNY_SERVICE_ERROR_UNAVAILABLE:
5428                 message = modest_protocol_get_translation (protocol,
5429                                                            MODEST_PROTOCOL_TRANSLATION_CONNECT_ERROR,
5430                                                            server_name);
5431                 break;
5432         default:
5433                 g_warning ("%s: unexpected ERROR %d",
5434                            __FUNCTION__, err->code);
5435                 message = g_strdup (_CS("sfil_ib_unable_to_send"));
5436                 break;
5437         }
5438
5439         modest_platform_run_information_dialog (NULL, message, FALSE);
5440         g_free (message);
5441 }
5442
5443 void
5444 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
5445                                                 gchar *msg_id,
5446                                                 guint status,
5447                                                 gpointer user_data)
5448 {
5449         ModestWindow *top_window = NULL;
5450         ModestWindowMgr *mgr = NULL;
5451         GtkWidget *header_view = NULL;
5452         TnyFolder *selected_folder = NULL;
5453         TnyFolderType folder_type;
5454
5455         mgr = modest_runtime_get_window_mgr ();
5456         top_window = modest_window_mgr_get_current_top (mgr);
5457
5458         if (!top_window)
5459                 return;
5460
5461         if (MODEST_IS_HEADER_WINDOW (top_window)) {
5462                 header_view = (GtkWidget *)
5463                         modest_header_window_get_header_view (MODEST_HEADER_WINDOW (top_window));
5464         }
5465
5466         /* Get selected folder */
5467         if (header_view)
5468                 selected_folder = modest_header_view_get_folder (MODEST_HEADER_VIEW (header_view));
5469         if (!selected_folder)
5470                 return;
5471
5472         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
5473 #if GTK_CHECK_VERSION(2, 8, 0)
5474         folder_type = modest_tny_folder_guess_folder_type (selected_folder);
5475         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {
5476                 GtkTreeViewColumn *tree_column;
5477
5478                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view),
5479                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
5480                 if (tree_column)
5481                         gtk_tree_view_column_queue_resize (tree_column);
5482                 }
5483 #else /* #if GTK_CHECK_VERSION(2, 8, 0) */
5484         gtk_widget_queue_draw (header_view);
5485 #endif
5486
5487 #ifndef MODEST_TOOLKIT_HILDON2
5488         /* Rerun dimming rules, because the message could become deletable for example */
5489         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
5490                                                  MODEST_DIMMING_RULES_TOOLBAR);
5491         modest_window_check_dimming_rules_group (MODEST_WINDOW (top_window),
5492                                                  MODEST_DIMMING_RULES_MENU);
5493 #endif
5494
5495         /* Free */
5496         g_object_unref (selected_folder);
5497 }
5498
5499 void
5500 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
5501                                                TnyAccount *account)
5502 {
5503         ModestProtocolType protocol_type;
5504         ModestProtocol *protocol;
5505         gchar *error_note = NULL;
5506
5507         protocol_type = modest_tny_account_get_protocol_type (account);
5508         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
5509                                                                   protocol_type);
5510
5511         error_note = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR, tny_account_get_hostname (account));
5512         if (error_note == NULL) {
5513                 g_warning ("%s: This should not be reached", __FUNCTION__);
5514         } else {
5515                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
5516                 g_free (error_note);
5517         }
5518 }
5519
5520 gchar *
5521 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
5522 {
5523         gchar *msg = NULL;
5524         gchar *subject;
5525         TnyFolderStore *folder = NULL;
5526         TnyAccount *account = NULL;
5527         ModestProtocolType proto;
5528         ModestProtocol *protocol;
5529         TnyHeader *header = NULL;
5530
5531         if (MODEST_IS_HEADER_WINDOW (win)) {
5532                 GtkWidget *header_view;
5533                 TnyList* headers = NULL;
5534                 TnyIterator *iter;
5535                 header_view = GTK_WIDGET (modest_header_window_get_header_view (MODEST_HEADER_WINDOW (win)));
5536                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5537                 if (!headers || tny_list_get_length (headers) == 0) {
5538                         if (headers)
5539                                 g_object_unref (headers);
5540                         return NULL;
5541                 }
5542                 iter = tny_list_create_iterator (headers);
5543                 header = TNY_HEADER (tny_iterator_get_current (iter));
5544                 if (header) {
5545                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
5546                 } else {
5547                         g_warning ("List should contain headers");
5548                 }
5549                 g_object_unref (iter);
5550                 g_object_unref (headers);
5551         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
5552                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5553                 if (header)
5554                         folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
5555         }
5556
5557         if (!header || !folder)
5558                 goto frees;
5559
5560         /* Get the account type */
5561         account = tny_folder_get_account (TNY_FOLDER (folder));
5562         proto = modest_tny_account_get_protocol_type (account);
5563         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
5564                                                                   proto);
5565
5566         subject = tny_header_dup_subject (header);
5567         msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
5568         if (subject)
5569                 g_free (subject);
5570         if (msg == NULL) {
5571                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
5572         }
5573
5574  frees:
5575         /* Frees */
5576         if (account)
5577                 g_object_unref (account);
5578         if (folder)
5579                 g_object_unref (folder);
5580         if (header)
5581                 g_object_unref (header);
5582
5583         return msg;
5584 }
5585
5586 gboolean
5587 modest_ui_actions_on_delete_account (GtkWindow *parent_window,
5588                                      const gchar *account_name,
5589                                      const gchar *account_title)
5590 {
5591         ModestAccountMgr *account_mgr;
5592         gchar *txt = NULL;
5593         gint response;
5594         ModestProtocol *protocol;
5595         gboolean removed = FALSE;
5596
5597         g_return_val_if_fail (account_name, FALSE);
5598         g_return_val_if_fail (account_title, FALSE);
5599
5600         account_mgr = modest_runtime_get_account_mgr();
5601
5602         /* The warning text depends on the account type: */
5603         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
5604                                                                   modest_account_mgr_get_store_protocol (account_mgr,
5605                                                                                                          account_name));
5606         txt = modest_protocol_get_translation (protocol,
5607                                                MODEST_PROTOCOL_TRANSLATION_DELETE_MAILBOX,
5608                                                account_title);
5609         if (txt == NULL)
5610                 txt = g_strdup_printf (_("emev_nc_delete_mailbox"), account_title);
5611
5612         response = modest_platform_run_confirmation_dialog (parent_window, txt);
5613         g_free (txt);
5614         txt = NULL;
5615
5616         if (response == GTK_RESPONSE_OK) {
5617                 /* Remove account. If it succeeds then it also removes
5618                    the account from the ModestAccountView: */
5619                 gboolean is_default = FALSE;
5620                 gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr);
5621                 if (default_account_name && (strcmp (default_account_name, account_name) == 0))
5622                         is_default = TRUE;
5623                 g_free (default_account_name);
5624
5625                 removed = modest_account_mgr_remove_account (account_mgr, account_name);
5626                 if (removed) {
5627                         /* Close all email notifications, we cannot
5628                            distinguish if the notification belongs to
5629                            this account or not, so for safety reasons
5630                            we remove them all */
5631                         modest_platform_remove_new_mail_notifications (FALSE);
5632                 } else {
5633                         g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__);
5634                 }
5635         }
5636         return removed;
5637 }
5638
5639 static void
5640 on_fetch_images_performer (gboolean canceled,
5641                            GError *err,
5642                            GtkWindow *parent_window,
5643                            TnyAccount *account,
5644                            gpointer user_data)
5645 {
5646         if (err || canceled) {
5647                 /* Show an unable to retrieve images ??? */
5648                 return;
5649         }
5650
5651         /* Note that the user could have closed the window while connecting */
5652         if (GTK_WIDGET_VISIBLE (parent_window))
5653                 modest_msg_view_window_fetch_images ((ModestMsgViewWindow *) parent_window);
5654         g_object_unref ((GObject *) user_data);
5655 }
5656
5657 void
5658 modest_ui_actions_on_fetch_images (GtkAction *action,
5659                                    ModestWindow *window)
5660 {
5661         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (window));
5662
5663         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE, 
5664                                              NULL,
5665                                              on_fetch_images_performer, 
5666                                              g_object_ref (window));
5667 }
5668
5669 void
5670 modest_ui_actions_on_reload_message (const gchar *msg_id)
5671 {
5672         ModestWindow *window = NULL;
5673
5674         g_return_if_fail (msg_id && msg_id[0] != '\0');
5675         if (!modest_window_mgr_find_registered_message_uid (modest_runtime_get_window_mgr (),
5676                                                             msg_id,
5677                                                             &window))
5678                 return;
5679
5680
5681         if (window == NULL || !MODEST_IS_MSG_VIEW_WINDOW (window))
5682                 return;
5683
5684         modest_msg_view_window_reload (MODEST_MSG_VIEW_WINDOW (window));
5685 }
5686
5687 /** Check whether any connections are active, and cancel them if 
5688  * the user wishes.
5689  * Returns TRUE is there was no problem, 
5690  * or if an operation was cancelled so we can continue.
5691  * Returns FALSE if the user chose to cancel his request instead.
5692  */
5693
5694 gboolean
5695 modest_ui_actions_check_for_active_account (ModestWindow *self,
5696                                             const gchar* account_name)
5697 {
5698         ModestTnySendQueue *send_queue;
5699         ModestTnyAccountStore *acc_store;
5700         ModestMailOperationQueue* queue;
5701         TnyConnectionStatus store_conn_status;
5702         TnyAccount *store_account = NULL, *transport_account = NULL;
5703         gboolean retval = TRUE, sending = FALSE;
5704
5705         acc_store = modest_runtime_get_account_store ();
5706         queue = modest_runtime_get_mail_operation_queue ();
5707
5708         store_account = 
5709                 modest_tny_account_store_get_server_account (acc_store,
5710                                                              account_name,
5711                                                              TNY_ACCOUNT_TYPE_STORE);
5712
5713         /* This could happen if the account was deleted before the
5714            call to this function */
5715         if (!store_account)
5716                 return FALSE;
5717
5718         transport_account = 
5719                 modest_tny_account_store_get_server_account (acc_store,
5720                                                              account_name,
5721                                                              TNY_ACCOUNT_TYPE_TRANSPORT);
5722
5723         /* This could happen if the account was deleted before the
5724            call to this function */
5725         if (!transport_account) {
5726                 g_object_unref (store_account);
5727                 return FALSE;
5728         }
5729
5730         /* If the transport account was not used yet, then the send
5731            queue could not exist (it's created on demand) */
5732         send_queue = modest_runtime_get_send_queue (TNY_TRANSPORT_ACCOUNT (transport_account), FALSE);
5733         if (TNY_IS_SEND_QUEUE (send_queue))
5734                 sending = modest_tny_send_queue_sending_in_progress (send_queue);
5735
5736         store_conn_status = tny_account_get_connection_status (store_account);
5737         if (store_conn_status == TNY_CONNECTION_STATUS_CONNECTED || sending) {
5738                 gint response;
5739
5740                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (self), 
5741                                                                 _("emev_nc_disconnect_account"));
5742                 if (response == GTK_RESPONSE_OK) {
5743                         retval = TRUE;
5744                 } else {
5745                         retval = FALSE;
5746                 }
5747         }
5748
5749         if (retval) {
5750
5751                 /* FIXME: We should only cancel those of this account */
5752                 modest_mail_operation_queue_cancel_all (queue);
5753
5754                 /* Also disconnect the account */
5755                 if ((tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED) &&
5756                     (tny_account_get_connection_status (store_account) != TNY_CONNECTION_STATUS_DISCONNECTED_BROKEN)) {
5757                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (store_account),
5758                                                       FALSE, NULL, NULL);
5759                 }
5760                 if (sending) {
5761                         tny_camel_account_set_online (TNY_CAMEL_ACCOUNT (transport_account),
5762                                                       FALSE, NULL, NULL);
5763                 }
5764         }
5765                 
5766         /* Frees */
5767         g_object_unref (store_account);
5768         g_object_unref (transport_account);
5769         
5770         return retval;
5771 }