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