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