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