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