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