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