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