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