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