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