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