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