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