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