* Fixes NB#88016, set details dialog as modal. Backported 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
2392                         /* Update the active account */
2393                         account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2394                         if (account) {
2395                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2396                                 account_name = 
2397                                         modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2398                                 g_object_unref (account);
2399                                 account = NULL;
2400                         }
2401
2402                         /* Set the header style by default, it could
2403                            be changed later by the refresh callback to
2404                            empty */
2405                         modest_main_window_set_contents_style (main_window, 
2406                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2407
2408                         /* Set folder on header view. This function
2409                            will call tny_folder_refresh_async so we
2410                            pass a callback that will be called when
2411                            finished. We use that callback to set the
2412                            empty view if there are no messages */
2413                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2414                                                        TNY_FOLDER (folder_store),
2415                                                        TRUE,
2416                                                        folder_refreshed_cb,
2417                                                        main_window);
2418                         
2419                         /* Restore configuration. We need to do this
2420                            *after* the set_folder because the widget
2421                            memory asks the header view about its
2422                            folder  */
2423                         modest_widget_memory_restore (modest_runtime_get_conf (), 
2424                                                       G_OBJECT(header_view),
2425                                                       MODEST_CONF_HEADER_VIEW_KEY);
2426                 } else {
2427                         /* No need to save the header view
2428                            configuration for Maemo because it only
2429                            saves the sorting stuff and that it's
2430                            already being done by the sort
2431                            dialog. Remove it when the GNOME version
2432                            has the same behaviour */
2433 #ifdef MODEST_PLATFORM_GNOME
2434                         if (modest_main_window_get_contents_style (main_window) ==
2435                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2436                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
2437                                                            MODEST_CONF_HEADER_VIEW_KEY);
2438 #endif
2439                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2440                 }
2441         }
2442
2443         /* Update dimming state */
2444         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2445         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2446 }
2447
2448 void 
2449 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2450                                      ModestWindow *win)
2451 {
2452         GtkWidget *dialog;
2453         gchar *txt, *item;
2454         gboolean online;
2455
2456         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2457         
2458         online = tny_device_is_online (modest_runtime_get_device());
2459
2460         if (online) {
2461                 /* already online -- the item is simply not there... */
2462                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2463                                                  GTK_DIALOG_MODAL,
2464                                                  GTK_MESSAGE_WARNING,
2465                                                  GTK_BUTTONS_NONE,
2466                                                  _("The %s you selected cannot be found"),
2467                                                  item);
2468                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2469                 gtk_dialog_run (GTK_DIALOG(dialog));
2470         } else {
2471                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2472                                                       GTK_WINDOW (win),
2473                                                       GTK_DIALOG_MODAL,
2474                                                       _("mcen_bd_dialog_cancel"),
2475                                                       GTK_RESPONSE_REJECT,
2476                                                       _("mcen_bd_dialog_ok"),
2477                                                       GTK_RESPONSE_ACCEPT,
2478                                                       NULL);
2479                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2480                                          "Do you want to get online?"), item);
2481                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
2482                                     gtk_label_new (txt), FALSE, FALSE, 0);
2483                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2484                 g_free (txt);
2485
2486                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2487                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2488                         /* TODO: Comment about why is this commented out: */
2489                         /* modest_platform_connect_and_wait (); */
2490                 }
2491         }
2492         gtk_widget_destroy (dialog);
2493 }
2494
2495 void
2496 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2497                                      ModestWindow *win)
2498 {
2499         /* g_message ("%s %s", __FUNCTION__, link); */
2500 }       
2501
2502
2503 void
2504 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2505                                         ModestWindow *win)
2506 {
2507         modest_platform_activate_uri (link);
2508 }
2509
2510 void
2511 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2512                                           ModestWindow *win)
2513 {
2514         modest_platform_show_uri_popup (link);
2515 }
2516
2517 void
2518 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2519                                              ModestWindow *win)
2520 {               
2521         /* we check for low-mem; in that case, show a warning, and don't allow
2522          * viewing attachments
2523          */
2524         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
2525                 return;
2526
2527         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2528 }
2529
2530 void
2531 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2532                                           const gchar *address,
2533                                           ModestWindow *win)
2534 {
2535         /* g_message ("%s %s", __FUNCTION__, address); */
2536 }
2537
2538 static void
2539 on_save_to_drafts_cb (ModestMailOperation *mail_op, 
2540                       TnyMsg *saved_draft,
2541                       gpointer user_data)
2542 {
2543         ModestMsgEditWindow *edit_window;
2544         ModestMainWindow *win;
2545
2546         /* FIXME. Make the header view sensitive again. This is a
2547          * temporary hack. See modest_ui_actions_on_save_to_drafts()
2548          * for details */
2549         win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2550                                          modest_runtime_get_window_mgr(), FALSE));
2551         if (win != NULL) {
2552                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2553                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2554                 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2555         }
2556
2557         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2558
2559         /* Set draft is there was no error */
2560         if (!modest_mail_operation_get_error (mail_op))
2561                 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2562
2563         g_object_unref(edit_window);
2564 }
2565
2566 gboolean
2567 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2568 {
2569         TnyTransportAccount *transport_account;
2570         ModestMailOperation *mail_operation;
2571         MsgData *data;
2572         gchar *account_name, *from;
2573         ModestAccountMgr *account_mgr;
2574 /*      char *info_text; */
2575         gboolean had_error = FALSE;
2576         guint64 available_disk, expected_size;
2577         gint parts_count;
2578         guint64 parts_size;
2579         ModestMainWindow *win;
2580
2581         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
2582         
2583         data = modest_msg_edit_window_get_msg_data (edit_window);
2584
2585         /* Check size */
2586         available_disk = modest_folder_available_space (NULL);
2587         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2588         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2589                                                  data->html_body,
2590                                                  parts_count,
2591                                                  parts_size);
2592
2593         if ((available_disk != -1) && expected_size > available_disk) {
2594                 modest_msg_edit_window_free_msg_data (edit_window, data);
2595
2596                 modest_platform_information_banner (NULL, NULL, dgettext("ke-recv", "cerm_device_memory_full"));
2597                 return FALSE;
2598         }
2599
2600         /*
2601          * djcb: if we're in low-memory state, we only allow for
2602          * saving messages smaller than
2603          * MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h) this
2604          * should still allow for sending anything critical...
2605          */
2606         if (expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) {
2607
2608                 if (modest_platform_check_memory_low (MODEST_WINDOW(edit_window), TRUE)) {
2609                         modest_msg_edit_window_free_msg_data (edit_window, data);
2610                         return FALSE;
2611                 }
2612         }
2613
2614         /*
2615          * djcb: we also make sure that the attachments are smaller than the max size
2616          * this is for the case where we'd try to forward a message with attachments 
2617          * bigger than our max allowed size, or sending an message from drafts which
2618          * somehow got past our checks when attaching.
2619          */
2620         if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
2621                 modest_platform_run_information_dialog (
2622                         GTK_WINDOW(edit_window),
2623                         dgettext("ke-recv","memr_ib_operation_disabled"),
2624                         TRUE);
2625                 modest_msg_edit_window_free_msg_data (edit_window, data);
2626                 return FALSE;
2627         }
2628
2629         account_name = g_strdup (data->account_name);
2630         account_mgr = modest_runtime_get_account_mgr();
2631         if (!account_name)
2632                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2633         if (!account_name) 
2634                 account_name = modest_account_mgr_get_default_account (account_mgr);
2635         if (!account_name) {
2636                 g_printerr ("modest: no account found\n");
2637                 modest_msg_edit_window_free_msg_data (edit_window, data);
2638                 return FALSE;
2639         }
2640
2641         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2642                 account_name = g_strdup (data->account_name);
2643         }
2644
2645         transport_account =
2646                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2647                                       (modest_runtime_get_account_store(),
2648                                        account_name,
2649                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2650         if (!transport_account) {
2651                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2652                 g_free (account_name);
2653                 modest_msg_edit_window_free_msg_data (edit_window, data);
2654                 return FALSE;
2655         }
2656         from = modest_account_mgr_get_from_string (account_mgr, account_name);
2657
2658         /* Create the mail operation */         
2659         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler,
2660                                                                         NULL, NULL);
2661         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2662
2663         modest_mail_operation_save_to_drafts (mail_operation,
2664                                               transport_account,
2665                                               data->draft_msg,
2666                                               from,
2667                                               data->to, 
2668                                               data->cc, 
2669                                               data->bcc,
2670                                               data->subject, 
2671                                               data->plain_body, 
2672                                               data->html_body,
2673                                               data->attachments,
2674                                               data->images,
2675                                               data->priority_flags,
2676                                               on_save_to_drafts_cb,
2677                                               g_object_ref(edit_window));
2678
2679         /* Use the main window as the parent of the banner, if the
2680            main window does not exist it won't be shown, if the parent
2681            window exists then it's properly shown. We don't use the
2682            editor window because it could be closed (save to drafts
2683            could happen after closing the window */
2684         win = (ModestMainWindow *)
2685                 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
2686         if (win) {
2687                 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2688                 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
2689                 g_free (text);
2690         }
2691         modest_msg_edit_window_set_modified (edit_window, FALSE);
2692
2693         /* Frees */
2694         g_free (from);
2695         g_free (account_name);
2696         g_object_unref (G_OBJECT (transport_account));
2697         g_object_unref (G_OBJECT (mail_operation));
2698
2699         modest_msg_edit_window_free_msg_data (edit_window, data);
2700
2701         /* ** FIXME **
2702          * If the drafts folder is selected then make the header view
2703          * insensitive while the message is being saved to drafts
2704          * (it'll be sensitive again in on_save_to_drafts_cb()). This
2705          * is not very clean but it avoids letting the drafts folder
2706          * in an inconsistent state: the user could edit the message
2707          * being saved and undesirable things would happen.
2708          * In the average case the user won't notice anything at
2709          * all. In the worst case (the user is editing a really big
2710          * file from Drafts) the header view will be insensitive
2711          * during the saving process (10 or 20 seconds, depending on
2712          * the message). Anyway this is just a quick workaround: once
2713          * we find a better solution it should be removed
2714          * See NB#65125 (commend #18) for details.
2715          */
2716         if (!had_error && win != NULL) {
2717                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
2718                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
2719                 if (view != NULL) {
2720                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
2721                         if (folder) {
2722                                 if (modest_tny_folder_is_local_folder(folder)) {
2723                                         TnyFolderType folder_type;
2724                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
2725                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
2726                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2727                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2728                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
2729                                         }
2730                                 }
2731                         }
2732                         if (folder != NULL) g_object_unref(folder);
2733                 }
2734         }
2735
2736         return !had_error;
2737 }
2738
2739 /* For instance, when clicking the Send toolbar button when editing a message: */
2740 gboolean
2741 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2742 {
2743         TnyTransportAccount *transport_account = NULL;
2744         gboolean had_error = FALSE;
2745         guint64 available_disk, expected_size;
2746         gint parts_count;
2747         guint64 parts_size;
2748
2749         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
2750
2751         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2752                 return TRUE;
2753         
2754         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2755
2756         /* Check size */
2757         available_disk = modest_folder_available_space (NULL);
2758         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2759         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2760                                                  data->html_body,
2761                                                  parts_count,
2762                                                  parts_size);
2763
2764         if ((available_disk != -1) && expected_size > available_disk) {
2765                 modest_msg_edit_window_free_msg_data (edit_window, data);
2766
2767                 modest_platform_information_banner (NULL, NULL, dgettext("ke-recv", "cerm_device_memory_full"));
2768                 return FALSE;
2769         }
2770
2771         
2772         /*
2773          * djcb: if we're in low-memory state, we only allow for sending messages
2774          * smaller than MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h)
2775          * this should still allow for sending anything critical... 
2776          */
2777         if (expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) {
2778                 if (modest_platform_check_memory_low (MODEST_WINDOW(edit_window), TRUE)) {
2779                         modest_msg_edit_window_free_msg_data (edit_window, data);
2780                         return FALSE;
2781                 }
2782         }
2783
2784         /*
2785          * djcb: we also make sure that the attachments are smaller than the max size
2786          * this is for the case where we'd try to forward a message with attachments 
2787          * bigger than our max allowed size, or sending an message from drafts which
2788          * somehow got past our checks when attaching.
2789          */
2790         if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
2791                 modest_platform_run_information_dialog (
2792                         GTK_WINDOW(edit_window),
2793                         dgettext("ke-recv","memr_ib_operation_disabled"),
2794                         TRUE);
2795                 modest_msg_edit_window_free_msg_data (edit_window, data);
2796                 return FALSE;
2797         }
2798
2799         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2800         gchar *account_name = g_strdup (data->account_name);
2801         if (!account_name)
2802                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2803
2804         if (!account_name) 
2805                 account_name = modest_account_mgr_get_default_account (account_mgr);
2806                 
2807         if (!account_name) {
2808                 modest_msg_edit_window_free_msg_data (edit_window, data);
2809                 /* Run account setup wizard */
2810                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
2811                         return TRUE;
2812                 }
2813         }
2814         
2815         /* Get the currently-active transport account for this modest account: */
2816         if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
2817                 transport_account = TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2818                                                           (modest_runtime_get_account_store(),
2819                                                            account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
2820         }
2821         
2822         if (!transport_account) {
2823                 modest_msg_edit_window_free_msg_data (edit_window, data);
2824                 /* Run account setup wizard */
2825                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
2826                         return TRUE;
2827         }
2828         
2829         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2830
2831         /* Create the mail operation */
2832         ModestMailOperation *mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler, NULL, NULL);
2833         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2834
2835         modest_mail_operation_send_new_mail (mail_operation,
2836                                              transport_account,
2837                                              data->draft_msg,
2838                                              from,
2839                                              data->to,
2840                                              data->cc, 
2841                                              data->bcc,
2842                                              data->subject, 
2843                                              data->plain_body, 
2844                                              data->html_body,
2845                                              data->attachments,
2846                                              data->images,
2847                                              data->priority_flags);
2848
2849         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2850                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
2851
2852
2853         if (modest_mail_operation_get_error (mail_operation) != NULL) {
2854                 const GError *error = modest_mail_operation_get_error (mail_operation);
2855                 if (error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
2856                         g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
2857                         modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
2858                         had_error = TRUE;
2859                 }
2860         }
2861                                              
2862         /* Free data: */
2863         g_free (from);
2864         g_free (account_name);
2865         g_object_unref (G_OBJECT (transport_account));
2866         g_object_unref (G_OBJECT (mail_operation));
2867
2868         modest_msg_edit_window_free_msg_data (edit_window, data);
2869
2870         if (!had_error) {
2871                 modest_msg_edit_window_set_sent (edit_window, TRUE);
2872
2873                 /* Save settings and close the window: */
2874                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2875         }
2876
2877         return !had_error;
2878 }
2879
2880 void 
2881 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2882                                   ModestMsgEditWindow *window)
2883 {
2884         ModestMsgEditFormatState *format_state = NULL;
2885
2886         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2887         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2888
2889         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2890                 return;
2891
2892         format_state = modest_msg_edit_window_get_format_state (window);
2893         g_return_if_fail (format_state != NULL);
2894
2895         format_state->bold = gtk_toggle_action_get_active (action);
2896         modest_msg_edit_window_set_format_state (window, format_state);
2897         g_free (format_state);
2898         
2899 }
2900
2901 void 
2902 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2903                                      ModestMsgEditWindow *window)
2904 {
2905         ModestMsgEditFormatState *format_state = NULL;
2906
2907         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2908         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2909
2910         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2911                 return;
2912
2913         format_state = modest_msg_edit_window_get_format_state (window);
2914         g_return_if_fail (format_state != NULL);
2915
2916         format_state->italics = gtk_toggle_action_get_active (action);
2917         modest_msg_edit_window_set_format_state (window, format_state);
2918         g_free (format_state);
2919         
2920 }
2921
2922 void 
2923 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2924                                      ModestMsgEditWindow *window)
2925 {
2926         ModestMsgEditFormatState *format_state = NULL;
2927
2928         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2929         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2930
2931         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2932                 return;
2933
2934         format_state = modest_msg_edit_window_get_format_state (window);
2935         g_return_if_fail (format_state != NULL);
2936
2937         format_state->bullet = gtk_toggle_action_get_active (action);
2938         modest_msg_edit_window_set_format_state (window, format_state);
2939         g_free (format_state);
2940         
2941 }
2942
2943 void 
2944 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2945                                      GtkRadioAction *selected,
2946                                      ModestMsgEditWindow *window)
2947 {
2948         ModestMsgEditFormatState *format_state = NULL;
2949         GtkJustification value;
2950
2951         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2952
2953         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2954                 return;
2955
2956         value = gtk_radio_action_get_current_value (selected);
2957
2958         format_state = modest_msg_edit_window_get_format_state (window);
2959         g_return_if_fail (format_state != NULL);
2960
2961         format_state->justification = value;
2962         modest_msg_edit_window_set_format_state (window, format_state);
2963         g_free (format_state);
2964 }
2965
2966 void 
2967 modest_ui_actions_on_select_editor_color (GtkAction *action,
2968                                           ModestMsgEditWindow *window)
2969 {
2970         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2971         g_return_if_fail (GTK_IS_ACTION (action));
2972
2973         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2974                 return;
2975
2976         modest_msg_edit_window_select_color (window);
2977 }
2978
2979 void 
2980 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2981                                                      ModestMsgEditWindow *window)
2982 {
2983         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2984         g_return_if_fail (GTK_IS_ACTION (action));
2985
2986         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2987                 return;
2988
2989         modest_msg_edit_window_select_background_color (window);
2990 }
2991
2992 void 
2993 modest_ui_actions_on_insert_image (GtkAction *action,
2994                                    ModestMsgEditWindow *window)
2995 {
2996         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2997         g_return_if_fail (GTK_IS_ACTION (action));
2998
2999
3000         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3001                 return;
3002
3003         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3004                 return;
3005
3006         modest_msg_edit_window_insert_image (window);
3007 }
3008
3009 void 
3010 modest_ui_actions_on_attach_file (GtkAction *action,
3011                                   ModestMsgEditWindow *window)
3012 {
3013         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3014         g_return_if_fail (GTK_IS_ACTION (action));
3015
3016         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3017                 return;
3018         
3019         modest_msg_edit_window_offer_attach_file (window);
3020 }
3021
3022 void 
3023 modest_ui_actions_on_remove_attachments (GtkAction *action,
3024                                          ModestMsgEditWindow *window)
3025 {
3026         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3027         g_return_if_fail (GTK_IS_ACTION (action));
3028
3029         modest_msg_edit_window_remove_attachments (window, NULL);
3030 }
3031
3032
3033 #ifdef MODEST_PLATFORM_MAEMO
3034 typedef struct {
3035         guint handler;
3036         gchar *name;
3037         GtkWindow *win;
3038         TnyFolderStore *folder;
3039 } CreateFolderHelper;
3040
3041 static gboolean
3042 show_create_folder_in_timeout (gpointer data)
3043 {
3044         CreateFolderHelper *helper = (CreateFolderHelper *) data;
3045
3046         /* Remove the timeout ASAP, we can not wait until the dialog
3047            is shown because it could take a lot of time and so the
3048            timeout could be called twice or more times */
3049         g_source_remove (helper->handler);
3050
3051         gdk_threads_enter ();
3052         do_create_folder (helper->win, helper->folder, helper->name);
3053         gdk_threads_leave ();
3054
3055         g_object_unref (helper->win);
3056         g_object_unref (helper->folder);
3057         g_free (helper->name);
3058         g_slice_free (CreateFolderHelper, helper);
3059
3060         return FALSE;
3061 }
3062 #endif
3063
3064 static void
3065 do_create_folder_cb (ModestMailOperation *mail_op,
3066                      TnyFolderStore *parent_folder, 
3067                      TnyFolder *new_folder,
3068                      gpointer user_data)
3069 {
3070         gchar *suggested_name = (gchar *) user_data;
3071         GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
3072
3073         if (modest_mail_operation_get_error (mail_op)) {
3074
3075                 /* Show an error. If there was some problem writing to
3076                    disk, show it, otherwise show the generic folder
3077                    create error. We do it here and not in an error
3078                    handler because the call to do_create_folder will
3079                    stop the main loop in a gtk_dialog_run and then,
3080                    the message won't be shown until that dialog is
3081                    closed */
3082                 modest_ui_actions_disk_operations_error_handler (mail_op,
3083                                                                  _("mail_in_ui_folder_create_error"));
3084
3085                 /* Try again. Do *NOT* show any error because the mail
3086                    operations system will do it for us because we
3087                    created the mail_op with new_with_error_handler */
3088 #ifdef MODEST_PLATFORM_MAEMO
3089                 CreateFolderHelper *helper;
3090                 helper = g_slice_new0 (CreateFolderHelper);
3091                 helper->name = g_strdup (suggested_name);
3092                 helper->folder = g_object_ref (parent_folder);
3093                 helper->win = g_object_ref (source_win);
3094
3095                 /* Ugly but neccesary stuff. The problem is that the
3096                    dialog when is shown calls a function that destroys
3097                    all the temporary windows, so the banner is
3098                    destroyed */
3099                 helper->handler = g_timeout_add (2000, show_create_folder_in_timeout, helper);
3100 #else
3101                 do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
3102 #endif
3103         } else {
3104                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
3105                  * FIXME: any other? */         
3106                 GtkWidget *folder_view;
3107
3108                 if (MODEST_IS_MAIN_WINDOW(source_win)) 
3109                         folder_view = 
3110                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
3111                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3112                 else
3113                         folder_view =
3114                                 get_folder_view_from_move_to_dialog (GTK_WIDGET(source_win));
3115                 
3116                 /* Select the newly created folder. It could happen
3117                    that the widget is no longer there (i.e. the window
3118                    has been destroyed, so we need to check this */
3119                 if (folder_view)
3120                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
3121                                                           new_folder, FALSE);
3122                 g_object_unref (new_folder);
3123         }
3124         /* Free. Note that the first time it'll be NULL so noop */
3125         g_free (suggested_name);
3126         g_object_unref (source_win);
3127 }
3128
3129 static void
3130 do_create_folder (GtkWindow *parent_window, 
3131                   TnyFolderStore *parent_folder, 
3132                   const gchar *suggested_name)
3133 {
3134         gint result;
3135         gchar *folder_name = NULL;
3136
3137         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
3138                                                         parent_folder,
3139                                                         (gchar *) suggested_name,
3140                                                         &folder_name);
3141         
3142         if (result == GTK_RESPONSE_ACCEPT) {
3143                 ModestMailOperation *mail_op;
3144                 
3145                 mail_op  = modest_mail_operation_new ((GObject *) parent_window);
3146                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3147                                                  mail_op);
3148                 modest_mail_operation_create_folder (mail_op,
3149                                                      parent_folder,
3150                                                      (const gchar *) folder_name,
3151                                                      do_create_folder_cb,
3152                                                      folder_name);
3153                 g_object_unref (mail_op);
3154         }
3155 }
3156
3157 static void
3158 create_folder_performer (gboolean canceled, 
3159                          GError *err,
3160                          GtkWindow *parent_window, 
3161                          TnyAccount *account, 
3162                          gpointer user_data)
3163 {
3164         TnyFolderStore *parent_folder = TNY_FOLDER_STORE (user_data);
3165
3166         if (canceled || err) {
3167                 /* In memory full conditions we could get this error here */
3168                 check_memory_full_error ((GtkWidget *) parent_window, err);
3169                 goto frees;
3170         }
3171
3172         /* Run the new folder dialog */
3173         do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
3174
3175  frees:
3176         g_object_unref (parent_folder);
3177 }
3178
3179 static void
3180 modest_ui_actions_create_folder(GtkWidget *parent_window,
3181                                 GtkWidget *folder_view)
3182 {
3183         TnyFolderStore *parent_folder;
3184
3185         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3186         
3187         if (parent_folder) {
3188                 /* The parent folder will be freed in the callback */
3189                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window), 
3190                                                                TRUE,
3191                                                                parent_folder,
3192                                                                create_folder_performer, 
3193                                                                parent_folder);
3194         }
3195 }
3196
3197 void 
3198 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
3199 {
3200         GtkWidget *folder_view;
3201         
3202         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3203
3204         folder_view = modest_main_window_get_child_widget (main_window,
3205                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3206         if (!folder_view)
3207                 return;
3208
3209         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
3210 }
3211
3212 static void
3213 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
3214                                                gpointer user_data)
3215 {
3216         const GError *error = NULL;
3217         const gchar *message = NULL;
3218         
3219         /* Get error message */
3220         error = modest_mail_operation_get_error (mail_op);
3221         if (!error)
3222                 g_return_if_reached ();
3223
3224         switch (error->code) {
3225         case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
3226                 message = _CS("ckdg_ib_folder_already_exists");
3227                 break;
3228         default:
3229                 message = _("emev_ib_ui_imap_unable_to_rename");
3230         }
3231
3232         /* We don't set a parent for the dialog because the dialog
3233            will be destroyed so the banner won't appear */
3234         modest_platform_information_banner (NULL, NULL, message);
3235 }
3236
3237 typedef struct {
3238         TnyFolderStore *folder;
3239         gchar *new_name;
3240 } RenameFolderInfo;
3241
3242 static void
3243 on_rename_folder_cb (ModestMailOperation *mail_op, 
3244                      TnyFolder *new_folder,
3245                      gpointer user_data)
3246 {
3247         ModestFolderView *folder_view;
3248
3249         /* If the window was closed when renaming a folder this could
3250            happen */
3251         if (!MODEST_IS_FOLDER_VIEW (user_data))
3252                 return;
3253
3254         folder_view = MODEST_FOLDER_VIEW (user_data);
3255         /* Note that if the rename fails new_folder will be NULL */
3256         if (new_folder) {
3257                 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
3258         } else {
3259                 modest_folder_view_select_first_inbox_or_local (folder_view);
3260         }
3261         gtk_widget_grab_focus (GTK_WIDGET (folder_view));       
3262 }
3263
3264 static void
3265 on_rename_folder_performer (gboolean canceled, 
3266                             GError *err, 
3267                             GtkWindow *parent_window, 
3268                             TnyAccount *account, 
3269                             gpointer user_data)
3270 {
3271         ModestMailOperation *mail_op = NULL;
3272         GtkTreeSelection *sel = NULL;
3273         GtkWidget *folder_view = NULL;
3274         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
3275
3276         if (canceled || err) {
3277                 /* In memory full conditions we could get this error here */
3278                 check_memory_full_error ((GtkWidget *) parent_window, err);
3279         } else if (MODEST_IS_MAIN_WINDOW(parent_window)) {
3280
3281                 folder_view = modest_main_window_get_child_widget (
3282                                 MODEST_MAIN_WINDOW (parent_window),
3283                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3284
3285                 mail_op = 
3286                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3287                                         modest_ui_actions_rename_folder_error_handler,
3288                                         parent_window, NULL);
3289
3290                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3291                                 mail_op);
3292
3293                 /* Clear the headers view */
3294                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3295                 gtk_tree_selection_unselect_all (sel);
3296
3297                 /* Actually rename the folder */
3298                 modest_mail_operation_rename_folder (mail_op,
3299                                                      TNY_FOLDER (data->folder),
3300                                                      (const gchar *) (data->new_name),
3301                                                      on_rename_folder_cb,
3302                                                      folder_view);
3303                 g_object_unref (mail_op);
3304         }
3305
3306         g_free (data->new_name);
3307         g_free (data);
3308 }
3309
3310 void 
3311 modest_ui_actions_on_rename_folder (GtkAction *action,
3312                                      ModestMainWindow *main_window)
3313 {
3314         TnyFolderStore *folder;
3315         GtkWidget *folder_view;
3316         GtkWidget *header_view; 
3317
3318         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3319
3320         folder_view = modest_main_window_get_child_widget (main_window,
3321                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3322         if (!folder_view)
3323                 return;
3324
3325         header_view = modest_main_window_get_child_widget (main_window,
3326                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3327         
3328         if (!header_view)
3329                 return;
3330
3331         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3332
3333         if (!folder)
3334                 return;
3335
3336         if (TNY_IS_FOLDER (folder)) {
3337                 gchar *folder_name;
3338                 gint response;
3339                 const gchar *current_name;
3340                 TnyFolderStore *parent;
3341                 gboolean do_rename = TRUE;
3342
3343                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
3344                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
3345                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
3346                                                                      parent, current_name, 
3347                                                                      &folder_name);
3348                 g_object_unref (parent);
3349
3350                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
3351                         do_rename = FALSE;
3352                 } else {
3353                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
3354                         rename_folder_data->folder = folder;
3355                         rename_folder_data->new_name = folder_name;
3356                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(main_window), TRUE,
3357                                         folder, on_rename_folder_performer, rename_folder_data);
3358                 }
3359         }
3360         g_object_unref (folder);
3361 }
3362
3363 static void
3364 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3365                                                gpointer user_data)
3366 {
3367         GObject *win = modest_mail_operation_get_source (mail_op);
3368
3369         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3370                                                 _("mail_in_ui_folder_delete_error"),
3371                                                 FALSE);
3372         g_object_unref (win);
3373 }
3374
3375 typedef struct {
3376         TnyFolderStore *folder;
3377         gboolean move_to_trash;
3378 } DeleteFolderInfo;
3379
3380 static void
3381 on_delete_folder_cb (gboolean canceled, 
3382                   GError *err,
3383                   GtkWindow *parent_window, 
3384                   TnyAccount *account, 
3385                   gpointer user_data)
3386 {
3387         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3388         GtkWidget *folder_view;
3389         ModestMailOperation *mail_op;
3390         GtkTreeSelection *sel;
3391         
3392         if (!MODEST_IS_MAIN_WINDOW(parent_window) || canceled || (err!=NULL)) {
3393                 g_object_unref (G_OBJECT (info->folder));
3394                 g_free (info);
3395                 return;
3396         }
3397         
3398         folder_view = modest_main_window_get_child_widget (
3399                         MODEST_MAIN_WINDOW (parent_window),
3400                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3401
3402         /* Unselect the folder before deleting it to free the headers */
3403         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3404         gtk_tree_selection_unselect_all (sel);
3405
3406         /* Create the mail operation */
3407         mail_op =
3408                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3409                                 modest_ui_actions_delete_folder_error_handler,
3410                                 NULL, NULL);
3411
3412         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3413                         mail_op);
3414         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3415         
3416         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3417
3418         g_object_unref (G_OBJECT (mail_op));
3419         g_object_unref (G_OBJECT (info->folder));
3420         g_free (info);
3421 }
3422
3423 static void
3424 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
3425 {
3426         TnyFolderStore *folder;
3427         GtkWidget *folder_view;
3428         gint response;
3429         gchar *message;
3430         
3431         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3432
3433         folder_view = modest_main_window_get_child_widget (main_window,
3434                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3435         if (!folder_view)
3436                 return;
3437
3438         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3439
3440         /* Show an error if it's an account */
3441         if (!TNY_IS_FOLDER (folder)) {
3442                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
3443                                                         _("mail_in_ui_folder_delete_error"),
3444                                                         FALSE);
3445                 g_object_unref (G_OBJECT (folder));
3446                 return;
3447         }
3448
3449         /* Ask the user */      
3450         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
3451                                     tny_folder_get_name (TNY_FOLDER (folder)));
3452         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
3453                                                             (const gchar *) message);
3454         g_free (message);
3455
3456         if (response == GTK_RESPONSE_OK) {
3457                 DeleteFolderInfo *info;
3458                 info = g_new0(DeleteFolderInfo, 1);
3459                 info->folder = folder;
3460                 info->move_to_trash = move_to_trash;
3461                 g_object_ref (G_OBJECT (info->folder));
3462                 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder));
3463                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (main_window), 
3464                                                                TRUE,
3465                                                                TNY_FOLDER_STORE (account), 
3466                                                                on_delete_folder_cb, info);
3467                 g_object_unref (account);
3468         }
3469         g_object_unref (G_OBJECT (folder));
3470 }
3471
3472 void 
3473 modest_ui_actions_on_delete_folder (GtkAction *action,
3474                                      ModestMainWindow *main_window)
3475 {
3476         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3477         
3478         delete_folder (main_window, FALSE);
3479 }
3480
3481 void 
3482 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
3483 {
3484         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3485         
3486         delete_folder (main_window, TRUE);
3487 }
3488
3489
3490 typedef struct _PasswordDialogFields {
3491         GtkWidget *username;
3492         GtkWidget *password;
3493         GtkWidget *dialog;
3494 } PasswordDialogFields;
3495
3496 static void
3497 password_dialog_check_field (GtkEditable *editable,
3498                              PasswordDialogFields *fields)
3499 {
3500         const gchar *value;
3501         gboolean any_value_empty = FALSE;
3502
3503         value = gtk_entry_get_text (GTK_ENTRY (fields->username));
3504         if ((value == NULL) || value[0] == '\0') {
3505                 any_value_empty = TRUE;
3506         }
3507         value = gtk_entry_get_text (GTK_ENTRY (fields->password));
3508         if ((value == NULL) || value[0] == '\0') {
3509                 any_value_empty = TRUE;
3510         }
3511         gtk_dialog_set_response_sensitive (GTK_DIALOG (fields->dialog), GTK_RESPONSE_ACCEPT, !any_value_empty);
3512 }
3513
3514 void
3515 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
3516                                          const gchar* server_account_name,
3517                                          gchar **username,
3518                                          gchar **password, 
3519                                          gboolean *cancel, 
3520                                          gboolean *remember,
3521                                          ModestMainWindow *main_window)
3522 {
3523         g_return_if_fail(server_account_name);
3524         gboolean completed = FALSE;
3525         PasswordDialogFields *fields = NULL;
3526         
3527         /* Initalize output parameters: */
3528         if (cancel)
3529                 *cancel = FALSE;
3530                 
3531         if (remember)
3532                 *remember = TRUE;
3533                 
3534 #ifdef MODEST_PLATFORM_MAEMO
3535         /* Maemo uses a different (awkward) button order,
3536          * It should probably just use gtk_alternative_dialog_button_order ().
3537          */
3538         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3539                                               NULL,
3540                                               GTK_DIALOG_MODAL,
3541                                               _("mcen_bd_dialog_ok"),
3542                                               GTK_RESPONSE_ACCEPT,
3543                                               _("mcen_bd_dialog_cancel"),
3544                                               GTK_RESPONSE_REJECT,
3545                                               NULL);
3546 #else
3547         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3548                                               NULL,
3549                                               GTK_DIALOG_MODAL,
3550                                               GTK_STOCK_CANCEL,
3551                                               GTK_RESPONSE_REJECT,
3552                                               GTK_STOCK_OK,
3553                                               GTK_RESPONSE_ACCEPT,
3554                                               NULL);
3555 #endif /* MODEST_PLATFORM_MAEMO */
3556
3557         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog));
3558         
3559         gchar *server_name = modest_account_mgr_get_server_account_hostname (
3560                 modest_runtime_get_account_mgr(), server_account_name);
3561         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3562                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3563                 if (cancel)
3564                         *cancel = TRUE;
3565                 return;
3566         }
3567         
3568         /* This causes a warning because the logical ID has no %s in it, 
3569          * though the translation does, but there is not much we can do about that: */
3570         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
3571         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
3572                             FALSE, FALSE, 0);
3573         g_free (txt);
3574         g_free (server_name);
3575         server_name = NULL;
3576
3577         /* username: */
3578         gchar *initial_username = modest_account_mgr_get_server_account_username (
3579                 modest_runtime_get_account_mgr(), server_account_name);
3580         
3581         GtkWidget *entry_username = gtk_entry_new ();
3582         if (initial_username)
3583                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
3584         /* Dim this if a connection has ever succeeded with this username,
3585          * as per the UI spec: */
3586         /* const gboolean username_known =  */
3587         /*      modest_account_mgr_get_server_account_username_has_succeeded( */
3588         /*              modest_runtime_get_account_mgr(), server_account_name); */
3589         /* gtk_widget_set_sensitive (entry_username, !username_known); */
3590
3591         /* We drop the username sensitive code and disallow changing it here
3592          * as tinymail does not support really changing the username in the callback
3593          */
3594         gtk_widget_set_sensitive (entry_username, FALSE);
3595
3596 #ifdef MODEST_PLATFORM_MAEMO
3597         /* Auto-capitalization is the default, so let's turn it off: */
3598         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
3599         
3600         /* Create a size group to be used by all captions.
3601          * Note that HildonCaption does not create a default size group if we do not specify one.
3602          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
3603         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3604         
3605         GtkWidget *caption = hildon_caption_new (sizegroup, 
3606                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
3607         gtk_widget_show (entry_username);
3608         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3609                 FALSE, FALSE, MODEST_MARGIN_HALF);
3610         gtk_widget_show (caption);
3611 #else 
3612         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
3613                             TRUE, FALSE, 0);
3614 #endif /* MODEST_PLATFORM_MAEMO */      
3615                             
3616         /* password: */
3617         GtkWidget *entry_password = gtk_entry_new ();
3618         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
3619         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
3620         
3621 #ifdef MODEST_PLATFORM_MAEMO
3622         /* Auto-capitalization is the default, so let's turn it off: */
3623         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
3624                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
3625         
3626         caption = hildon_caption_new (sizegroup, 
3627                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
3628         gtk_widget_show (entry_password);
3629         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3630                 FALSE, FALSE, MODEST_MARGIN_HALF);
3631         gtk_widget_show (caption);
3632         g_object_unref (sizegroup);
3633 #else 
3634         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
3635                             TRUE, FALSE, 0);
3636 #endif /* MODEST_PLATFORM_MAEMO */      
3637
3638         if (initial_username != NULL)
3639                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
3640                                 
3641 /* This is not in the Maemo UI spec:
3642         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
3643         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
3644                             TRUE, FALSE, 0);
3645 */
3646
3647         fields = g_slice_new0 (PasswordDialogFields);
3648         fields->username = entry_username;
3649         fields->password = entry_password;
3650         fields->dialog = dialog;
3651
3652         g_signal_connect (entry_username, "changed", G_CALLBACK (password_dialog_check_field), fields);
3653         g_signal_connect (entry_password, "changed", G_CALLBACK (password_dialog_check_field), fields);
3654         password_dialog_check_field (NULL, fields);
3655
3656         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3657
3658         while (!completed) {
3659         
3660                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
3661                         if (username) {
3662                                 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
3663                                 
3664                                 /* Note that an empty field becomes the "" string */
3665                                 if (*username && strlen (*username) > 0) {
3666                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(), 
3667                                                                                         server_account_name, 
3668                                                                                         *username);
3669                                         completed = TRUE;
3670                                 
3671                                         const gboolean username_was_changed = 
3672                                                 (strcmp (*username, initial_username) != 0);
3673                                         if (username_was_changed) {
3674                                                 g_warning ("%s: tinymail does not yet support changing the "
3675                                                            "username in the get_password() callback.\n", __FUNCTION__);
3676                                         }
3677                                 } else {
3678                                         /* Show error */
3679                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL, 
3680                                                                             _("mcen_ib_username_pw_incorrect"));
3681                                         completed = FALSE;
3682                                 }
3683                         }
3684                         
3685                         if (password) {
3686                                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
3687                         
3688                                 /* We do not save the password in the configuration, 
3689                                  * because this function is only called for passwords that should 
3690                                  * not be remembered:
3691                                  modest_server_account_set_password (
3692                                  modest_runtime_get_account_mgr(), server_account_name, 
3693                                  *password);
3694                                  */
3695                         }                       
3696                         if (cancel)
3697                                 *cancel   = FALSE;                      
3698                 } else {
3699                         /* Set parent to NULL or the banner will disappear with its parent dialog */
3700                         modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
3701                         completed = TRUE;
3702                         if (username)
3703                                 *username = NULL;                       
3704                         if (password)
3705                                 *password = NULL;                       
3706                         if (cancel)
3707                                 *cancel   = TRUE;
3708                 }
3709         }
3710
3711 /* This is not in the Maemo UI spec:
3712         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
3713                 *remember = TRUE;
3714         else
3715                 *remember = FALSE;
3716 */
3717
3718         gtk_widget_destroy (dialog);
3719         g_slice_free (PasswordDialogFields, fields);
3720         
3721         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
3722 }
3723
3724 void
3725 modest_ui_actions_on_cut (GtkAction *action,
3726                           ModestWindow *window)
3727 {
3728         GtkWidget *focused_widget;
3729         GtkClipboard *clipboard;
3730
3731         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3732         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3733         if (GTK_IS_EDITABLE (focused_widget)) {
3734                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3735                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3736                 gtk_clipboard_store (clipboard);
3737         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3738                 GtkTextBuffer *buffer;
3739
3740                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3741                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3742                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3743                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3744                         gtk_clipboard_store (clipboard);
3745                 }
3746         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3747                 TnyList *header_list = modest_header_view_get_selected_headers (
3748                                 MODEST_HEADER_VIEW (focused_widget));
3749                 gboolean continue_download = FALSE;
3750                 gint num_of_unc_msgs;
3751
3752                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3753
3754                 if (num_of_unc_msgs) {
3755                         TnyAccount *account = get_account_from_header_list (header_list);
3756                         if (account) {
3757                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3758                                 g_object_unref (account);
3759                         }
3760                 }
3761
3762                 if (num_of_unc_msgs == 0 || continue_download) {
3763 /*                      modest_platform_information_banner (
3764                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
3765                         modest_header_view_cut_selection (
3766                                         MODEST_HEADER_VIEW (focused_widget));
3767                 }
3768
3769                 g_object_unref (header_list);
3770         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3771                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3772         }
3773 }
3774
3775 void
3776 modest_ui_actions_on_copy (GtkAction *action,
3777                            ModestWindow *window)
3778 {
3779         GtkClipboard *clipboard;
3780         GtkWidget *focused_widget;
3781         gboolean copied = TRUE;
3782
3783         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3784         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3785
3786         if (GTK_IS_LABEL (focused_widget)) {
3787                 gchar *selection;
3788                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
3789                 gtk_clipboard_set_text (clipboard, selection, -1);
3790                 g_free (selection);
3791                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3792                 gtk_clipboard_store (clipboard);
3793         } else if (GTK_IS_EDITABLE (focused_widget)) {
3794                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3795                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3796                 gtk_clipboard_store (clipboard);
3797         } else if (GTK_IS_HTML (focused_widget)) {
3798                 gtk_html_copy (GTK_HTML (focused_widget));
3799                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3800                 gtk_clipboard_store (clipboard);
3801         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3802                 GtkTextBuffer *buffer;
3803                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3804                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3805                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
3806                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3807                         gtk_clipboard_store (clipboard);
3808                 }
3809         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3810                 TnyList *header_list = modest_header_view_get_selected_headers (
3811                                 MODEST_HEADER_VIEW (focused_widget));
3812                 gboolean continue_download = FALSE;
3813                 gint num_of_unc_msgs;
3814
3815                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3816
3817                 if (num_of_unc_msgs) {
3818                         TnyAccount *account = get_account_from_header_list (header_list);
3819                         if (account) {
3820                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3821                                 g_object_unref (account);
3822                         }
3823                 }
3824
3825                 if (num_of_unc_msgs == 0 || continue_download) {
3826                         modest_platform_information_banner (
3827                                         NULL, NULL, _CS("mcen_ib_getting_items"));
3828                         modest_header_view_copy_selection (
3829                                         MODEST_HEADER_VIEW (focused_widget));
3830                 } else
3831                         copied = FALSE;
3832
3833                 g_object_unref (header_list);
3834
3835         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3836                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3837         }
3838
3839         /* Show information banner if there was a copy to clipboard */
3840         if(copied)
3841                 modest_platform_information_banner (
3842                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3843 }
3844
3845 void
3846 modest_ui_actions_on_undo (GtkAction *action,
3847                            ModestWindow *window)
3848 {
3849         ModestEmailClipboard *clipboard = NULL;
3850
3851         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3852                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3853         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3854                 /* Clear clipboard source */
3855                 clipboard = modest_runtime_get_email_clipboard ();
3856                 modest_email_clipboard_clear (clipboard);               
3857         }
3858         else {
3859                 g_return_if_reached ();
3860         }
3861 }
3862
3863 void
3864 modest_ui_actions_on_redo (GtkAction *action,
3865                            ModestWindow *window)
3866 {
3867         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3868                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3869         }
3870         else {
3871                 g_return_if_reached ();
3872         }
3873 }
3874
3875
3876 static void
3877 destroy_information_note (ModestMailOperation *mail_op, 
3878                           gpointer user_data)
3879 {
3880         /* destroy information note */
3881         gtk_widget_destroy (GTK_WIDGET(user_data));
3882 }
3883
3884 static void
3885 destroy_folder_information_note (ModestMailOperation *mail_op, 
3886                                  TnyFolder *new_folder,
3887                                  gpointer user_data)
3888 {
3889         /* destroy information note */
3890         gtk_widget_destroy (GTK_WIDGET(user_data));
3891 }
3892
3893
3894 static void
3895 paste_as_attachment_free (gpointer data)
3896 {
3897         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3898
3899         gtk_widget_destroy (helper->banner);
3900         g_object_unref (helper->banner);
3901         g_free (helper);
3902 }
3903
3904 static void
3905 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3906                             TnyHeader *header,
3907                             TnyMsg *msg,
3908                             gpointer userdata)
3909 {
3910         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3911         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3912
3913         if (msg == NULL)
3914                 return;
3915
3916         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3917         
3918 }
3919
3920 void
3921 modest_ui_actions_on_paste (GtkAction *action,
3922                             ModestWindow *window)
3923 {
3924         GtkWidget *focused_widget = NULL;
3925         GtkWidget *inf_note = NULL;
3926         ModestMailOperation *mail_op = NULL;
3927
3928         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3929         if (GTK_IS_EDITABLE (focused_widget)) {
3930                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3931         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3932                 ModestEmailClipboard *e_clipboard = NULL;
3933                 e_clipboard = modest_runtime_get_email_clipboard ();
3934                 if (modest_email_clipboard_cleared (e_clipboard)) {
3935                         GtkTextBuffer *buffer;
3936                         GtkClipboard *clipboard;
3937
3938                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3939                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3940                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3941                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3942                         ModestMailOperation *mail_op;
3943                         TnyFolder *src_folder;
3944                         TnyList *data;
3945                         gboolean delete;
3946                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3947                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3948                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3949                                                                            _CS("ckct_nw_pasting"));
3950                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3951                         mail_op = modest_mail_operation_new (G_OBJECT (window));
3952                         if (helper->banner != NULL) {
3953                                 g_object_ref (G_OBJECT (helper->banner));
3954                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3955                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3956                         }
3957
3958                         if (data != NULL) {
3959                                 modest_mail_operation_get_msgs_full (mail_op, 
3960                                                                      data,
3961                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3962                                                                      helper,
3963                                                                      paste_as_attachment_free);
3964                         }
3965                 }
3966         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3967                 ModestEmailClipboard *clipboard = NULL;
3968                 TnyFolder *src_folder = NULL;
3969                 TnyFolderStore *folder_store = NULL;
3970                 TnyList *data = NULL;           
3971                 gboolean delete = FALSE;
3972                 
3973                 /* Check clipboard source */
3974                 clipboard = modest_runtime_get_email_clipboard ();
3975                 if (modest_email_clipboard_cleared (clipboard)) 
3976                         return;
3977                 
3978                 /* Get elements to paste */
3979                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3980
3981                 /* Create a new mail operation */
3982                 mail_op = modest_mail_operation_new (G_OBJECT(window));
3983                 
3984                 /* Get destination folder */
3985                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3986
3987                 /* transfer messages  */
3988                 if (data != NULL) {
3989                         gint response = 0;
3990
3991                         /* Ask for user confirmation */
3992                         response = 
3993                                 modest_ui_actions_msgs_move_to_confirmation (window, 
3994                                                                              TNY_FOLDER (folder_store), 
3995                                                                              delete,
3996                                                                              data);
3997                         
3998                         if (response == GTK_RESPONSE_OK) {
3999                                 /* Launch notification */
4000                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
4001                                                                              _CS("ckct_nw_pasting"));
4002                                 if (inf_note != NULL)  {
4003                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4004                                         gtk_widget_show (GTK_WIDGET(inf_note));
4005                                 }
4006
4007                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4008                                 modest_mail_operation_xfer_msgs (mail_op, 
4009                                                                  data,
4010                                                                  TNY_FOLDER (folder_store),
4011                                                                  delete,
4012                                                                  destroy_information_note,
4013                                                                  inf_note);                             
4014                         } else {
4015                                 g_object_unref (mail_op);
4016                         }
4017                         
4018                 } else if (src_folder != NULL) {                        
4019                         /* Launch notification */
4020                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
4021                                                                      _CS("ckct_nw_pasting"));
4022                         if (inf_note != NULL)  {
4023                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4024                                 gtk_widget_show (GTK_WIDGET(inf_note));
4025                         }
4026                         
4027                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4028                         modest_mail_operation_xfer_folder (mail_op, 
4029                                                            src_folder,
4030                                                            folder_store,
4031                                                            delete,
4032                                                            destroy_folder_information_note,
4033                                                            inf_note);
4034                 }
4035
4036                 /* Free */
4037                 if (data != NULL) 
4038                         g_object_unref (data);
4039                 if (src_folder != NULL) 
4040                         g_object_unref (src_folder);
4041                 if (folder_store != NULL) 
4042                         g_object_unref (folder_store);
4043         }
4044 }
4045
4046
4047 void
4048 modest_ui_actions_on_select_all (GtkAction *action,
4049                                  ModestWindow *window)
4050 {
4051         GtkWidget *focused_widget;
4052
4053         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4054         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
4055                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
4056         } else if (GTK_IS_LABEL (focused_widget)) {
4057                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
4058         } else if (GTK_IS_EDITABLE (focused_widget)) {
4059                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
4060         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4061                 GtkTextBuffer *buffer;
4062                 GtkTextIter start, end;
4063
4064                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4065                 gtk_text_buffer_get_start_iter (buffer, &start);
4066                 gtk_text_buffer_get_end_iter (buffer, &end);
4067                 gtk_text_buffer_select_range (buffer, &start, &end);
4068         } else if (GTK_IS_HTML (focused_widget)) {
4069                 gtk_html_select_all (GTK_HTML (focused_widget));
4070         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4071                 GtkWidget *header_view = focused_widget;
4072                 GtkTreeSelection *selection = NULL;
4073                 
4074                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
4075                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4076                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4077                 }
4078                                 
4079                 /* Disable window dimming management */
4080                 modest_window_disable_dimming (MODEST_WINDOW(window));
4081                 
4082                 /* Select all messages */
4083                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
4084                 gtk_tree_selection_select_all (selection);
4085
4086                 /* Set focuse on header view */
4087                 gtk_widget_grab_focus (header_view);
4088
4089
4090                 /* Enable window dimming management */
4091                 modest_window_enable_dimming (MODEST_WINDOW(window));
4092                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
4093         }
4094
4095 }
4096
4097 void
4098 modest_ui_actions_on_mark_as_read (GtkAction *action,
4099                                    ModestWindow *window)
4100 {       
4101         g_return_if_fail (MODEST_IS_WINDOW(window));
4102                 
4103         /* Mark each header as read */
4104         do_headers_action (window, headers_action_mark_as_read, NULL);
4105 }
4106
4107 void
4108 modest_ui_actions_on_mark_as_unread (GtkAction *action,
4109                                      ModestWindow *window)
4110 {       
4111         g_return_if_fail (MODEST_IS_WINDOW(window));
4112                 
4113         /* Mark each header as read */
4114         do_headers_action (window, headers_action_mark_as_unread, NULL);
4115 }
4116
4117 void
4118 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
4119                                   GtkRadioAction *selected,
4120                                   ModestWindow *window)
4121 {
4122         gint value;
4123
4124         value = gtk_radio_action_get_current_value (selected);
4125         if (MODEST_IS_WINDOW (window)) {
4126                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
4127         }
4128 }
4129
4130 void
4131 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
4132                                                GtkRadioAction *selected,
4133                                                ModestWindow *window)
4134 {
4135         TnyHeaderFlags flags;
4136         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4137
4138         flags = gtk_radio_action_get_current_value (selected);
4139         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
4140 }
4141
4142 void
4143 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
4144                                                   GtkRadioAction *selected,
4145                                                   ModestWindow *window)
4146 {
4147         gint file_format;
4148
4149         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4150
4151         file_format = gtk_radio_action_get_current_value (selected);
4152         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
4153 }
4154
4155
4156 void
4157 modest_ui_actions_on_zoom_plus (GtkAction *action,
4158                                 ModestWindow *window)
4159 {
4160         g_return_if_fail (MODEST_IS_WINDOW (window));
4161
4162         modest_window_zoom_plus (MODEST_WINDOW (window));
4163 }
4164
4165 void     
4166 modest_ui_actions_on_zoom_minus (GtkAction *action,
4167                                  ModestWindow *window)
4168 {
4169         g_return_if_fail (MODEST_IS_WINDOW (window));
4170
4171         modest_window_zoom_minus (MODEST_WINDOW (window));
4172 }
4173
4174 void     
4175 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
4176                                            ModestWindow *window)
4177 {
4178         ModestWindowMgr *mgr;
4179         gboolean fullscreen, active;
4180         g_return_if_fail (MODEST_IS_WINDOW (window));
4181
4182         mgr = modest_runtime_get_window_mgr ();
4183
4184         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4185         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4186
4187         if (active != fullscreen) {
4188                 modest_window_mgr_set_fullscreen_mode (mgr, active);
4189                 gtk_window_present (GTK_WINDOW (window));
4190         }
4191 }
4192
4193 void
4194 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4195                                         ModestWindow *window)
4196 {
4197         ModestWindowMgr *mgr;
4198         gboolean fullscreen;
4199
4200         g_return_if_fail (MODEST_IS_WINDOW (window));
4201
4202         mgr = modest_runtime_get_window_mgr ();
4203         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4204         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4205
4206         gtk_window_present (GTK_WINDOW (window));
4207 }
4208
4209 /* 
4210  * Used by modest_ui_actions_on_details to call do_headers_action 
4211  */
4212 static void
4213 headers_action_show_details (TnyHeader *header, 
4214                              ModestWindow *window,
4215                              gpointer user_data)
4216
4217 {
4218         GtkWidget *dialog;
4219         
4220         /* Create dialog */
4221         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
4222
4223         /* Run dialog */
4224         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog));
4225         gtk_widget_show_all (dialog);
4226         gtk_dialog_run (GTK_DIALOG (dialog));
4227
4228         gtk_widget_destroy (dialog);
4229 }
4230
4231 /*
4232  * Show the folder details in a ModestDetailsDialog widget
4233  */
4234 static void
4235 show_folder_details (TnyFolder *folder, 
4236                      GtkWindow *window)
4237 {
4238         GtkWidget *dialog;
4239         
4240         /* Create dialog */
4241         dialog = modest_details_dialog_new_with_folder (window, folder);
4242
4243         /* Run dialog */
4244         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
4245         gtk_widget_show_all (dialog);
4246         gtk_dialog_run (GTK_DIALOG (dialog));
4247
4248         gtk_widget_destroy (dialog);
4249 }
4250
4251 /*
4252  * Show the header details in a ModestDetailsDialog widget
4253  */
4254 void     
4255 modest_ui_actions_on_details (GtkAction *action, 
4256                               ModestWindow *win)
4257 {
4258         TnyList * headers_list;
4259         TnyIterator *iter;
4260         TnyHeader *header;              
4261
4262         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4263                 TnyMsg *msg;
4264
4265                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4266                 if (!msg)
4267                         return;
4268                 g_object_unref (msg);           
4269
4270                 headers_list = get_selected_headers (win);
4271                 if (!headers_list)
4272                         return;
4273
4274                 iter = tny_list_create_iterator (headers_list);
4275
4276                 header = TNY_HEADER (tny_iterator_get_current (iter));
4277                 if (header) {
4278                         headers_action_show_details (header, win, NULL);
4279                         g_object_unref (header);
4280                 }
4281
4282                 g_object_unref (iter);
4283                 g_object_unref (headers_list);
4284
4285         } else if (MODEST_IS_MAIN_WINDOW (win)) {
4286                 GtkWidget *folder_view, *header_view;
4287
4288                 /* Check which widget has the focus */
4289                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4290                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4291                 if (gtk_widget_is_focus (folder_view)) {
4292                         TnyFolderStore *folder_store
4293                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4294                         if (!folder_store) {
4295                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4296                                 return; 
4297                         }
4298                         /* Show only when it's a folder */
4299                         /* This function should not be called for account items, 
4300                          * because we dim the menu item for them. */
4301                         if (TNY_IS_FOLDER (folder_store)) {
4302                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
4303                         }
4304
4305                         g_object_unref (folder_store);
4306
4307                 } else {
4308                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4309                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4310                         /* Show details of each header */
4311                         do_headers_action (win, headers_action_show_details, header_view);
4312                 }
4313         }
4314 }
4315
4316 void     
4317 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4318                                      ModestMsgEditWindow *window)
4319 {
4320         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4321
4322         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4323 }
4324
4325 void     
4326 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4327                                       ModestMsgEditWindow *window)
4328 {
4329         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4330
4331         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4332 }
4333
4334 void
4335 modest_ui_actions_toggle_folders_view (GtkAction *action, 
4336                                        ModestMainWindow *main_window)
4337 {
4338         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4339
4340         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4341                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4342         else
4343                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4344 }
4345
4346 void 
4347 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
4348                                      ModestWindow *window)
4349 {
4350         gboolean active, fullscreen = FALSE;
4351         ModestWindowMgr *mgr;
4352
4353         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4354
4355         /* Check if we want to toggle the toolbar vuew in fullscreen
4356            or normal mode */
4357         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
4358                      "ViewShowToolbarFullScreen")) {
4359                 fullscreen = TRUE;
4360         }
4361
4362         /* Toggle toolbar */
4363         mgr = modest_runtime_get_window_mgr ();
4364         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4365 }
4366
4367 void     
4368 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4369                                            ModestMsgEditWindow *window)
4370 {
4371         modest_msg_edit_window_select_font (window);
4372 }
4373
4374
4375 void
4376 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4377                                                   const gchar *display_name,
4378                                                   GtkWindow *window)
4379 {
4380         /* don't update the display name if it was already set;
4381          * updating the display name apparently is expensive */
4382         const gchar* old_name = gtk_window_get_title (window);
4383
4384         if (display_name == NULL)
4385                 display_name = " ";
4386
4387         if (old_name && display_name && strcmp (old_name, display_name) == 0)
4388                 return; /* don't do anything */
4389
4390         /* This is usually used to change the title of the main window, which
4391          * is the one that holds the folder view. Note that this change can
4392          * happen even when the widget doesn't have the focus. */
4393         gtk_window_set_title (window, display_name);
4394
4395 }
4396
4397 void
4398 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4399 {
4400         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4401         modest_msg_edit_window_select_contacts (window);
4402 }
4403
4404 void
4405 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4406 {
4407         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4408         modest_msg_edit_window_check_names (window, FALSE);
4409 }
4410
4411 static void
4412 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
4413 {
4414         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
4415                                          GTK_WIDGET (user_data));
4416 }
4417
4418 /*
4419  * This function is used to track changes in the selection of the
4420  * folder view that is inside the "move to" dialog to enable/disable
4421  * the OK button because we do not want the user to select a disallowed
4422  * destination for a folder.
4423  * The user also not desired to be able to use NEW button on items where
4424  * folder creation is not possibel.
4425  */
4426 static void
4427 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4428                                             TnyFolderStore *folder_store,
4429                                             gboolean selected,
4430                                             gpointer user_data)
4431 {
4432         GtkWidget *dialog = NULL;
4433         GtkWidget *ok_button = NULL, *new_button = NULL;
4434         GList *children = NULL;
4435         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4436         gboolean moving_folder = FALSE;
4437         gboolean is_local_account = TRUE;
4438         GtkWidget *folder_view = NULL;
4439         ModestTnyFolderRules rules;
4440
4441         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4442         
4443         if (!selected)
4444                 return;
4445         
4446         /* Get the OK button */
4447         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4448         if (!dialog)
4449                 return;
4450
4451         children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
4452         ok_button = GTK_WIDGET (children->next->next->data);
4453         new_button = GTK_WIDGET (children->next->data);
4454         g_list_free (children);
4455
4456         /* check if folder_store is an remote account */
4457         if (TNY_IS_ACCOUNT (folder_store)) {
4458                 TnyAccount *local_account = NULL;
4459                 TnyAccount *mmc_account = NULL;
4460                 ModestTnyAccountStore *account_store = NULL;
4461
4462                 account_store = modest_runtime_get_account_store ();
4463                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4464                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4465
4466                 if ((gpointer) local_account != (gpointer) folder_store &&
4467                     (gpointer) mmc_account != (gpointer) folder_store) {
4468                         const char *proto_name = tny_account_get_proto (TNY_ACCOUNT (folder_store));
4469                         ModestTransportStoreProtocol proto = MODEST_PROTOCOL_STORE_MAILDIR;
4470                         if (proto_name != NULL) {
4471                                 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
4472                         }
4473                         is_local_account = FALSE;
4474                         /* New button should be dimmed on remote
4475                            POP account root */
4476                         new_sensitive = (proto != MODEST_PROTOCOL_STORE_POP);
4477                 }
4478                 g_object_unref (local_account);
4479                 g_object_unref (mmc_account);
4480         }
4481
4482         /* Check the target folder rules */
4483         if (TNY_IS_FOLDER (folder_store)) {
4484                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
4485                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
4486                         ok_sensitive = FALSE;
4487                         new_sensitive = FALSE;
4488                         goto end;
4489                 }
4490         }
4491
4492         /* Check if we're moving a folder */
4493         if (MODEST_IS_MAIN_WINDOW (user_data)) {
4494                 /* Get the widgets */
4495                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
4496                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4497                 if (gtk_widget_is_focus (folder_view))
4498                         moving_folder = TRUE;
4499         }
4500
4501         if (moving_folder) {
4502                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
4503
4504                 /* Get the folder to move */
4505                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4506                 
4507                 /* Check that we're not moving to the same folder */
4508                 if (TNY_IS_FOLDER (moved_folder)) {
4509                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
4510                         if (parent == folder_store)
4511                                 ok_sensitive = FALSE;
4512                         g_object_unref (parent);
4513                 } 
4514
4515                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
4516                         /* Do not allow to move to an account unless it's the
4517                            local folders account */
4518                         if (!is_local_account)
4519                                 ok_sensitive = FALSE;
4520                 } 
4521
4522                 if (ok_sensitive && (moved_folder == folder_store)) {
4523                         /* Do not allow to move to itself */
4524                         ok_sensitive = FALSE;
4525                 }
4526                 g_object_unref (moved_folder);
4527         } else {
4528                 TnyFolder *src_folder = NULL;
4529
4530                 /* Moving a message */
4531                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
4532
4533                         TnyHeader *header = NULL;
4534                         header = modest_msg_view_window_get_header
4535                                 (MODEST_MSG_VIEW_WINDOW (user_data));
4536                         if (!TNY_IS_HEADER(header))
4537                                 g_warning ("%s: could not get source header", __FUNCTION__);
4538                         else
4539                                 src_folder = tny_header_get_folder (header);
4540
4541                         if (header)
4542                                 g_object_unref (header);
4543                 } else {
4544                         src_folder = 
4545                                 TNY_FOLDER (modest_folder_view_get_selected
4546                                             (MODEST_FOLDER_VIEW (folder_view)));
4547                 }
4548
4549                 if (TNY_IS_FOLDER(src_folder)) {
4550                         /* Do not allow to move the msg to the same folder */
4551                         /* Do not allow to move the msg to an account */
4552                         if ((gpointer) src_folder == (gpointer) folder_store ||
4553                             TNY_IS_ACCOUNT (folder_store))
4554                                 ok_sensitive = FALSE;
4555                         g_object_unref (src_folder);
4556                 } else
4557                         g_warning ("%s: could not get source folder", __FUNCTION__);
4558         }
4559
4560  end:
4561         /* Set sensitivity of the OK button */
4562         gtk_widget_set_sensitive (ok_button, ok_sensitive);
4563         /* Set sensitivity of the NEW button */
4564         gtk_widget_set_sensitive (new_button, new_sensitive);
4565 }
4566
4567
4568 #define MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
4569
4570 static GtkWidget*
4571 get_folder_view_from_move_to_dialog (GtkWidget *move_to_dialog)
4572 {
4573         return GTK_WIDGET(g_object_get_data (G_OBJECT(move_to_dialog),
4574                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4575 }
4576
4577 static GtkWidget*
4578 create_move_to_dialog (GtkWindow *win,
4579                        GtkWidget *folder_view,
4580                        GtkWidget **tree_view)
4581 {
4582         GtkWidget *dialog, *scroll;
4583         GtkWidget *new_button;
4584
4585         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
4586                                               GTK_WINDOW (win),
4587                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
4588                                               NULL);
4589
4590         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
4591         /* We do this manually so GTK+ does not associate a response ID for
4592          * the button. */
4593         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
4594         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
4595         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
4596
4597         /* Create scrolled window */
4598         scroll = gtk_scrolled_window_new (NULL, NULL);
4599         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
4600                                          GTK_POLICY_AUTOMATIC,
4601                                          GTK_POLICY_AUTOMATIC);
4602
4603         /* Create folder view */
4604         *tree_view = modest_platform_create_folder_view (NULL);
4605
4606         /* Track changes in the selection to
4607          * disable the OK button whenever "Move to" is not possible
4608          * disbale NEW button whenever New is not possible */
4609         g_signal_connect (*tree_view,
4610                           "folder_selection_changed",
4611                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
4612                           win);
4613
4614         /* Listen to clicks on New button */
4615         g_signal_connect (G_OBJECT (new_button), 
4616                           "clicked", 
4617                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
4618                           *tree_view);
4619
4620         /* It could happen that we're trying to move a message from a
4621            window (msg window for example) after the main window was
4622            closed, so we can not just get the model of the folder
4623            view */
4624         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
4625                 const gchar *visible_id = NULL;
4626
4627                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4628                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4629                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
4630                                                MODEST_FOLDER_VIEW(*tree_view));
4631
4632                 visible_id = 
4633                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
4634
4635                 /* Show the same account than the one that is shown in the main window */
4636                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
4637                                                                              visible_id);
4638         } else {
4639                 const gchar *active_account_name = NULL;
4640                 ModestAccountMgr *mgr = NULL;
4641                 ModestAccountSettings *settings = NULL;
4642                 ModestServerAccountSettings *store_settings = NULL;
4643
4644                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4645                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4646                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
4647                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
4648
4649                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
4650                 mgr = modest_runtime_get_account_mgr ();
4651                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
4652
4653                 if (settings) {
4654                         const gchar *store_account_name;
4655                         store_settings = modest_account_settings_get_store_settings (settings);
4656                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
4657
4658                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
4659                                                                                      store_account_name);
4660                         g_object_unref (store_settings);
4661                         g_object_unref (settings);
4662                 }
4663         }
4664
4665         /* we keep a pointer to the embedded folder view, so we can retrieve it with
4666          *   get_folder_view_from_move_to_dialog 
4667          * (see above) later (needed for focus handling) 
4668          */
4669         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, *tree_view);
4670
4671         
4672         /* Hide special folders */
4673         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
4674
4675         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
4676
4677         /* Add scroll to dialog */
4678         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
4679                             scroll, TRUE, TRUE, 0);
4680
4681         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4682         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
4683
4684         return dialog;
4685 }
4686
4687
4688
4689 /*
4690  * Shows a confirmation dialog to the user when we're moving messages
4691  * from a remote server to the local storage. Returns the dialog
4692  * response. If it's other kind of movement then it always returns
4693  * GTK_RESPONSE_OK
4694  *
4695  * This one is used by the next functions:
4696  *      modest_ui_actions_on_paste                      - commented out
4697  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4698  */
4699 gint
4700 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4701                                              TnyFolder *dest_folder,
4702                                              gboolean delete,
4703                                              TnyList *headers)
4704 {
4705         gint response = GTK_RESPONSE_OK;
4706         TnyAccount *account = NULL;
4707         TnyFolder *src_folder = NULL;
4708         TnyIterator *iter = NULL;
4709         TnyHeader *header = NULL;
4710
4711         /* return with OK if the destination is a remote folder */
4712         if (modest_tny_folder_is_remote_folder (dest_folder))
4713                 return GTK_RESPONSE_OK;
4714
4715         /* Get source folder */
4716         iter = tny_list_create_iterator (headers);
4717         header = TNY_HEADER (tny_iterator_get_current (iter));
4718         if (header) {
4719                 src_folder = tny_header_get_folder (header);
4720                 g_object_unref (header);
4721         }
4722         g_object_unref (iter);
4723
4724         /* if no src_folder, message may be an attahcment */
4725         if (src_folder == NULL) 
4726                 return GTK_RESPONSE_CANCEL;
4727
4728         /* If the source is a local or MMC folder */
4729         if (!modest_tny_folder_is_remote_folder (src_folder)) {
4730                 g_object_unref (src_folder);
4731                 return GTK_RESPONSE_OK;
4732         }
4733
4734         /* Get the account */
4735         account = tny_folder_get_account (src_folder);
4736
4737         /* now if offline we ask the user */
4738         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4739                 response = GTK_RESPONSE_OK;
4740         else
4741                 response = GTK_RESPONSE_CANCEL;
4742
4743         /* Frees */
4744         g_object_unref (src_folder);
4745         g_object_unref (account);
4746
4747         return response;
4748 }
4749
4750 static void
4751 move_to_cb (ModestMailOperation *mail_op, 
4752             gpointer user_data)
4753 {
4754         MoveToHelper *helper = (MoveToHelper *) user_data;
4755
4756         /* Note that the operation could have failed, in that case do
4757            nothing */
4758         if (modest_mail_operation_get_status (mail_op) == 
4759             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4760
4761                 GObject *object = modest_mail_operation_get_source (mail_op);
4762                 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4763                         ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4764
4765                         if (!modest_msg_view_window_select_next_message (self) &&
4766                             !modest_msg_view_window_select_previous_message (self)) {
4767                                 /* No more messages to view, so close this window */
4768                                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4769                         }
4770                 } else if (MODEST_IS_MAIN_WINDOW (object) && helper->reference != NULL) {
4771                         GtkWidget *header_view;
4772                         GtkTreePath *path;
4773                         GtkTreeSelection *sel;
4774
4775                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4776                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4777                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4778                         path = gtk_tree_row_reference_get_path (helper->reference);
4779                         /* We need to unselect the previous one
4780                            because we could be copying instead of
4781                            moving */
4782                         gtk_tree_selection_unselect_all (sel);
4783                         gtk_tree_selection_select_path (sel, path);
4784                         gtk_tree_path_free (path);
4785                 }
4786                 g_object_unref (object);
4787         }
4788
4789         /* Close the "Pasting" information banner */
4790         gtk_widget_destroy (GTK_WIDGET(helper->banner));
4791         g_object_unref (helper->banner);
4792         if (helper->reference != NULL)
4793                 gtk_tree_row_reference_free (helper->reference);
4794         g_free (helper);
4795 }
4796
4797 static void
4798 folder_move_to_cb (ModestMailOperation *mail_op, 
4799                    TnyFolder *new_folder,
4800                    gpointer user_data)
4801 {
4802         GtkWidget *folder_view;
4803         GObject *object;
4804
4805         object = modest_mail_operation_get_source (mail_op);
4806         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4807                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4808         g_object_ref (folder_view);
4809         g_object_unref (object);
4810         move_to_cb (mail_op, user_data);
4811         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
4812         g_object_unref (folder_view);
4813 }
4814
4815 static void
4816 msgs_move_to_cb (ModestMailOperation *mail_op, 
4817                  gpointer user_data)
4818 {
4819         move_to_cb (mail_op, user_data);
4820 }
4821
4822 void
4823 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
4824                                              gpointer user_data)
4825 {
4826         ModestWindow *main_window = NULL;
4827         
4828         /* Disable next automatic folder selection */
4829         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4830                                                          FALSE); /* don't create */
4831         if (main_window) {
4832                 GObject *win = NULL;
4833                 GtkWidget *folder_view = NULL;
4834         
4835                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4836                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
4837                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4838                 
4839                 if (user_data && TNY_IS_FOLDER (user_data)) {
4840                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), 
4841                                                           TNY_FOLDER (user_data), FALSE);
4842                 }
4843
4844                 /* Show notification dialog only if the main window exists */
4845                 win = modest_mail_operation_get_source (mail_op);
4846                 modest_platform_run_information_dialog ((GtkWindow *) win, 
4847                                                         _("mail_in_ui_folder_move_target_error"), 
4848                                                         FALSE);
4849                 if (win)
4850                         g_object_unref (win);
4851         }
4852 }
4853
4854 static void
4855 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
4856                        TnyHeader *header, 
4857                        gboolean canceled,
4858                        TnyMsg *msg, 
4859                        GError *err,
4860                        gpointer user_data)
4861 {
4862         TnyList *parts;
4863         TnyIterator *iter;
4864         gint pending_purges = 0;
4865         gboolean some_purged = FALSE;
4866         ModestWindow *win = MODEST_WINDOW (user_data);
4867         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4868
4869         /* If there was any error */
4870         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4871                 modest_window_mgr_unregister_header (mgr, header);
4872                 return;
4873         }
4874
4875         /* Once the message has been retrieved for purging, we check if
4876          * it's all ok for purging */
4877
4878         parts = tny_simple_list_new ();
4879         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4880         iter = tny_list_create_iterator (parts);
4881
4882         while (!tny_iterator_is_done (iter)) {
4883                 TnyMimePart *part;
4884                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4885                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4886                         if (tny_mime_part_is_purged (part))
4887                                 some_purged = TRUE;
4888                         else
4889                                 pending_purges++;
4890                 }
4891
4892                 if (part)
4893                         g_object_unref (part);
4894
4895                 tny_iterator_next (iter);
4896         }
4897         g_object_unref (iter);
4898         
4899
4900         if (pending_purges>0) {
4901                 gint response;
4902                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4903
4904                 if (response == GTK_RESPONSE_OK) {
4905                         GtkWidget *info;
4906                         info =
4907                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_ib_removing_attachment"));
4908                         iter = tny_list_create_iterator (parts);
4909                         while (!tny_iterator_is_done (iter)) {
4910                                 TnyMimePart *part;
4911                                 
4912                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4913                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4914                                         tny_mime_part_set_purged (part);
4915
4916                                 if (part)
4917                                         g_object_unref (part);
4918
4919                                 tny_iterator_next (iter);
4920                         }
4921                         g_object_unref (iter);
4922                         
4923                         tny_msg_rewrite_cache (msg);
4924
4925                         gtk_widget_destroy (info);
4926                 }
4927         }
4928
4929         modest_window_mgr_unregister_header (mgr, header);
4930
4931         g_object_unref (parts);
4932 }
4933
4934 static void
4935 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4936                                                      ModestMainWindow *win)
4937 {
4938         GtkWidget *header_view;
4939         TnyList *header_list;
4940         TnyHeader *header;
4941         TnyHeaderFlags flags;
4942         ModestWindow *msg_view_window =  NULL;
4943         gboolean found;
4944
4945         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4946
4947         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4948                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4949
4950         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4951         if (!header_list) {
4952                 g_warning ("%s: no header selected", __FUNCTION__);
4953                 return;
4954         }
4955         
4956         if (tny_list_get_length (header_list) == 1) {
4957                 TnyIterator *iter = tny_list_create_iterator (header_list);
4958                 header = TNY_HEADER (tny_iterator_get_current (iter));
4959                 g_object_unref (iter);
4960         } else
4961                 return;
4962         
4963         if (!header || !TNY_IS_HEADER(header)) {
4964                 g_warning ("%s: header is not valid", __FUNCTION__);
4965                 return;
4966         }
4967         
4968         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4969                                                           header, &msg_view_window);
4970         flags = tny_header_get_flags (header);
4971         if (!(flags & TNY_HEADER_FLAG_CACHED))
4972                 return;
4973         if (found) {
4974                 if (msg_view_window != NULL) 
4975                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4976                 else {
4977                         /* do nothing; uid was registered before, so window is probably on it's way */
4978                         g_warning ("debug: header %p has already been registered", header);
4979                 }
4980         } else {
4981                 ModestMailOperation *mail_op = NULL;
4982                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
4983                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
4984                                                                          modest_ui_actions_disk_operations_error_handler,
4985                                                                          NULL, NULL);
4986                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4987                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
4988                 
4989                 g_object_unref (mail_op);
4990         }
4991         if (header)
4992                 g_object_unref (header);
4993         if (header_list)
4994                 g_object_unref (header_list);
4995 }
4996
4997 /*
4998  * Checks if we need a connection to do the transfer and if the user
4999  * wants to connect to complete it
5000  */
5001 void
5002 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5003                                        TnyFolderStore *src_folder,
5004                                        TnyList *headers,
5005                                        TnyFolder *dst_folder,
5006                                        gboolean delete_originals,
5007                                        gboolean *need_connection,
5008                                        gboolean *do_xfer)
5009 {
5010         TnyAccount *src_account;
5011         gint uncached_msgs = 0;
5012
5013         uncached_msgs = header_list_count_uncached_msgs (headers);
5014
5015         /* We don't need any further check if
5016          *
5017          * 1- the source folder is local OR
5018          * 2- the device is already online
5019          */
5020         if (!modest_tny_folder_store_is_remote (src_folder) ||
5021             tny_device_is_online (modest_runtime_get_device())) {
5022                 *need_connection = FALSE;
5023                 *do_xfer = TRUE;
5024                 return;
5025         }
5026
5027         /* We must ask for a connection when
5028          *
5029          *   - the message(s) is not already cached   OR 
5030          *   - the message(s) is cached but the leave_on_server setting
5031          * is FALSE (because we need to sync the source folder to
5032          * delete the message from the server (for IMAP we could do it
5033          * offline, it'll take place the next time we get a
5034          * connection)
5035          */
5036         src_account = get_account_from_folder_store (src_folder);
5037         if (uncached_msgs > 0) {
5038                 guint num_headers;
5039                 const gchar *msg;
5040
5041                 *need_connection = TRUE;
5042                 num_headers = tny_list_get_length (headers);
5043                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
5044
5045                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
5046                     GTK_RESPONSE_CANCEL) {
5047                         *do_xfer = FALSE;
5048                 } else {
5049                         *do_xfer = TRUE;
5050                 }
5051         } else {
5052                 /* The transfer is possible and the user wants to */
5053                 *do_xfer = TRUE;
5054
5055                 if (remote_folder_is_pop (src_folder) && delete_originals) {
5056                         const gchar *account_name;
5057                         gboolean leave_on_server;
5058                         
5059                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
5060                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
5061                                                                                   account_name);
5062                         
5063                         if (leave_on_server == TRUE) {
5064                                 *need_connection = FALSE;
5065                         } else {
5066                                 *need_connection = TRUE;
5067                         }
5068                 } else {
5069                         *need_connection = FALSE;
5070                 }
5071         }
5072
5073         /* Frees */
5074         g_object_unref (src_account);
5075 }
5076
5077 static void
5078 xfer_messages_error_handler (ModestMailOperation *mail_op, 
5079                              gpointer user_data)
5080 {
5081         ModestWindow *main_window = NULL;
5082         
5083         /* Disable next automatic folder selection */
5084         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5085                                                          FALSE); /* don't create */
5086         if (main_window) {
5087                 GObject *win = modest_mail_operation_get_source (mail_op);
5088                 modest_platform_run_information_dialog ((GtkWindow *) win, 
5089                                                         _("mail_in_ui_folder_move_target_error"), 
5090                                                         FALSE);
5091                 if (win)
5092                         g_object_unref (win);
5093         }
5094 }
5095
5096 typedef struct {
5097         TnyFolderStore *dst_folder;
5098         TnyList *headers;
5099 } XferMsgsHelper;
5100
5101 /**
5102  * Utility function that transfer messages from both the main window
5103  * and the msg view window when using the "Move to" dialog
5104  */
5105 static void
5106 xfer_messages_performer  (gboolean canceled, 
5107                           GError *err,
5108                           GtkWindow *parent_window, 
5109                           TnyAccount *account, 
5110                           gpointer user_data)
5111 {
5112         ModestWindow *win = MODEST_WINDOW (parent_window);
5113         TnyAccount *dst_account = NULL;
5114         const gchar *proto_str = NULL;
5115         gboolean dst_is_pop = FALSE;
5116         XferMsgsHelper *helper;
5117         MoveToHelper *movehelper;
5118         ModestMailOperation *mail_op;
5119
5120         helper = (XferMsgsHelper *) user_data;
5121
5122         if (canceled || err) {
5123                 if (!check_memory_full_error ((GtkWidget *) parent_window, err)) {
5124                         /* Show the proper error message */
5125                         modest_ui_actions_on_account_connection_error (parent_window, account);
5126                 }
5127                 goto end;
5128         }
5129
5130         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
5131         proto_str = tny_account_get_proto (dst_account);
5132
5133         /* tinymail will return NULL for local folders it seems */
5134         dst_is_pop = proto_str &&
5135                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
5136                  MODEST_PROTOCOL_STORE_POP);
5137
5138         g_object_unref (dst_account);
5139
5140         if (dst_is_pop) {
5141                 modest_platform_information_banner (GTK_WIDGET (win),
5142                                                     NULL,
5143                                                     ngettext("mail_in_ui_folder_move_target_error",
5144                                                              "mail_in_ui_folder_move_targets_error",
5145                                                              tny_list_get_length (helper->headers)));
5146                 goto end;
5147         }
5148
5149         movehelper = g_new0 (MoveToHelper, 1);
5150         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
5151                                                                _CS("ckct_nw_pasting"));
5152         if (movehelper->banner != NULL)  {
5153                 g_object_ref (movehelper->banner);
5154                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
5155         }
5156
5157         if (MODEST_IS_MAIN_WINDOW (win)) {
5158                 GtkWidget *header_view = 
5159                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5160                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5161                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5162         }
5163
5164         /* Perform the mail operation */
5165         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5166                                                                  xfer_messages_error_handler,
5167                                                                  movehelper, NULL);
5168         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
5169                                          mail_op);
5170
5171         modest_mail_operation_xfer_msgs (mail_op, 
5172                                          helper->headers,
5173                                          TNY_FOLDER (helper->dst_folder),
5174                                          TRUE,
5175                                          msgs_move_to_cb,
5176                                          movehelper);
5177
5178         g_object_unref (G_OBJECT (mail_op));
5179  end:
5180         g_object_unref (helper->dst_folder);
5181         g_object_unref (helper->headers);
5182         g_slice_free (XferMsgsHelper, helper);
5183 }
5184
5185 typedef struct {
5186         TnyFolder *src_folder;
5187         TnyFolderStore *dst_folder;
5188         gboolean delete_original;
5189         GtkWidget *folder_view;
5190 } MoveFolderInfo;
5191
5192 static void
5193 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window, 
5194                 TnyAccount *account, gpointer user_data)
5195 {
5196         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5197         GtkTreeSelection *sel;
5198         ModestMailOperation *mail_op = NULL;
5199         
5200         if (canceled || err || !MODEST_IS_MAIN_WINDOW (parent_window)) {
5201                 g_object_unref (G_OBJECT (info->src_folder));
5202                 g_object_unref (G_OBJECT (info->dst_folder));
5203                 g_free (info);
5204                 return;
5205         }
5206         
5207         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5208         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5209                         _CS("ckct_nw_pasting"));
5210         if (helper->banner != NULL)  {
5211                 g_object_ref (helper->banner);
5212                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
5213                 gtk_widget_show (GTK_WIDGET(helper->banner));
5214         }
5215         /* Clean folder on header view before moving it */
5216         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5217         gtk_tree_selection_unselect_all (sel);
5218
5219         /* Let gtk events run. We need that the folder
5220            view frees its reference to the source
5221            folder *before* issuing the mail operation
5222            so we need the signal handler of selection
5223            changed to happen before the mail
5224            operation 
5225         while (gtk_events_pending ())
5226                 gtk_main_iteration ();   */
5227
5228         mail_op =
5229                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5230                                 modest_ui_actions_move_folder_error_handler,
5231                                 info->src_folder, NULL);
5232         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5233                         mail_op);
5234
5235         /* Select *after* the changes */
5236         /* TODO: this function hangs UI after transfer */ 
5237         /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
5238         /*                                                        TNY_FOLDER (src_folder), TRUE); */
5239
5240         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5241                                           TNY_FOLDER (info->dst_folder), TRUE);
5242         modest_mail_operation_xfer_folder (mail_op,
5243                         TNY_FOLDER (info->src_folder),
5244                         info->dst_folder,
5245                         info->delete_original, 
5246                         folder_move_to_cb, 
5247                         helper);
5248         g_object_unref (G_OBJECT (info->src_folder));
5249
5250         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
5251         /* } */
5252         
5253         /* Unref mail operation */
5254         g_object_unref (G_OBJECT (mail_op));
5255         g_object_unref (G_OBJECT (info->dst_folder));
5256         g_free (user_data);
5257 }
5258
5259 static TnyAccount *
5260 get_account_from_folder_store (TnyFolderStore *folder_store) 
5261 {
5262         if (TNY_IS_ACCOUNT (folder_store))
5263                 return g_object_ref (folder_store);
5264         else
5265                 return tny_folder_get_account (TNY_FOLDER (folder_store));
5266 }
5267
5268 /*
5269  * UI handler for the "Move to" action when invoked from the
5270  * ModestMainWindow
5271  */
5272 static void 
5273 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
5274                                           GtkWidget *folder_view,
5275                                           TnyFolderStore *dst_folder,
5276                                           ModestMainWindow *win)
5277 {
5278         ModestHeaderView *header_view = NULL;
5279         TnyFolderStore *src_folder = NULL;
5280
5281         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5282
5283         /* Get the source folder */
5284         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5285
5286         /* Get header view */
5287         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
5288
5289         /* Get folder or messages to transfer */
5290         if (gtk_widget_is_focus (folder_view)) {
5291                 gboolean do_xfer = TRUE;
5292
5293                 /* Allow only to transfer folders to the local root folder */
5294                 if (TNY_IS_ACCOUNT (dst_folder) && 
5295                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5296                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5297                         do_xfer = FALSE;
5298                 } else if (!TNY_IS_FOLDER (src_folder)) {
5299                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5300                         do_xfer = FALSE;
5301                 }
5302
5303                 if (do_xfer) {                  
5304                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5305                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5306
5307                         info->src_folder = g_object_ref (src_folder);
5308                         info->dst_folder = g_object_ref (dst_folder);
5309                         info->delete_original = TRUE;
5310                         info->folder_view = folder_view;
5311
5312                         connect_info->callback = on_move_folder_cb;
5313                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5314                         connect_info->data = info;
5315
5316                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5317                                                                    TNY_FOLDER_STORE (src_folder), 
5318                                                                    connect_info);
5319                 }
5320         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5321                 TnyList *headers;
5322
5323                 headers = modest_header_view_get_selected_headers(header_view);
5324
5325                 /* Transfer the messages */
5326                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder), 
5327                                                             headers, TNY_FOLDER (dst_folder));
5328
5329                 g_object_unref (headers);
5330         }
5331
5332         /* Frees */
5333         g_object_unref (src_folder);
5334 }
5335
5336
5337 void
5338 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
5339                                             TnyFolder *src_folder,
5340                                             TnyList *headers,
5341                                             TnyFolder *dst_folder)
5342 {
5343         gboolean need_connection = TRUE;
5344         gboolean do_xfer = TRUE;
5345         XferMsgsHelper *helper;
5346
5347         g_return_if_fail (TNY_IS_FOLDER (src_folder));
5348         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5349         g_return_if_fail (TNY_IS_LIST (headers));
5350         
5351         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder), 
5352                                                headers, TNY_FOLDER (dst_folder),
5353                                                TRUE, &need_connection, 
5354                                                &do_xfer);
5355
5356         /* If we don't want to transfer just return */
5357         if (!do_xfer)
5358                 return;
5359
5360         /* Create the helper */
5361         helper = g_slice_new (XferMsgsHelper);
5362         helper->dst_folder = g_object_ref (dst_folder);
5363         helper->headers = g_object_ref (headers);
5364
5365         if (need_connection) {
5366                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5367                 connect_info->callback = xfer_messages_performer;
5368                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
5369                 connect_info->data = helper;
5370                 
5371                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5372                                                            TNY_FOLDER_STORE (src_folder), 
5373                                                            connect_info);
5374         } else {
5375                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
5376                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
5377                                          src_account, helper);
5378                 g_object_unref (src_account);
5379         }
5380 }
5381
5382 /*
5383  * UI handler for the "Move to" action when invoked from the
5384  * ModestMsgViewWindow
5385  */
5386 static void 
5387 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
5388                                               TnyFolderStore *dst_folder,
5389                                               ModestMsgViewWindow *win)
5390 {
5391         TnyList *headers = NULL;
5392         TnyHeader *header = NULL;
5393         TnyFolder *src_folder = NULL;
5394
5395         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5396
5397         /* Create header list */
5398         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5399         src_folder = TNY_FOLDER (tny_header_get_folder(header));
5400         headers = tny_simple_list_new ();
5401         tny_list_append (headers, G_OBJECT (header));
5402
5403         /* Transfer the messages */
5404         modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder, headers, 
5405                                                     TNY_FOLDER (dst_folder));
5406
5407         /* Frees */
5408         g_object_unref (src_folder);
5409         g_object_unref (header);
5410         g_object_unref (headers);
5411 }
5412
5413 void 
5414 modest_ui_actions_on_move_to (GtkAction *action, 
5415                               ModestWindow *win)
5416 {
5417         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
5418         gint result = 0;
5419         TnyFolderStore *dst_folder = NULL;
5420         ModestMainWindow *main_window;
5421
5422         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
5423                           MODEST_IS_MSG_VIEW_WINDOW (win));
5424
5425         /* Get the main window if exists */
5426         if (MODEST_IS_MAIN_WINDOW (win))
5427                 main_window = MODEST_MAIN_WINDOW (win);
5428         else
5429                 main_window = 
5430                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5431                                                                                FALSE)); /* don't create */
5432
5433         /* Get the folder view widget if exists */
5434         if (main_window)
5435                 folder_view = modest_main_window_get_child_widget (main_window,
5436                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5437         else
5438                 folder_view = NULL;
5439
5440         /* Create and run the dialog */
5441         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
5442         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5443         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5444         result = gtk_dialog_run (GTK_DIALOG(dialog));
5445         g_object_ref (tree_view);
5446         gtk_widget_destroy (dialog);
5447
5448         if (result != GTK_RESPONSE_ACCEPT)
5449                 return;
5450
5451         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
5452         /* Do window specific stuff */
5453         if (MODEST_IS_MAIN_WINDOW (win)) {
5454                 modest_ui_actions_on_main_window_move_to (action,
5455                                 folder_view,
5456                                 dst_folder,
5457                                 MODEST_MAIN_WINDOW (win));
5458         } else {
5459                 modest_ui_actions_on_msg_view_window_move_to (action,
5460                                 dst_folder,
5461                                 MODEST_MSG_VIEW_WINDOW (win));
5462         }
5463
5464         if (dst_folder)
5465                 g_object_unref (dst_folder);
5466 }
5467
5468 /*
5469  * Calls #HeadersFunc for each header already selected in the main
5470  * window or the message currently being shown in the msg view window
5471  */
5472 static void
5473 do_headers_action (ModestWindow *win, 
5474                    HeadersFunc func,
5475                    gpointer user_data)
5476 {
5477         TnyList *headers_list = NULL;
5478         TnyIterator *iter = NULL;
5479         TnyHeader *header = NULL;
5480         TnyFolder *folder = NULL;
5481
5482         /* Get headers */
5483         headers_list = get_selected_headers (win);
5484         if (!headers_list)
5485                 return;
5486
5487         /* Get the folder */
5488         iter = tny_list_create_iterator (headers_list);
5489         header = TNY_HEADER (tny_iterator_get_current (iter));
5490         if (header) {
5491                 folder = tny_header_get_folder (header);
5492                 g_object_unref (header);
5493         }
5494
5495         /* Call the function for each header */
5496         while (!tny_iterator_is_done (iter)) {
5497                 header = TNY_HEADER (tny_iterator_get_current (iter));
5498                 func (header, win, user_data);
5499                 g_object_unref (header);
5500                 tny_iterator_next (iter);
5501         }
5502
5503         /* Trick: do a poke status in order to speed up the signaling
5504            of observers */
5505         tny_folder_poke_status (folder);
5506
5507         /* Frees */
5508         g_object_unref (folder);
5509         g_object_unref (iter);
5510         g_object_unref (headers_list);
5511 }
5512
5513 void 
5514 modest_ui_actions_view_attachment (GtkAction *action,
5515                                    ModestWindow *window)
5516 {
5517         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5518                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
5519         } else {
5520                 /* not supported window for this action */
5521                 g_return_if_reached ();
5522         }
5523 }
5524
5525 void
5526 modest_ui_actions_save_attachments (GtkAction *action,
5527                                     ModestWindow *window)
5528 {
5529         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5530
5531                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
5532                         return;
5533
5534                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
5535         } else {
5536                 /* not supported window for this action */
5537                 g_return_if_reached ();
5538         }
5539 }
5540
5541 void
5542 modest_ui_actions_remove_attachments (GtkAction *action,
5543                                       ModestWindow *window)
5544 {
5545         if (MODEST_IS_MAIN_WINDOW (window)) {
5546                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
5547         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5548                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
5549         } else {
5550                 /* not supported window for this action */
5551                 g_return_if_reached ();
5552         }
5553 }
5554
5555 void 
5556 modest_ui_actions_on_settings (GtkAction *action, 
5557                                ModestWindow *win)
5558 {
5559         GtkWidget *dialog;
5560
5561         dialog = modest_platform_get_global_settings_dialog ();
5562         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
5563         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5564         gtk_widget_show_all (dialog);
5565
5566         gtk_dialog_run (GTK_DIALOG (dialog));
5567
5568         gtk_widget_destroy (dialog);
5569 }
5570
5571 void 
5572 modest_ui_actions_on_help (GtkAction *action, 
5573                            GtkWindow *win)
5574 {
5575         const gchar *help_id;
5576
5577         g_return_if_fail (win && GTK_IS_WINDOW(win));
5578         
5579         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
5580
5581         if (help_id)
5582                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5583 }
5584
5585 void 
5586 modest_ui_actions_on_csm_help (GtkAction *action, 
5587                                GtkWindow *win)
5588 {
5589         const gchar* help_id = NULL;
5590         GtkWidget *folder_view;
5591         TnyFolderStore *folder_store;
5592
5593         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
5594
5595         /* Get selected folder */
5596         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5597                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5598         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5599
5600         /* Switch help_id */
5601         if (folder_store && TNY_IS_FOLDER (folder_store))
5602                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
5603
5604         if (folder_store)
5605                 g_object_unref (folder_store);
5606
5607         if (help_id)
5608                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5609         else
5610                 modest_ui_actions_on_help (action, win);
5611 }
5612
5613 static void     
5614 retrieve_contents_cb (ModestMailOperation *mail_op, 
5615                       TnyHeader *header, 
5616                       gboolean canceled,
5617                       TnyMsg *msg,
5618                       GError *err,
5619                       gpointer user_data)
5620 {
5621         /* We only need this callback to show an error in case of
5622            memory low condition */
5623         modest_ui_actions_msg_retrieval_check (mail_op, header, msg);
5624 }
5625
5626 static void
5627 retrieve_msg_contents_performer (gboolean canceled, 
5628                                  GError *err,
5629                                  GtkWindow *parent_window, 
5630                                  TnyAccount *account, 
5631                                  gpointer user_data)
5632 {
5633         ModestMailOperation *mail_op;
5634         TnyList *headers = TNY_LIST (user_data);
5635
5636         if (err || canceled) {
5637                 check_memory_full_error ((GtkWidget *) parent_window, err);
5638                 goto out;
5639         }
5640
5641         /* Create mail operation */
5642         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
5643                                                                  modest_ui_actions_disk_operations_error_handler, 
5644                                                                  NULL, NULL);
5645         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5646         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
5647
5648         /* Frees */
5649         g_object_unref (mail_op);
5650  out:
5651         g_object_unref (headers);
5652         g_object_unref (account);
5653 }
5654
5655 void 
5656 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
5657                                             ModestWindow *window)
5658 {
5659         TnyList *headers = NULL;
5660         TnyAccount *account = NULL;
5661         TnyIterator *iter = NULL;
5662         TnyHeader *header = NULL;
5663         TnyFolder *folder = NULL;
5664
5665         /* Get headers */
5666         headers = get_selected_headers (window);
5667         if (!headers)
5668                 return;
5669
5670         /* Pick the account */
5671         iter = tny_list_create_iterator (headers);
5672         header = TNY_HEADER (tny_iterator_get_current (iter));
5673         folder = tny_header_get_folder (header);
5674         account = tny_folder_get_account (folder);
5675         g_object_unref (folder);
5676         g_object_unref (header);
5677         g_object_unref (iter);
5678
5679         /* Connect and perform the message retrieval */
5680         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
5681                                              g_object_ref (account), 
5682                                              retrieve_msg_contents_performer, 
5683                                              g_object_ref (headers));
5684
5685         /* Frees */
5686         g_object_unref (account);
5687         g_object_unref (headers);
5688 }
5689
5690 void
5691 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
5692 {
5693         g_return_if_fail (MODEST_IS_WINDOW (window));
5694
5695         /* Update dimmed */
5696         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
5697 }
5698
5699 void
5700 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
5701 {
5702         g_return_if_fail (MODEST_IS_WINDOW (window));
5703
5704         /* Update dimmed */
5705         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
5706 }
5707
5708 void
5709 modest_ui_actions_on_email_menu_activated (GtkAction *action,
5710                                           ModestWindow *window)
5711 {
5712         g_return_if_fail (MODEST_IS_WINDOW (window));
5713         
5714         /* Update dimmed */
5715         modest_ui_actions_check_menu_dimming_rules (window);
5716 }
5717
5718 void
5719 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
5720                                           ModestWindow *window)
5721 {
5722         g_return_if_fail (MODEST_IS_WINDOW (window));
5723
5724         /* Update dimmed */
5725         modest_ui_actions_check_menu_dimming_rules (window);
5726 }
5727
5728 void
5729 modest_ui_actions_on_view_menu_activated (GtkAction *action,
5730                                           ModestWindow *window)
5731 {
5732         g_return_if_fail (MODEST_IS_WINDOW (window));
5733
5734         /* Update dimmed */
5735         modest_ui_actions_check_menu_dimming_rules (window);
5736 }
5737
5738 void
5739 modest_ui_actions_on_format_menu_activated (GtkAction *action,
5740                                             ModestWindow *window)
5741 {
5742         g_return_if_fail (MODEST_IS_WINDOW (window));
5743
5744         /* Update dimmed */
5745         modest_ui_actions_check_menu_dimming_rules (window);
5746 }
5747
5748 void
5749 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
5750                                           ModestWindow *window)
5751 {
5752         g_return_if_fail (MODEST_IS_WINDOW (window));
5753
5754         /* Update dimmed */
5755         modest_ui_actions_check_menu_dimming_rules (window);
5756 }
5757
5758 void
5759 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
5760                                           ModestWindow *window)
5761 {
5762         g_return_if_fail (MODEST_IS_WINDOW (window));
5763
5764         /* Update dimmed */
5765         modest_ui_actions_check_menu_dimming_rules (window);
5766 }
5767
5768 void
5769 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
5770                                                  ModestWindow *window)
5771 {
5772         g_return_if_fail (MODEST_IS_WINDOW (window));
5773
5774         /* Update dimmed */
5775         modest_ui_actions_check_menu_dimming_rules (window);
5776 }
5777
5778 void
5779 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
5780                                                      ModestWindow *window)
5781 {
5782         g_return_if_fail (MODEST_IS_WINDOW (window));
5783
5784         /* Update dimmed */
5785         modest_ui_actions_check_menu_dimming_rules (window);
5786 }
5787
5788 void
5789 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
5790                                                      ModestWindow *window)
5791 {
5792         g_return_if_fail (MODEST_IS_WINDOW (window));
5793
5794         /* Update dimmed */
5795         modest_ui_actions_check_menu_dimming_rules (window);
5796 }
5797
5798 void
5799 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
5800 {
5801         g_return_if_fail (MODEST_IS_WINDOW (window));
5802
5803         /* we check for low-mem; in that case, show a warning, and don't allow
5804          * searching
5805          */
5806         if (modest_platform_check_memory_low (window, TRUE))
5807                 return;
5808         
5809         modest_platform_show_search_messages (GTK_WINDOW (window));
5810 }
5811
5812 void     
5813 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
5814 {
5815         g_return_if_fail (MODEST_IS_WINDOW (win));
5816
5817
5818         /* we check for low-mem; in that case, show a warning, and don't allow
5819          * for the addressbook
5820          */
5821         if (modest_platform_check_memory_low (win, TRUE))
5822                 return;
5823
5824
5825         modest_platform_show_addressbook (GTK_WINDOW (win));
5826 }
5827
5828
5829 void
5830 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
5831                                           ModestWindow *window)
5832 {
5833         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5834
5835         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
5836 }
5837
5838 static void 
5839 on_send_receive_finished (ModestMailOperation  *mail_op, 
5840                            gpointer user_data)
5841 {
5842         GtkWidget *header_view, *folder_view;
5843         TnyFolderStore *folder_store;
5844         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
5845
5846         /* Set send/receive operation finished */       
5847         modest_main_window_notify_send_receive_completed (main_win);
5848
5849         /* Don't refresh the current folder if there were any errors */
5850         if (modest_mail_operation_get_status (mail_op) !=
5851             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5852                 return;
5853         
5854         /* Refresh the current folder if we're viewing a window. We do
5855            this because the user won't be able to see the new mails in
5856            the selected folder after a Send&Receive because it only
5857            performs a poke_status, i.e, only the number of read/unread
5858            messages is updated, but the new headers are not
5859            downloaded */
5860         folder_view = modest_main_window_get_child_widget (main_win, 
5861                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5862         if (!folder_view)
5863                 return;
5864
5865         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5866         
5867         /* Do not need to refresh INBOX again because the
5868            update_account does it always automatically */
5869         if (folder_store && TNY_IS_FOLDER (folder_store) && 
5870             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
5871                 ModestMailOperation *refresh_op;
5872
5873                 header_view = modest_main_window_get_child_widget (main_win,
5874                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5875                 
5876                 /* We do not need to set the contents style
5877                    because it hasn't changed. We also do not
5878                    need to save the widget status. Just force
5879                    a refresh */
5880                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
5881                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
5882                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
5883                                                       folder_refreshed_cb, main_win);
5884                 g_object_unref (refresh_op);
5885         }
5886         
5887         if (folder_store)
5888                 g_object_unref (folder_store);
5889 }
5890
5891
5892 void 
5893 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
5894                                                 TnyHeader *header, 
5895                                                 TnyMsg *msg, 
5896                                                 GError *err, 
5897                                                 gpointer user_data)
5898 {
5899         const gchar* server_name = NULL;
5900         TnyTransportAccount *server_account;
5901         gchar *message = NULL;
5902
5903         /* Don't show anything if the user cancelled something or the send receive request is not
5904          * interactive */
5905         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
5906             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
5907                 return;
5908
5909
5910         /* Get the server name: */
5911         server_account = 
5912                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
5913         if (server_account)
5914                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));          
5915         else
5916                 g_return_if_reached ();
5917
5918         /* Show the appropriate message text for the GError: */
5919         switch (err->code) {
5920         case TNY_SERVICE_ERROR_CONNECT:
5921                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5922                 break;
5923         case TNY_SERVICE_ERROR_AUTHENTICATE:
5924                 message = g_strdup_printf (_("emev_ni_ui_smtp_authentication_fail_error"), server_name);
5925                 break;
5926         case TNY_SERVICE_ERROR_SEND:
5927                 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
5928                 break;
5929         case TNY_SERVICE_ERROR_UNAVAILABLE:
5930                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5931                 break;
5932         default:
5933                 g_warning ("%s: unexpected ERROR %d",
5934                            __FUNCTION__, err->code);
5935                 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
5936                 break;  
5937         }
5938         
5939         /* TODO if the username or the password where not defined we
5940            should show the Accounts Settings dialog or the Connection
5941            specific SMTP server window */
5942
5943         modest_platform_run_information_dialog (NULL, message, FALSE);
5944         g_free (message);
5945         g_object_unref (server_account);
5946 }
5947
5948 void
5949 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
5950                                                 gchar *msg_id, 
5951                                                 guint status,
5952                                                 gpointer user_data)
5953 {
5954         ModestMainWindow *main_window = NULL;
5955         ModestWindowMgr *mgr = NULL;
5956         GtkWidget *folder_view = NULL, *header_view = NULL;
5957         TnyFolderStore *selected_folder = NULL;
5958         TnyFolderType folder_type;
5959
5960         mgr = modest_runtime_get_window_mgr ();
5961         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
5962                                                                              FALSE));/* don't create */
5963         if (!main_window)
5964                 return;
5965
5966         /* Check if selected folder is OUTBOX */
5967         folder_view = modest_main_window_get_child_widget (main_window,
5968                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5969         header_view = modest_main_window_get_child_widget (main_window,
5970                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5971
5972         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5973         if (!TNY_IS_FOLDER (selected_folder)) 
5974                 goto frees;
5975
5976         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
5977 #if GTK_CHECK_VERSION(2, 8, 0) 
5978         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
5979         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
5980                 GtkTreeViewColumn *tree_column;
5981
5982                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
5983                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
5984                 gtk_tree_view_column_queue_resize (tree_column);
5985         }
5986 #else
5987         gtk_widget_queue_draw (header_view);
5988 #endif          
5989
5990         /* Rerun dimming rules, because the message could become deletable for example */
5991         modest_window_check_dimming_rules_group (MODEST_WINDOW (main_window), 
5992                                                  MODEST_DIMMING_RULES_TOOLBAR);
5993         
5994         /* Free */
5995  frees:
5996         if (selected_folder != NULL)
5997                 g_object_unref (selected_folder);
5998 }
5999
6000 void 
6001 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
6002                                                TnyAccount *account)
6003 {
6004         ModestTransportStoreProtocol proto;
6005         const gchar *proto_name;
6006         gchar *error_note = NULL;
6007         
6008         proto_name = tny_account_get_proto (account);
6009         proto = modest_protocol_info_get_transport_store_protocol (proto_name);
6010         
6011         switch (proto) {
6012         case MODEST_PROTOCOL_STORE_POP:
6013                 error_note = g_strdup_printf (_("emev_ni_ui_pop3_msg_connect_error"), 
6014                                               tny_account_get_hostname (account));
6015                 break;
6016         case MODEST_PROTOCOL_STORE_IMAP:
6017                 error_note = g_strdup_printf (_("emev_ni_ui_imap_connect_server_error"), 
6018                                               tny_account_get_hostname (account));
6019                 break;
6020         case MODEST_PROTOCOL_STORE_MAILDIR:
6021         case MODEST_PROTOCOL_STORE_MBOX:
6022                 error_note = g_strdup (_("emev_nc_mailbox_notavailable"));
6023                 break;
6024         default:
6025                 g_warning ("%s: This should not be reached", __FUNCTION__);
6026         }
6027
6028         if (error_note) {
6029                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
6030                 g_free (error_note);
6031         }
6032 }
6033
6034 gchar *
6035 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
6036 {
6037         gchar *msg = NULL;
6038         TnyFolderStore *folder = NULL;
6039         TnyAccount *account = NULL;
6040         ModestTransportStoreProtocol proto;
6041         TnyHeader *header = NULL;
6042
6043         if (MODEST_IS_MAIN_WINDOW (win)) {
6044                 GtkWidget *header_view;
6045                 TnyList* headers = NULL;
6046                 TnyIterator *iter;
6047                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
6048                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6049                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6050                 if (!headers || tny_list_get_length (headers) == 0) {
6051                         if (headers)
6052                                 g_object_unref (headers);
6053                         return NULL;
6054                 }
6055                 iter = tny_list_create_iterator (headers);
6056                 header = TNY_HEADER (tny_iterator_get_current (iter));
6057                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6058                 g_object_unref (iter);
6059                 g_object_unref (headers);
6060         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
6061                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
6062                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6063         }
6064
6065         /* Get the account type */
6066         account = tny_folder_get_account (TNY_FOLDER (folder));
6067         proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
6068         if (proto == MODEST_PROTOCOL_STORE_POP) {
6069                 msg = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
6070         } else if (proto == MODEST_PROTOCOL_STORE_IMAP) {
6071                 gchar *subject;
6072                 subject = tny_header_dup_subject (header);
6073                 msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"), 
6074                                        subject);
6075                 g_free (subject);
6076         } else {
6077                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
6078         }
6079
6080         /* Frees */
6081         g_object_unref (account);
6082         g_object_unref (folder);
6083         g_object_unref (header);
6084
6085         return msg;
6086 }