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