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