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