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