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