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