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