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