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