* Fixes NB#87094 merged from trunk 5191 & 5259
[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 (gtk_tree_row_reference_valid (next_row_reference)) 
533                                 gtk_tree_row_reference_free (next_row_reference);
534                         if (next_path != NULL) 
535                                 gtk_tree_path_free (next_path);                         
536                         if (gtk_tree_row_reference_valid (prev_row_reference)) 
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) && 
4774                            gtk_tree_row_reference_valid (helper->reference)) {
4775                         GtkWidget *header_view;
4776                         GtkTreePath *path;
4777                         GtkTreeSelection *sel;
4778
4779                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4780                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4781                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4782                         path = gtk_tree_row_reference_get_path (helper->reference);
4783                         /* We need to unselect the previous one
4784                            because we could be copying instead of
4785                            moving */
4786                         gtk_tree_selection_unselect_all (sel);
4787                         gtk_tree_selection_select_path (sel, path);
4788                         gtk_tree_path_free (path);
4789                 }
4790                 g_object_unref (object);
4791         }
4792
4793         /* Close the "Pasting" information banner */
4794         gtk_widget_destroy (GTK_WIDGET(helper->banner));
4795         g_object_unref (helper->banner);
4796         if (gtk_tree_row_reference_valid (helper->reference))
4797                 gtk_tree_row_reference_free (helper->reference);
4798         g_free (helper);
4799 }
4800
4801 static void
4802 folder_move_to_cb (ModestMailOperation *mail_op, 
4803                    TnyFolder *new_folder,
4804                    gpointer user_data)
4805 {
4806         GtkWidget *folder_view;
4807         GObject *object;
4808
4809         object = modest_mail_operation_get_source (mail_op);
4810         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4811                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4812         g_object_ref (folder_view);
4813         g_object_unref (object);
4814         move_to_cb (mail_op, user_data);
4815         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
4816         g_object_unref (folder_view);
4817 }
4818
4819 static void
4820 msgs_move_to_cb (ModestMailOperation *mail_op, 
4821                  gpointer user_data)
4822 {
4823         move_to_cb (mail_op, user_data);
4824 }
4825
4826 void
4827 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
4828                                              gpointer user_data)
4829 {
4830         ModestWindow *main_window = NULL;
4831         
4832         /* Disable next automatic folder selection */
4833         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4834                                                          FALSE); /* don't create */
4835         if (main_window) {
4836                 GObject *win = NULL;
4837                 GtkWidget *folder_view = NULL;
4838         
4839                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4840                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
4841                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4842                 
4843                 if (user_data && TNY_IS_FOLDER (user_data)) {
4844                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), 
4845                                                           TNY_FOLDER (user_data), FALSE);
4846                 }
4847
4848                 /* Show notification dialog only if the main window exists */
4849                 win = modest_mail_operation_get_source (mail_op);
4850                 modest_platform_run_information_dialog ((GtkWindow *) win, 
4851                                                         _("mail_in_ui_folder_move_target_error"), 
4852                                                         FALSE);
4853                 if (win)
4854                         g_object_unref (win);
4855         }
4856 }
4857
4858 static void
4859 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
4860                        TnyHeader *header, 
4861                        gboolean canceled,
4862                        TnyMsg *msg, 
4863                        GError *err,
4864                        gpointer user_data)
4865 {
4866         TnyList *parts;
4867         TnyIterator *iter;
4868         gint pending_purges = 0;
4869         gboolean some_purged = FALSE;
4870         ModestWindow *win = MODEST_WINDOW (user_data);
4871         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4872
4873         /* If there was any error */
4874         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4875                 modest_window_mgr_unregister_header (mgr, header);
4876                 return;
4877         }
4878
4879         /* Once the message has been retrieved for purging, we check if
4880          * it's all ok for purging */
4881
4882         parts = tny_simple_list_new ();
4883         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4884         iter = tny_list_create_iterator (parts);
4885
4886         while (!tny_iterator_is_done (iter)) {
4887                 TnyMimePart *part;
4888                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4889                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4890                         if (tny_mime_part_is_purged (part))
4891                                 some_purged = TRUE;
4892                         else
4893                                 pending_purges++;
4894                 }
4895
4896                 if (part)
4897                         g_object_unref (part);
4898
4899                 tny_iterator_next (iter);
4900         }
4901         g_object_unref (iter);
4902         
4903
4904         if (pending_purges>0) {
4905                 gint response;
4906                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4907
4908                 if (response == GTK_RESPONSE_OK) {
4909                         GtkWidget *info;
4910                         info =
4911                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_ib_removing_attachment"));
4912                         iter = tny_list_create_iterator (parts);
4913                         while (!tny_iterator_is_done (iter)) {
4914                                 TnyMimePart *part;
4915                                 
4916                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4917                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4918                                         tny_mime_part_set_purged (part);
4919
4920                                 if (part)
4921                                         g_object_unref (part);
4922
4923                                 tny_iterator_next (iter);
4924                         }
4925                         g_object_unref (iter);
4926                         
4927                         tny_msg_rewrite_cache (msg);
4928
4929                         gtk_widget_destroy (info);
4930                 }
4931         }
4932
4933         modest_window_mgr_unregister_header (mgr, header);
4934
4935         g_object_unref (parts);
4936 }
4937
4938 static void
4939 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4940                                                      ModestMainWindow *win)
4941 {
4942         GtkWidget *header_view;
4943         TnyList *header_list;
4944         TnyHeader *header;
4945         TnyHeaderFlags flags;
4946         ModestWindow *msg_view_window =  NULL;
4947         gboolean found;
4948
4949         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4950
4951         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4952                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4953
4954         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4955         if (!header_list) {
4956                 g_warning ("%s: no header selected", __FUNCTION__);
4957                 return;
4958         }
4959         
4960         if (tny_list_get_length (header_list) == 1) {
4961                 TnyIterator *iter = tny_list_create_iterator (header_list);
4962                 header = TNY_HEADER (tny_iterator_get_current (iter));
4963                 g_object_unref (iter);
4964         } else
4965                 return;
4966         
4967         if (!header || !TNY_IS_HEADER(header)) {
4968                 g_warning ("%s: header is not valid", __FUNCTION__);
4969                 return;
4970         }
4971         
4972         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4973                                                           header, &msg_view_window);
4974         flags = tny_header_get_flags (header);
4975         if (!(flags & TNY_HEADER_FLAG_CACHED))
4976                 return;
4977         if (found) {
4978                 if (msg_view_window != NULL) 
4979                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4980                 else {
4981                         /* do nothing; uid was registered before, so window is probably on it's way */
4982                         g_warning ("debug: header %p has already been registered", header);
4983                 }
4984         } else {
4985                 ModestMailOperation *mail_op = NULL;
4986                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
4987                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
4988                                                                          modest_ui_actions_disk_operations_error_handler,
4989                                                                          NULL, NULL);
4990                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4991                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
4992                 
4993                 g_object_unref (mail_op);
4994         }
4995         if (header)
4996                 g_object_unref (header);
4997         if (header_list)
4998                 g_object_unref (header_list);
4999 }
5000
5001 /*
5002  * Checks if we need a connection to do the transfer and if the user
5003  * wants to connect to complete it
5004  */
5005 void
5006 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5007                                        TnyFolderStore *src_folder,
5008                                        TnyList *headers,
5009                                        TnyFolder *dst_folder,
5010                                        gboolean delete_originals,
5011                                        gboolean *need_connection,
5012                                        gboolean *do_xfer)
5013 {
5014         TnyAccount *src_account;
5015         gint uncached_msgs = 0;
5016
5017         uncached_msgs = header_list_count_uncached_msgs (headers);
5018
5019         /* We don't need any further check if
5020          *
5021          * 1- the source folder is local OR
5022          * 2- the device is already online
5023          */
5024         if (!modest_tny_folder_store_is_remote (src_folder) ||
5025             tny_device_is_online (modest_runtime_get_device())) {
5026                 *need_connection = FALSE;
5027                 *do_xfer = TRUE;
5028                 return;
5029         }
5030
5031         /* We must ask for a connection when
5032          *
5033          *   - the message(s) is not already cached   OR 
5034          *   - the message(s) is cached but the leave_on_server setting
5035          * is FALSE (because we need to sync the source folder to
5036          * delete the message from the server (for IMAP we could do it
5037          * offline, it'll take place the next time we get a
5038          * connection)
5039          */
5040         src_account = get_account_from_folder_store (src_folder);
5041         if (uncached_msgs > 0) {
5042                 guint num_headers;
5043                 const gchar *msg;
5044
5045                 *need_connection = TRUE;
5046                 num_headers = tny_list_get_length (headers);
5047                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
5048
5049                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
5050                     GTK_RESPONSE_CANCEL) {
5051                         *do_xfer = FALSE;
5052                 } else {
5053                         *do_xfer = TRUE;
5054                 }
5055         } else {
5056                 /* The transfer is possible and the user wants to */
5057                 *do_xfer = TRUE;
5058
5059                 if (remote_folder_is_pop (src_folder) && delete_originals) {
5060                         const gchar *account_name;
5061                         gboolean leave_on_server;
5062                         
5063                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
5064                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
5065                                                                                   account_name);
5066                         
5067                         if (leave_on_server == TRUE) {
5068                                 *need_connection = FALSE;
5069                         } else {
5070                                 *need_connection = TRUE;
5071                         }
5072                 } else {
5073                         *need_connection = FALSE;
5074                 }
5075         }
5076
5077         /* Frees */
5078         g_object_unref (src_account);
5079 }
5080
5081 static void
5082 xfer_messages_error_handler (ModestMailOperation *mail_op, 
5083                              gpointer user_data)
5084 {
5085         ModestWindow *main_window = NULL;
5086         
5087         /* Disable next automatic folder selection */
5088         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5089                                                          FALSE); /* don't create */
5090         if (main_window) {
5091                 GObject *win = modest_mail_operation_get_source (mail_op);
5092                 modest_platform_run_information_dialog ((GtkWindow *) win, 
5093                                                         _("mail_in_ui_folder_move_target_error"), 
5094                                                         FALSE);
5095                 if (win)
5096                         g_object_unref (win);
5097         }
5098 }
5099
5100 typedef struct {
5101         TnyFolderStore *dst_folder;
5102         TnyList *headers;
5103 } XferMsgsHelper;
5104
5105 /**
5106  * Utility function that transfer messages from both the main window
5107  * and the msg view window when using the "Move to" dialog
5108  */
5109 static void
5110 xfer_messages_performer  (gboolean canceled, 
5111                           GError *err,
5112                           GtkWindow *parent_window, 
5113                           TnyAccount *account, 
5114                           gpointer user_data)
5115 {
5116         ModestWindow *win = MODEST_WINDOW (parent_window);
5117         TnyAccount *dst_account = NULL;
5118         const gchar *proto_str = NULL;
5119         gboolean dst_is_pop = FALSE;
5120         XferMsgsHelper *helper;
5121         MoveToHelper *movehelper;
5122         ModestMailOperation *mail_op;
5123
5124         helper = (XferMsgsHelper *) user_data;
5125
5126         if (canceled || err) {
5127                 if (!check_memory_full_error ((GtkWidget *) parent_window, err)) {
5128                         /* Show the proper error message */
5129                         modest_ui_actions_on_account_connection_error (parent_window, account);
5130                 }
5131                 goto end;
5132         }
5133
5134         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
5135         proto_str = tny_account_get_proto (dst_account);
5136
5137         /* tinymail will return NULL for local folders it seems */
5138         dst_is_pop = proto_str &&
5139                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
5140                  MODEST_PROTOCOL_STORE_POP);
5141
5142         g_object_unref (dst_account);
5143
5144         if (dst_is_pop) {
5145                 modest_platform_information_banner (GTK_WIDGET (win),
5146                                                     NULL,
5147                                                     ngettext("mail_in_ui_folder_move_target_error",
5148                                                              "mail_in_ui_folder_move_targets_error",
5149                                                              tny_list_get_length (helper->headers)));
5150                 goto end;
5151         }
5152
5153         movehelper = g_new0 (MoveToHelper, 1);
5154         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
5155                                                                _CS("ckct_nw_pasting"));
5156         if (movehelper->banner != NULL)  {
5157                 g_object_ref (movehelper->banner);
5158                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
5159         }
5160
5161         if (MODEST_IS_MAIN_WINDOW (win)) {
5162                 GtkWidget *header_view = 
5163                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5164                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5165                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5166         }
5167
5168         /* Perform the mail operation */
5169         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5170                                                                  xfer_messages_error_handler,
5171                                                                  movehelper, NULL);
5172         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
5173                                          mail_op);
5174
5175         modest_mail_operation_xfer_msgs (mail_op, 
5176                                          helper->headers,
5177                                          TNY_FOLDER (helper->dst_folder),
5178                                          TRUE,
5179                                          msgs_move_to_cb,
5180                                          movehelper);
5181
5182         g_object_unref (G_OBJECT (mail_op));
5183  end:
5184         g_object_unref (helper->dst_folder);
5185         g_object_unref (helper->headers);
5186         g_slice_free (XferMsgsHelper, helper);
5187 }
5188
5189 typedef struct {
5190         TnyFolder *src_folder;
5191         TnyFolderStore *dst_folder;
5192         gboolean delete_original;
5193         GtkWidget *folder_view;
5194 } MoveFolderInfo;
5195
5196 static void
5197 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window, 
5198                 TnyAccount *account, gpointer user_data)
5199 {
5200         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5201         GtkTreeSelection *sel;
5202         ModestMailOperation *mail_op = NULL;
5203         
5204         if (canceled || err || !MODEST_IS_MAIN_WINDOW (parent_window)) {
5205                 g_object_unref (G_OBJECT (info->src_folder));
5206                 g_object_unref (G_OBJECT (info->dst_folder));
5207                 g_free (info);
5208                 return;
5209         }
5210         
5211         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5212         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5213                         _CS("ckct_nw_pasting"));
5214         if (helper->banner != NULL)  {
5215                 g_object_ref (helper->banner);
5216                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
5217                 gtk_widget_show (GTK_WIDGET(helper->banner));
5218         }
5219         /* Clean folder on header view before moving it */
5220         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5221         gtk_tree_selection_unselect_all (sel);
5222
5223         /* Let gtk events run. We need that the folder
5224            view frees its reference to the source
5225            folder *before* issuing the mail operation
5226            so we need the signal handler of selection
5227            changed to happen before the mail
5228            operation 
5229         while (gtk_events_pending ())
5230                 gtk_main_iteration ();   */
5231
5232         mail_op =
5233                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5234                                 modest_ui_actions_move_folder_error_handler,
5235                                 info->src_folder, NULL);
5236         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5237                         mail_op);
5238
5239         /* Select *after* the changes */
5240         /* TODO: this function hangs UI after transfer */ 
5241         /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
5242         /*                                                        TNY_FOLDER (src_folder), TRUE); */
5243
5244         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5245                                           TNY_FOLDER (info->dst_folder), TRUE);
5246         modest_mail_operation_xfer_folder (mail_op,
5247                         TNY_FOLDER (info->src_folder),
5248                         info->dst_folder,
5249                         info->delete_original, 
5250                         folder_move_to_cb, 
5251                         helper);
5252         g_object_unref (G_OBJECT (info->src_folder));
5253
5254         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
5255         /* } */
5256         
5257         /* Unref mail operation */
5258         g_object_unref (G_OBJECT (mail_op));
5259         g_object_unref (G_OBJECT (info->dst_folder));
5260         g_free (user_data);
5261 }
5262
5263 static TnyAccount *
5264 get_account_from_folder_store (TnyFolderStore *folder_store) 
5265 {
5266         if (TNY_IS_ACCOUNT (folder_store))
5267                 return g_object_ref (folder_store);
5268         else
5269                 return tny_folder_get_account (TNY_FOLDER (folder_store));
5270 }
5271
5272 /*
5273  * UI handler for the "Move to" action when invoked from the
5274  * ModestMainWindow
5275  */
5276 static void 
5277 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
5278                                           GtkWidget *folder_view,
5279                                           TnyFolderStore *dst_folder,
5280                                           ModestMainWindow *win)
5281 {
5282         ModestHeaderView *header_view = NULL;
5283         TnyFolderStore *src_folder = NULL;
5284
5285         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5286
5287         /* Get the source folder */
5288         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5289
5290         /* Get header view */
5291         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
5292
5293         /* Get folder or messages to transfer */
5294         if (gtk_widget_is_focus (folder_view)) {
5295                 gboolean do_xfer = TRUE;
5296
5297                 /* Allow only to transfer folders to the local root folder */
5298                 if (TNY_IS_ACCOUNT (dst_folder) && 
5299                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5300                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5301                         do_xfer = FALSE;
5302                 } else if (!TNY_IS_FOLDER (src_folder)) {
5303                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5304                         do_xfer = FALSE;
5305                 }
5306
5307                 if (do_xfer) {                  
5308                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5309                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5310
5311                         info->src_folder = g_object_ref (src_folder);
5312                         info->dst_folder = g_object_ref (dst_folder);
5313                         info->delete_original = TRUE;
5314                         info->folder_view = folder_view;
5315
5316                         connect_info->callback = on_move_folder_cb;
5317                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5318                         connect_info->data = info;
5319
5320                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5321                                                                    TNY_FOLDER_STORE (src_folder), 
5322                                                                    connect_info);
5323                 }
5324         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5325                 TnyList *headers;
5326
5327                 headers = modest_header_view_get_selected_headers(header_view);
5328
5329                 /* Transfer the messages */
5330                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder), 
5331                                                             headers, TNY_FOLDER (dst_folder));
5332
5333                 g_object_unref (headers);
5334         }
5335
5336         /* Frees */
5337         g_object_unref (src_folder);
5338 }
5339
5340
5341 void
5342 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
5343                                             TnyFolder *src_folder,
5344                                             TnyList *headers,
5345                                             TnyFolder *dst_folder)
5346 {
5347         gboolean need_connection = TRUE;
5348         gboolean do_xfer = TRUE;
5349         XferMsgsHelper *helper;
5350
5351         g_return_if_fail (TNY_IS_FOLDER (src_folder));
5352         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5353         g_return_if_fail (TNY_IS_LIST (headers));
5354         
5355         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder), 
5356                                                headers, TNY_FOLDER (dst_folder),
5357                                                TRUE, &need_connection, 
5358                                                &do_xfer);
5359
5360         /* If we don't want to transfer just return */
5361         if (!do_xfer)
5362                 return;
5363
5364         /* Create the helper */
5365         helper = g_slice_new (XferMsgsHelper);
5366         helper->dst_folder = g_object_ref (dst_folder);
5367         helper->headers = g_object_ref (headers);
5368
5369         if (need_connection) {
5370                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5371                 connect_info->callback = xfer_messages_performer;
5372                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
5373                 connect_info->data = helper;
5374                 
5375                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5376                                                            TNY_FOLDER_STORE (src_folder), 
5377                                                            connect_info);
5378         } else {
5379                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
5380                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
5381                                          src_account, helper);
5382                 g_object_unref (src_account);
5383         }
5384 }
5385
5386 /*
5387  * UI handler for the "Move to" action when invoked from the
5388  * ModestMsgViewWindow
5389  */
5390 static void 
5391 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
5392                                               TnyFolderStore *dst_folder,
5393                                               ModestMsgViewWindow *win)
5394 {
5395         TnyList *headers = NULL;
5396         TnyHeader *header = NULL;
5397         TnyFolder *src_folder = NULL;
5398
5399         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5400
5401         /* Create header list */
5402         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5403         src_folder = TNY_FOLDER (tny_header_get_folder(header));
5404         headers = tny_simple_list_new ();
5405         tny_list_append (headers, G_OBJECT (header));
5406
5407         /* Transfer the messages */
5408         modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder, headers, 
5409                                                     TNY_FOLDER (dst_folder));
5410
5411         /* Frees */
5412         g_object_unref (src_folder);
5413         g_object_unref (header);
5414         g_object_unref (headers);
5415 }
5416
5417 void 
5418 modest_ui_actions_on_move_to (GtkAction *action, 
5419                               ModestWindow *win)
5420 {
5421         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
5422         gint result = 0;
5423         TnyFolderStore *dst_folder = NULL;
5424         ModestMainWindow *main_window;
5425
5426         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
5427                           MODEST_IS_MSG_VIEW_WINDOW (win));
5428
5429         /* Get the main window if exists */
5430         if (MODEST_IS_MAIN_WINDOW (win))
5431                 main_window = MODEST_MAIN_WINDOW (win);
5432         else
5433                 main_window = 
5434                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5435                                                                                FALSE)); /* don't create */
5436
5437         /* Get the folder view widget if exists */
5438         if (main_window)
5439                 folder_view = modest_main_window_get_child_widget (main_window,
5440                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5441         else
5442                 folder_view = NULL;
5443
5444         /* Create and run the dialog */
5445         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
5446         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5447         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog));
5448         result = gtk_dialog_run (GTK_DIALOG(dialog));
5449         g_object_ref (tree_view);
5450         gtk_widget_destroy (dialog);
5451
5452         if (result != GTK_RESPONSE_ACCEPT)
5453                 return;
5454
5455         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
5456         /* Do window specific stuff */
5457         if (MODEST_IS_MAIN_WINDOW (win)) {
5458                 modest_ui_actions_on_main_window_move_to (action,
5459                                 folder_view,
5460                                 dst_folder,
5461                                 MODEST_MAIN_WINDOW (win));
5462         } else {
5463                 modest_ui_actions_on_msg_view_window_move_to (action,
5464                                 dst_folder,
5465                                 MODEST_MSG_VIEW_WINDOW (win));
5466         }
5467
5468         if (dst_folder)
5469                 g_object_unref (dst_folder);
5470 }
5471
5472 /*
5473  * Calls #HeadersFunc for each header already selected in the main
5474  * window or the message currently being shown in the msg view window
5475  */
5476 static void
5477 do_headers_action (ModestWindow *win, 
5478                    HeadersFunc func,
5479                    gpointer user_data)
5480 {
5481         TnyList *headers_list = NULL;
5482         TnyIterator *iter = NULL;
5483         TnyHeader *header = NULL;
5484         TnyFolder *folder = NULL;
5485
5486         /* Get headers */
5487         headers_list = get_selected_headers (win);
5488         if (!headers_list)
5489                 return;
5490
5491         /* Get the folder */
5492         iter = tny_list_create_iterator (headers_list);
5493         header = TNY_HEADER (tny_iterator_get_current (iter));
5494         if (header) {
5495                 folder = tny_header_get_folder (header);
5496                 g_object_unref (header);
5497         }
5498
5499         /* Call the function for each header */
5500         while (!tny_iterator_is_done (iter)) {
5501                 header = TNY_HEADER (tny_iterator_get_current (iter));
5502                 func (header, win, user_data);
5503                 g_object_unref (header);
5504                 tny_iterator_next (iter);
5505         }
5506
5507         /* Trick: do a poke status in order to speed up the signaling
5508            of observers */
5509         tny_folder_poke_status (folder);
5510
5511         /* Frees */
5512         g_object_unref (folder);
5513         g_object_unref (iter);
5514         g_object_unref (headers_list);
5515 }
5516
5517 void 
5518 modest_ui_actions_view_attachment (GtkAction *action,
5519                                    ModestWindow *window)
5520 {
5521         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5522                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
5523         } else {
5524                 /* not supported window for this action */
5525                 g_return_if_reached ();
5526         }
5527 }
5528
5529 void
5530 modest_ui_actions_save_attachments (GtkAction *action,
5531                                     ModestWindow *window)
5532 {
5533         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5534
5535                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
5536                         return;
5537
5538                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
5539         } else {
5540                 /* not supported window for this action */
5541                 g_return_if_reached ();
5542         }
5543 }
5544
5545 void
5546 modest_ui_actions_remove_attachments (GtkAction *action,
5547                                       ModestWindow *window)
5548 {
5549         if (MODEST_IS_MAIN_WINDOW (window)) {
5550                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
5551         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5552                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
5553         } else {
5554                 /* not supported window for this action */
5555                 g_return_if_reached ();
5556         }
5557 }
5558
5559 void 
5560 modest_ui_actions_on_settings (GtkAction *action, 
5561                                ModestWindow *win)
5562 {
5563         GtkWidget *dialog;
5564
5565         dialog = modest_platform_get_global_settings_dialog ();
5566         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
5567         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5568         gtk_widget_show_all (dialog);
5569
5570         gtk_dialog_run (GTK_DIALOG (dialog));
5571
5572         gtk_widget_destroy (dialog);
5573 }
5574
5575 void 
5576 modest_ui_actions_on_help (GtkAction *action, 
5577                            GtkWindow *win)
5578 {
5579         const gchar *help_id;
5580
5581         g_return_if_fail (win && GTK_IS_WINDOW(win));
5582         
5583         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
5584
5585         if (help_id)
5586                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5587 }
5588
5589 void 
5590 modest_ui_actions_on_csm_help (GtkAction *action, 
5591                                GtkWindow *win)
5592 {
5593         const gchar* help_id = NULL;
5594         GtkWidget *folder_view;
5595         TnyFolderStore *folder_store;
5596
5597         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
5598
5599         /* Get selected folder */
5600         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5601                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5602         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5603
5604         /* Switch help_id */
5605         if (folder_store && TNY_IS_FOLDER (folder_store))
5606                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
5607
5608         if (folder_store)
5609                 g_object_unref (folder_store);
5610
5611         if (help_id)
5612                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5613         else
5614                 modest_ui_actions_on_help (action, win);
5615 }
5616
5617 static void     
5618 retrieve_contents_cb (ModestMailOperation *mail_op, 
5619                       TnyHeader *header, 
5620                       gboolean canceled,
5621                       TnyMsg *msg,
5622                       GError *err,
5623                       gpointer user_data)
5624 {
5625         /* We only need this callback to show an error in case of
5626            memory low condition */
5627         modest_ui_actions_msg_retrieval_check (mail_op, header, msg);
5628 }
5629
5630 static void
5631 retrieve_msg_contents_performer (gboolean canceled, 
5632                                  GError *err,
5633                                  GtkWindow *parent_window, 
5634                                  TnyAccount *account, 
5635                                  gpointer user_data)
5636 {
5637         ModestMailOperation *mail_op;
5638         TnyList *headers = TNY_LIST (user_data);
5639
5640         if (err || canceled) {
5641                 check_memory_full_error ((GtkWidget *) parent_window, err);
5642                 goto out;
5643         }
5644
5645         /* Create mail operation */
5646         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
5647                                                                  modest_ui_actions_disk_operations_error_handler, 
5648                                                                  NULL, NULL);
5649         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5650         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
5651
5652         /* Frees */
5653         g_object_unref (mail_op);
5654  out:
5655         g_object_unref (headers);
5656         g_object_unref (account);
5657 }
5658
5659 void 
5660 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
5661                                             ModestWindow *window)
5662 {
5663         TnyList *headers = NULL;
5664         TnyAccount *account = NULL;
5665         TnyIterator *iter = NULL;
5666         TnyHeader *header = NULL;
5667         TnyFolder *folder = NULL;
5668
5669         /* Get headers */
5670         headers = get_selected_headers (window);
5671         if (!headers)
5672                 return;
5673
5674         /* Pick the account */
5675         iter = tny_list_create_iterator (headers);
5676         header = TNY_HEADER (tny_iterator_get_current (iter));
5677         folder = tny_header_get_folder (header);
5678         account = tny_folder_get_account (folder);
5679         g_object_unref (folder);
5680         g_object_unref (header);
5681         g_object_unref (iter);
5682
5683         /* Connect and perform the message retrieval */
5684         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
5685                                              g_object_ref (account), 
5686                                              retrieve_msg_contents_performer, 
5687                                              g_object_ref (headers));
5688
5689         /* Frees */
5690         g_object_unref (account);
5691         g_object_unref (headers);
5692 }
5693
5694 void
5695 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
5696 {
5697         g_return_if_fail (MODEST_IS_WINDOW (window));
5698
5699         /* Update dimmed */
5700         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
5701 }
5702
5703 void
5704 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
5705 {
5706         g_return_if_fail (MODEST_IS_WINDOW (window));
5707
5708         /* Update dimmed */
5709         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
5710 }
5711
5712 void
5713 modest_ui_actions_on_email_menu_activated (GtkAction *action,
5714                                           ModestWindow *window)
5715 {
5716         g_return_if_fail (MODEST_IS_WINDOW (window));
5717         
5718         /* Update dimmed */
5719         modest_ui_actions_check_menu_dimming_rules (window);
5720 }
5721
5722 void
5723 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
5724                                           ModestWindow *window)
5725 {
5726         g_return_if_fail (MODEST_IS_WINDOW (window));
5727
5728         /* Update dimmed */
5729         modest_ui_actions_check_menu_dimming_rules (window);
5730 }
5731
5732 void
5733 modest_ui_actions_on_view_menu_activated (GtkAction *action,
5734                                           ModestWindow *window)
5735 {
5736         g_return_if_fail (MODEST_IS_WINDOW (window));
5737
5738         /* Update dimmed */
5739         modest_ui_actions_check_menu_dimming_rules (window);
5740 }
5741
5742 void
5743 modest_ui_actions_on_format_menu_activated (GtkAction *action,
5744                                             ModestWindow *window)
5745 {
5746         g_return_if_fail (MODEST_IS_WINDOW (window));
5747
5748         /* Update dimmed */
5749         modest_ui_actions_check_menu_dimming_rules (window);
5750 }
5751
5752 void
5753 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
5754                                           ModestWindow *window)
5755 {
5756         g_return_if_fail (MODEST_IS_WINDOW (window));
5757
5758         /* Update dimmed */
5759         modest_ui_actions_check_menu_dimming_rules (window);
5760 }
5761
5762 void
5763 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
5764                                           ModestWindow *window)
5765 {
5766         g_return_if_fail (MODEST_IS_WINDOW (window));
5767
5768         /* Update dimmed */
5769         modest_ui_actions_check_menu_dimming_rules (window);
5770 }
5771
5772 void
5773 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
5774                                                  ModestWindow *window)
5775 {
5776         g_return_if_fail (MODEST_IS_WINDOW (window));
5777
5778         /* Update dimmed */
5779         modest_ui_actions_check_menu_dimming_rules (window);
5780 }
5781
5782 void
5783 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
5784                                                      ModestWindow *window)
5785 {
5786         g_return_if_fail (MODEST_IS_WINDOW (window));
5787
5788         /* Update dimmed */
5789         modest_ui_actions_check_menu_dimming_rules (window);
5790 }
5791
5792 void
5793 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
5794                                                      ModestWindow *window)
5795 {
5796         g_return_if_fail (MODEST_IS_WINDOW (window));
5797
5798         /* Update dimmed */
5799         modest_ui_actions_check_menu_dimming_rules (window);
5800 }
5801
5802 void
5803 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
5804 {
5805         g_return_if_fail (MODEST_IS_WINDOW (window));
5806
5807         /* we check for low-mem; in that case, show a warning, and don't allow
5808          * searching
5809          */
5810         if (modest_platform_check_memory_low (window, TRUE))
5811                 return;
5812         
5813         modest_platform_show_search_messages (GTK_WINDOW (window));
5814 }
5815
5816 void     
5817 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
5818 {
5819         g_return_if_fail (MODEST_IS_WINDOW (win));
5820
5821
5822         /* we check for low-mem; in that case, show a warning, and don't allow
5823          * for the addressbook
5824          */
5825         if (modest_platform_check_memory_low (win, TRUE))
5826                 return;
5827
5828
5829         modest_platform_show_addressbook (GTK_WINDOW (win));
5830 }
5831
5832
5833 void
5834 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
5835                                           ModestWindow *window)
5836 {
5837         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5838
5839         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
5840 }
5841
5842 static void 
5843 on_send_receive_finished (ModestMailOperation  *mail_op, 
5844                            gpointer user_data)
5845 {
5846         GtkWidget *header_view, *folder_view;
5847         TnyFolderStore *folder_store;
5848         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
5849
5850         /* Set send/receive operation finished */       
5851         modest_main_window_notify_send_receive_completed (main_win);
5852
5853         /* Don't refresh the current folder if there were any errors */
5854         if (modest_mail_operation_get_status (mail_op) !=
5855             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5856                 return;
5857         
5858         /* Refresh the current folder if we're viewing a window. We do
5859            this because the user won't be able to see the new mails in
5860            the selected folder after a Send&Receive because it only
5861            performs a poke_status, i.e, only the number of read/unread
5862            messages is updated, but the new headers are not
5863            downloaded */
5864         folder_view = modest_main_window_get_child_widget (main_win, 
5865                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5866         if (!folder_view)
5867                 return;
5868
5869         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5870         
5871         /* Do not need to refresh INBOX again because the
5872            update_account does it always automatically */
5873         if (folder_store && TNY_IS_FOLDER (folder_store) && 
5874             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
5875                 ModestMailOperation *refresh_op;
5876
5877                 header_view = modest_main_window_get_child_widget (main_win,
5878                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5879                 
5880                 /* We do not need to set the contents style
5881                    because it hasn't changed. We also do not
5882                    need to save the widget status. Just force
5883                    a refresh */
5884                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
5885                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
5886                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
5887                                                       folder_refreshed_cb, main_win);
5888                 g_object_unref (refresh_op);
5889         }
5890         
5891         if (folder_store)
5892                 g_object_unref (folder_store);
5893 }
5894
5895
5896 void 
5897 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
5898                                                 TnyHeader *header, 
5899                                                 TnyMsg *msg, 
5900                                                 GError *err, 
5901                                                 gpointer user_data)
5902 {
5903         const gchar* server_name = NULL;
5904         TnyTransportAccount *server_account;
5905         gchar *message = NULL;
5906
5907         /* Don't show anything if the user cancelled something or the send receive request is not
5908          * interactive */
5909         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
5910             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
5911                 return;
5912
5913
5914         /* Get the server name: */
5915         server_account = 
5916                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
5917         if (server_account)
5918                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));          
5919         else
5920                 g_return_if_reached ();
5921
5922         /* Show the appropriate message text for the GError: */
5923         switch (err->code) {
5924         case TNY_SERVICE_ERROR_CONNECT:
5925                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5926                 break;
5927         case TNY_SERVICE_ERROR_AUTHENTICATE:
5928                 message = g_strdup_printf (_("emev_ni_ui_smtp_authentication_fail_error"), server_name);
5929                 break;
5930         case TNY_SERVICE_ERROR_SEND:
5931                 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
5932                 break;
5933         case TNY_SERVICE_ERROR_UNAVAILABLE:
5934                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5935                 break;
5936         default:
5937                 g_warning ("%s: unexpected ERROR %d",
5938                            __FUNCTION__, err->code);
5939                 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
5940                 break;  
5941         }
5942         
5943         /* TODO if the username or the password where not defined we
5944            should show the Accounts Settings dialog or the Connection
5945            specific SMTP server window */
5946
5947         modest_platform_run_information_dialog (NULL, message, FALSE);
5948         g_free (message);
5949         g_object_unref (server_account);
5950 }
5951
5952 void
5953 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
5954                                                 gchar *msg_id, 
5955                                                 guint status,
5956                                                 gpointer user_data)
5957 {
5958         ModestMainWindow *main_window = NULL;
5959         ModestWindowMgr *mgr = NULL;
5960         GtkWidget *folder_view = NULL, *header_view = NULL;
5961         TnyFolderStore *selected_folder = NULL;
5962         TnyFolderType folder_type;
5963
5964         mgr = modest_runtime_get_window_mgr ();
5965         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
5966                                                                              FALSE));/* don't create */
5967         if (!main_window)
5968                 return;
5969
5970         /* Check if selected folder is OUTBOX */
5971         folder_view = modest_main_window_get_child_widget (main_window,
5972                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5973         header_view = modest_main_window_get_child_widget (main_window,
5974                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5975
5976         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5977         if (!TNY_IS_FOLDER (selected_folder)) 
5978                 goto frees;
5979
5980         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
5981 #if GTK_CHECK_VERSION(2, 8, 0) 
5982         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
5983         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
5984                 GtkTreeViewColumn *tree_column;
5985
5986                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
5987                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
5988                 gtk_tree_view_column_queue_resize (tree_column);
5989         }
5990 #else
5991         gtk_widget_queue_draw (header_view);
5992 #endif          
5993
5994         /* Rerun dimming rules, because the message could become deletable for example */
5995         modest_window_check_dimming_rules_group (MODEST_WINDOW (main_window), 
5996                                                  MODEST_DIMMING_RULES_TOOLBAR);
5997         modest_window_check_dimming_rules_group (MODEST_WINDOW (main_window), 
5998                                                  MODEST_DIMMING_RULES_MENU);
5999         
6000         /* Free */
6001  frees:
6002         if (selected_folder != NULL)
6003                 g_object_unref (selected_folder);
6004 }
6005
6006 void 
6007 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
6008                                                TnyAccount *account)
6009 {
6010         ModestTransportStoreProtocol proto;
6011         const gchar *proto_name;
6012         gchar *error_note = NULL;
6013         
6014         proto_name = tny_account_get_proto (account);
6015         proto = modest_protocol_info_get_transport_store_protocol (proto_name);
6016         
6017         switch (proto) {
6018         case MODEST_PROTOCOL_STORE_POP:
6019                 error_note = g_strdup_printf (_("emev_ni_ui_pop3_msg_connect_error"), 
6020                                               tny_account_get_hostname (account));
6021                 break;
6022         case MODEST_PROTOCOL_STORE_IMAP:
6023                 error_note = g_strdup_printf (_("emev_ni_ui_imap_connect_server_error"), 
6024                                               tny_account_get_hostname (account));
6025                 break;
6026         case MODEST_PROTOCOL_STORE_MAILDIR:
6027         case MODEST_PROTOCOL_STORE_MBOX:
6028                 error_note = g_strdup (_("emev_nc_mailbox_notavailable"));
6029                 break;
6030         default:
6031                 g_warning ("%s: This should not be reached", __FUNCTION__);
6032         }
6033
6034         if (error_note) {
6035                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
6036                 g_free (error_note);
6037         }
6038 }
6039
6040 gchar *
6041 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
6042 {
6043         gchar *msg = NULL;
6044         TnyFolderStore *folder = NULL;
6045         TnyAccount *account = NULL;
6046         ModestTransportStoreProtocol proto;
6047         TnyHeader *header = NULL;
6048
6049         if (MODEST_IS_MAIN_WINDOW (win)) {
6050                 GtkWidget *header_view;
6051                 TnyList* headers = NULL;
6052                 TnyIterator *iter;
6053                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
6054                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6055                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6056                 if (!headers || tny_list_get_length (headers) == 0) {
6057                         if (headers)
6058                                 g_object_unref (headers);
6059                         return NULL;
6060                 }
6061                 iter = tny_list_create_iterator (headers);
6062                 header = TNY_HEADER (tny_iterator_get_current (iter));
6063                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6064                 g_object_unref (iter);
6065                 g_object_unref (headers);
6066         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
6067                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
6068                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6069         }
6070
6071         /* Get the account type */
6072         account = tny_folder_get_account (TNY_FOLDER (folder));
6073         proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
6074         if (proto == MODEST_PROTOCOL_STORE_POP) {
6075                 msg = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
6076         } else if (proto == MODEST_PROTOCOL_STORE_IMAP) {
6077                 gchar *subject;
6078                 subject = tny_header_dup_subject (header);
6079                 msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"), 
6080                                        subject);
6081                 g_free (subject);
6082         } else {
6083                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
6084         }
6085
6086         /* Frees */
6087         g_object_unref (account);
6088         g_object_unref (folder);
6089         g_object_unref (header);
6090
6091         return msg;
6092 }