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