* Fixes NB#93489, remove the login cancelled message
[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 #ifndef MODEST_TOOLKIT_HILDON2
3777                         /* Set parent to NULL or the banner will disappear with its parent dialog */
3778                         modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
3779 #endif
3780                         completed = TRUE;
3781                         if (username)
3782                                 *username = NULL;
3783                         if (password)
3784                                 *password = NULL;
3785                         if (cancel)
3786                                 *cancel   = TRUE;
3787                 }
3788         }
3789
3790 /* This is not in the Maemo UI spec:
3791         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
3792                 *remember = TRUE;
3793         else
3794                 *remember = FALSE;
3795 */
3796
3797         g_free (initial_username);
3798         gtk_widget_destroy (dialog);
3799         g_slice_free (PasswordDialogFields, fields);
3800         
3801         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
3802 }
3803
3804 void
3805 modest_ui_actions_on_cut (GtkAction *action,
3806                           ModestWindow *window)
3807 {
3808         GtkWidget *focused_widget;
3809         GtkClipboard *clipboard;
3810
3811         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3812         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3813         if (GTK_IS_EDITABLE (focused_widget)) {
3814                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3815                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3816                 gtk_clipboard_store (clipboard);
3817         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3818                 GtkTextBuffer *buffer;
3819
3820                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3821                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3822                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3823                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3824                         gtk_clipboard_store (clipboard);
3825                 }
3826         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3827                 TnyList *header_list = modest_header_view_get_selected_headers (
3828                                 MODEST_HEADER_VIEW (focused_widget));
3829                 gboolean continue_download = FALSE;
3830                 gint num_of_unc_msgs;
3831
3832                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3833
3834                 if (num_of_unc_msgs) {
3835                         TnyAccount *account = get_account_from_header_list (header_list);
3836                         if (account) {
3837                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3838                                 g_object_unref (account);
3839                         }
3840                 }
3841
3842                 if (num_of_unc_msgs == 0 || continue_download) {
3843 /*                      modest_platform_information_banner (
3844                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
3845                         modest_header_view_cut_selection (
3846                                         MODEST_HEADER_VIEW (focused_widget));
3847                 }
3848
3849                 g_object_unref (header_list);
3850         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3851                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3852         }
3853 }
3854
3855 void
3856 modest_ui_actions_on_copy (GtkAction *action,
3857                            ModestWindow *window)
3858 {
3859         GtkClipboard *clipboard;
3860         GtkWidget *focused_widget;
3861         gboolean copied = TRUE;
3862
3863         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3864         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3865
3866         if (GTK_IS_LABEL (focused_widget)) {
3867                 gchar *selection;
3868                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
3869                 gtk_clipboard_set_text (clipboard, selection, -1);
3870                 g_free (selection);
3871                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3872                 gtk_clipboard_store (clipboard);
3873         } else if (GTK_IS_EDITABLE (focused_widget)) {
3874                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3875                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3876                 gtk_clipboard_store (clipboard);
3877         } else if (GTK_IS_HTML (focused_widget)) {
3878                 const gchar *sel;
3879                 int len = -1;
3880                 sel = gtk_html_get_selection_html (GTK_HTML (focused_widget), &len);
3881                 if ((sel == NULL) || (sel[0] == '\0')) {
3882                         copied = FALSE;
3883                 } else {
3884                         gtk_html_copy (GTK_HTML (focused_widget));
3885                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3886                         gtk_clipboard_store (clipboard);
3887                 }
3888         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3889                 GtkTextBuffer *buffer;
3890                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3891                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3892                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
3893                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3894                         gtk_clipboard_store (clipboard);
3895                 }
3896         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3897                 TnyList *header_list = modest_header_view_get_selected_headers (
3898                                 MODEST_HEADER_VIEW (focused_widget));
3899                 gboolean continue_download = FALSE;
3900                 gint num_of_unc_msgs;
3901
3902                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3903
3904                 if (num_of_unc_msgs) {
3905                         TnyAccount *account = get_account_from_header_list (header_list);
3906                         if (account) {
3907                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3908                                 g_object_unref (account);
3909                         }
3910                 }
3911
3912                 if (num_of_unc_msgs == 0 || continue_download) {
3913                         modest_platform_information_banner (
3914                                         NULL, NULL, _CS("mcen_ib_getting_items"));
3915                         modest_header_view_copy_selection (
3916                                         MODEST_HEADER_VIEW (focused_widget));
3917                 } else
3918                         copied = FALSE;
3919
3920                 g_object_unref (header_list);
3921
3922         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3923                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3924         }
3925
3926         /* Show information banner if there was a copy to clipboard */
3927         if(copied)
3928                 modest_platform_information_banner (
3929                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3930 }
3931
3932 void
3933 modest_ui_actions_on_undo (GtkAction *action,
3934                            ModestWindow *window)
3935 {
3936         ModestEmailClipboard *clipboard = NULL;
3937
3938         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3939                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3940         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3941                 /* Clear clipboard source */
3942                 clipboard = modest_runtime_get_email_clipboard ();
3943                 modest_email_clipboard_clear (clipboard);               
3944         }
3945         else {
3946                 g_return_if_reached ();
3947         }
3948 }
3949
3950 void
3951 modest_ui_actions_on_redo (GtkAction *action,
3952                            ModestWindow *window)
3953 {
3954         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3955                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3956         }
3957         else {
3958                 g_return_if_reached ();
3959         }
3960 }
3961
3962
3963 static void
3964 destroy_information_note (ModestMailOperation *mail_op, 
3965                           gpointer user_data)
3966 {
3967         /* destroy information note */
3968         gtk_widget_destroy (GTK_WIDGET(user_data));
3969 }
3970
3971 static void
3972 destroy_folder_information_note (ModestMailOperation *mail_op, 
3973                                  TnyFolder *new_folder,
3974                                  gpointer user_data)
3975 {
3976         /* destroy information note */
3977         gtk_widget_destroy (GTK_WIDGET(user_data));
3978 }
3979
3980
3981 static void
3982 paste_as_attachment_free (gpointer data)
3983 {
3984         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3985
3986         if (helper->banner) {
3987                 gtk_widget_destroy (helper->banner);
3988                 g_object_unref (helper->banner);
3989         }
3990         g_free (helper);
3991 }
3992
3993 static void
3994 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3995                             TnyHeader *header,
3996                             TnyMsg *msg,
3997                             gpointer userdata)
3998 {
3999         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
4000         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
4001
4002         if (msg == NULL)
4003                 return;
4004
4005         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
4006         
4007 }
4008
4009 void
4010 modest_ui_actions_on_paste (GtkAction *action,
4011                             ModestWindow *window)
4012 {
4013         GtkWidget *focused_widget = NULL;
4014         GtkWidget *inf_note = NULL;
4015         ModestMailOperation *mail_op = NULL;
4016
4017         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4018         if (GTK_IS_EDITABLE (focused_widget)) {
4019                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
4020         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4021                 ModestEmailClipboard *e_clipboard = NULL;
4022                 e_clipboard = modest_runtime_get_email_clipboard ();
4023                 if (modest_email_clipboard_cleared (e_clipboard)) {
4024                         GtkTextBuffer *buffer;
4025                         GtkClipboard *clipboard;
4026
4027                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4028                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4029                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
4030                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4031                         ModestMailOperation *mail_op;
4032                         TnyFolder *src_folder = NULL;
4033                         TnyList *data = NULL;
4034                         gboolean delete;
4035                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
4036                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
4037                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4038                                                                            _CS("ckct_nw_pasting"));
4039                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
4040                         mail_op = modest_mail_operation_new (G_OBJECT (window));
4041                         if (helper->banner != NULL) {
4042                                 g_object_ref (G_OBJECT (helper->banner));
4043                                 gtk_widget_show (GTK_WIDGET (helper->banner));
4044                         }
4045
4046                         if (data != NULL) {
4047                                 modest_mail_operation_get_msgs_full (mail_op, 
4048                                                                      data,
4049                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
4050                                                                      helper,
4051                                                                      paste_as_attachment_free);
4052                         }
4053                         /* Free */
4054                         if (data) 
4055                                 g_object_unref (data);
4056                         if (src_folder) 
4057                                 g_object_unref (src_folder);
4058
4059                 }
4060         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4061                 ModestEmailClipboard *clipboard = NULL;
4062                 TnyFolder *src_folder = NULL;
4063                 TnyFolderStore *folder_store = NULL;
4064                 TnyList *data = NULL;           
4065                 gboolean delete = FALSE;
4066                 
4067                 /* Check clipboard source */
4068                 clipboard = modest_runtime_get_email_clipboard ();
4069                 if (modest_email_clipboard_cleared (clipboard)) 
4070                         return;
4071                 
4072                 /* Get elements to paste */
4073                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
4074
4075                 /* Create a new mail operation */
4076                 mail_op = modest_mail_operation_new (G_OBJECT(window));
4077                 
4078                 /* Get destination folder */
4079                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
4080
4081                 /* transfer messages  */
4082                 if (data != NULL) {
4083                         gint response = 0;
4084
4085                         /* Ask for user confirmation */
4086                         response = 
4087                                 modest_ui_actions_msgs_move_to_confirmation (window, 
4088                                                                              TNY_FOLDER (folder_store), 
4089                                                                              delete,
4090                                                                              data);
4091                         
4092                         if (response == GTK_RESPONSE_OK) {
4093                                 /* Launch notification */
4094                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
4095                                                                              _CS("ckct_nw_pasting"));
4096                                 if (inf_note != NULL)  {
4097                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4098                                         gtk_widget_show (GTK_WIDGET(inf_note));
4099                                 }
4100
4101                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4102                                 modest_mail_operation_xfer_msgs (mail_op, 
4103                                                                  data,
4104                                                                  TNY_FOLDER (folder_store),
4105                                                                  delete,
4106                                                                  destroy_information_note,
4107                                                                  inf_note);                             
4108                         } else {
4109                                 g_object_unref (mail_op);
4110                         }
4111                         
4112                 } else if (src_folder != NULL) {                        
4113                         /* Launch notification */
4114                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
4115                                                                      _CS("ckct_nw_pasting"));
4116                         if (inf_note != NULL)  {
4117                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4118                                 gtk_widget_show (GTK_WIDGET(inf_note));
4119                         }
4120                         
4121                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4122                         modest_mail_operation_xfer_folder (mail_op, 
4123                                                            src_folder,
4124                                                            folder_store,
4125                                                            delete,
4126                                                            destroy_folder_information_note,
4127                                                            inf_note);
4128                 }
4129
4130                 /* Free */
4131                 if (data != NULL) 
4132                         g_object_unref (data);
4133                 if (src_folder != NULL) 
4134                         g_object_unref (src_folder);
4135                 if (folder_store != NULL) 
4136                         g_object_unref (folder_store);
4137         }
4138 }
4139
4140
4141 void
4142 modest_ui_actions_on_select_all (GtkAction *action,
4143                                  ModestWindow *window)
4144 {
4145         GtkWidget *focused_widget;
4146
4147         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4148         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
4149                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
4150         } else if (GTK_IS_LABEL (focused_widget)) {
4151                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
4152         } else if (GTK_IS_EDITABLE (focused_widget)) {
4153                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
4154         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4155                 GtkTextBuffer *buffer;
4156                 GtkTextIter start, end;
4157
4158                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4159                 gtk_text_buffer_get_start_iter (buffer, &start);
4160                 gtk_text_buffer_get_end_iter (buffer, &end);
4161                 gtk_text_buffer_select_range (buffer, &start, &end);
4162         } else if (GTK_IS_HTML (focused_widget)) {
4163                 gtk_html_select_all (GTK_HTML (focused_widget));
4164         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4165                 GtkWidget *header_view = focused_widget;
4166                 GtkTreeSelection *selection = NULL;
4167                 
4168                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
4169                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4170                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4171                 }
4172                                 
4173                 /* Disable window dimming management */
4174                 modest_window_disable_dimming (MODEST_WINDOW(window));
4175                 
4176                 /* Select all messages */
4177                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
4178                 gtk_tree_selection_select_all (selection);
4179
4180                 /* Set focuse on header view */
4181                 gtk_widget_grab_focus (header_view);
4182
4183                 /* Enable window dimming management */
4184                 modest_window_enable_dimming (MODEST_WINDOW(window));
4185                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
4186                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
4187         }
4188
4189 }
4190
4191 void
4192 modest_ui_actions_on_mark_as_read (GtkAction *action,
4193                                    ModestWindow *window)
4194 {       
4195         g_return_if_fail (MODEST_IS_WINDOW(window));
4196                 
4197         /* Mark each header as read */
4198         do_headers_action (window, headers_action_mark_as_read, NULL);
4199 }
4200
4201 void
4202 modest_ui_actions_on_mark_as_unread (GtkAction *action,
4203                                      ModestWindow *window)
4204 {       
4205         g_return_if_fail (MODEST_IS_WINDOW(window));
4206                 
4207         /* Mark each header as read */
4208         do_headers_action (window, headers_action_mark_as_unread, NULL);
4209 }
4210
4211 void
4212 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
4213                                   GtkRadioAction *selected,
4214                                   ModestWindow *window)
4215 {
4216         gint value;
4217
4218         value = gtk_radio_action_get_current_value (selected);
4219         if (MODEST_IS_WINDOW (window)) {
4220                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
4221         }
4222 }
4223
4224 void
4225 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
4226                                                GtkRadioAction *selected,
4227                                                ModestWindow *window)
4228 {
4229         TnyHeaderFlags flags;
4230         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4231
4232         flags = gtk_radio_action_get_current_value (selected);
4233         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
4234 }
4235
4236 void
4237 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
4238                                                   GtkRadioAction *selected,
4239                                                   ModestWindow *window)
4240 {
4241         gint file_format;
4242
4243         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4244
4245         file_format = gtk_radio_action_get_current_value (selected);
4246         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
4247 }
4248
4249
4250 void
4251 modest_ui_actions_on_zoom_plus (GtkAction *action,
4252                                 ModestWindow *window)
4253 {
4254         g_return_if_fail (MODEST_IS_WINDOW (window));
4255
4256         modest_window_zoom_plus (MODEST_WINDOW (window));
4257 }
4258
4259 void     
4260 modest_ui_actions_on_zoom_minus (GtkAction *action,
4261                                  ModestWindow *window)
4262 {
4263         g_return_if_fail (MODEST_IS_WINDOW (window));
4264
4265         modest_window_zoom_minus (MODEST_WINDOW (window));
4266 }
4267
4268 void     
4269 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
4270                                            ModestWindow *window)
4271 {
4272         ModestWindowMgr *mgr;
4273         gboolean fullscreen, active;
4274         g_return_if_fail (MODEST_IS_WINDOW (window));
4275
4276         mgr = modest_runtime_get_window_mgr ();
4277
4278         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4279         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4280
4281         if (active != fullscreen) {
4282                 modest_window_mgr_set_fullscreen_mode (mgr, active);
4283 #ifndef MODEST_TOOLKIT_HILDON2
4284                 gtk_window_present (GTK_WINDOW (window));
4285 #endif
4286         }
4287 }
4288
4289 void
4290 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4291                                         ModestWindow *window)
4292 {
4293         ModestWindowMgr *mgr;
4294         gboolean fullscreen;
4295
4296         g_return_if_fail (MODEST_IS_WINDOW (window));
4297
4298         mgr = modest_runtime_get_window_mgr ();
4299         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4300         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4301
4302 #ifndef MODEST_TOOLKIT_HILDON2
4303         gtk_window_present (GTK_WINDOW (window));
4304 #endif
4305 }
4306
4307 /* 
4308  * Used by modest_ui_actions_on_details to call do_headers_action 
4309  */
4310 static void
4311 headers_action_show_details (TnyHeader *header, 
4312                              ModestWindow *window,
4313                              gpointer user_data)
4314
4315 {
4316         modest_platform_run_header_details_dialog (GTK_WINDOW (window), header);
4317 }
4318
4319 /*
4320  * Show the header details in a ModestDetailsDialog widget
4321  */
4322 void     
4323 modest_ui_actions_on_details (GtkAction *action, 
4324                               ModestWindow *win)
4325 {
4326         TnyList * headers_list;
4327         TnyIterator *iter;
4328         TnyHeader *header;              
4329
4330         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4331                 TnyMsg *msg;
4332
4333                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4334                 if (!msg)
4335                         return;
4336                 g_object_unref (msg);           
4337
4338                 headers_list = get_selected_headers (win);
4339                 if (!headers_list)
4340                         return;
4341
4342                 iter = tny_list_create_iterator (headers_list);
4343
4344                 header = TNY_HEADER (tny_iterator_get_current (iter));
4345                 if (header) {
4346                         headers_action_show_details (header, win, NULL);
4347                         g_object_unref (header);
4348                 }
4349
4350                 g_object_unref (iter);
4351                 g_object_unref (headers_list);
4352
4353         } else if (MODEST_IS_MAIN_WINDOW (win)) {
4354                 GtkWidget *folder_view, *header_view;
4355
4356                 /* Check which widget has the focus */
4357                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4358                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4359                 if (gtk_widget_is_focus (folder_view)) {
4360                         TnyFolderStore *folder_store
4361                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4362                         if (!folder_store) {
4363                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4364                                 return; 
4365                         }
4366                         /* Show only when it's a folder */
4367                         /* This function should not be called for account items, 
4368                          * because we dim the menu item for them. */
4369                         if (TNY_IS_FOLDER (folder_store)) {
4370                                 modest_platform_run_folder_details_dialog (GTK_WINDOW (win), 
4371                                                                            TNY_FOLDER (folder_store));
4372                         }
4373
4374                         g_object_unref (folder_store);
4375
4376                 } else {
4377                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4378                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4379                         /* Show details of each header */
4380                         do_headers_action (win, headers_action_show_details, header_view);
4381                 }
4382         }
4383 }
4384
4385 void     
4386 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4387                                      ModestMsgEditWindow *window)
4388 {
4389         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4390
4391         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4392 }
4393
4394 void     
4395 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4396                                       ModestMsgEditWindow *window)
4397 {
4398         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4399
4400         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4401 }
4402
4403 void
4404 modest_ui_actions_toggle_folders_view (GtkAction *action, 
4405                                        ModestMainWindow *main_window)
4406 {
4407         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4408
4409         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4410                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4411         else
4412                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4413 }
4414
4415 void 
4416 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
4417                                      ModestWindow *window)
4418 {
4419         gboolean active, fullscreen = FALSE;
4420         ModestWindowMgr *mgr;
4421
4422         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4423
4424         /* Check if we want to toggle the toolbar view in fullscreen
4425            or normal mode */
4426         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
4427                      "ViewShowToolbarFullScreen")) {
4428                 fullscreen = TRUE;
4429         }
4430
4431         /* Toggle toolbar */
4432         mgr = modest_runtime_get_window_mgr ();
4433         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4434 }
4435
4436 void     
4437 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4438                                            ModestMsgEditWindow *window)
4439 {
4440         modest_msg_edit_window_select_font (window);
4441 }
4442
4443
4444 void
4445 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4446                                                   const gchar *display_name,
4447                                                   GtkWindow *window)
4448 {
4449         /* don't update the display name if it was already set;
4450          * updating the display name apparently is expensive */
4451         const gchar* old_name = gtk_window_get_title (window);
4452
4453         if (display_name == NULL)
4454                 display_name = " ";
4455
4456         if (old_name && display_name && strcmp (old_name, display_name) == 0)
4457                 return; /* don't do anything */
4458
4459         /* This is usually used to change the title of the main window, which
4460          * is the one that holds the folder view. Note that this change can
4461          * happen even when the widget doesn't have the focus. */
4462         gtk_window_set_title (window, display_name);
4463
4464 }
4465
4466 void
4467 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4468 {
4469         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4470         modest_msg_edit_window_select_contacts (window);
4471 }
4472
4473 void
4474 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4475 {
4476         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4477         modest_msg_edit_window_check_names (window, FALSE);
4478 }
4479
4480 static void
4481 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
4482 {
4483         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
4484                                          GTK_WIDGET (user_data));
4485 }
4486
4487 /*
4488  * This function is used to track changes in the selection of the
4489  * folder view that is inside the "move to" dialog to enable/disable
4490  * the OK button because we do not want the user to select a disallowed
4491  * destination for a folder.
4492  * The user also not desired to be able to use NEW button on items where
4493  * folder creation is not possibel.
4494  */
4495 static void
4496 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4497                                             TnyFolderStore *folder_store,
4498                                             gboolean selected,
4499                                             gpointer user_data)
4500 {
4501         GtkWidget *dialog = NULL;
4502         GtkWidget *ok_button = NULL, *new_button = NULL;
4503         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4504         gboolean moving_folder = FALSE;
4505         gboolean is_local_account = TRUE;
4506         GtkWidget *folder_view = NULL;
4507         ModestTnyFolderRules rules;
4508
4509         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4510         
4511         if (!selected)
4512                 return;
4513         
4514         /* Get the OK button */
4515         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4516         if (!dialog)
4517                 return;
4518
4519         ok_button = g_object_get_data (G_OBJECT (dialog), MOVE_FOLDER_OK_BUTTON);
4520         new_button = g_object_get_data (G_OBJECT (dialog), MOVE_FOLDER_NEW_BUTTON);
4521
4522         /* check if folder_store is an remote account */
4523         if (TNY_IS_ACCOUNT (folder_store)) {
4524                 TnyAccount *local_account = NULL;
4525                 TnyAccount *mmc_account = NULL;
4526                 ModestTnyAccountStore *account_store = NULL;
4527
4528                 account_store = modest_runtime_get_account_store ();
4529                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4530                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4531
4532                 if ((gpointer) local_account != (gpointer) folder_store &&
4533                     (gpointer) mmc_account != (gpointer) folder_store) {
4534                         ModestProtocolType proto;
4535                         proto = modest_tny_account_get_protocol_type (TNY_ACCOUNT (folder_store));
4536                         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
4537                                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
4538                         }
4539                         is_local_account = FALSE;
4540                         /* New button should be dimmed on remote
4541                            POP account root */
4542                         new_sensitive = (modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
4543                                                                                          proto,
4544                                                                                          MODEST_PROTOCOL_REGISTRY_STORE_HAS_FOLDERS));
4545                 }
4546                 g_object_unref (local_account);
4547
4548                 /* It could not exist */
4549                 if (mmc_account)
4550                         g_object_unref (mmc_account);
4551         }
4552
4553         /* Check the target folder rules */
4554         if (TNY_IS_FOLDER (folder_store)) {
4555                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
4556                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
4557                         ok_sensitive = FALSE;
4558                         new_sensitive = FALSE;
4559                         goto end;
4560                 }
4561         }
4562
4563         /* Check if we're moving a folder */
4564         if (MODEST_IS_MAIN_WINDOW (user_data)) {
4565                 /* Get the widgets */
4566                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
4567                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4568                 if (gtk_widget_is_focus (folder_view))
4569                         moving_folder = TRUE;
4570         }
4571
4572         if (moving_folder) {
4573                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
4574
4575                 /* Get the folder to move */
4576                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4577                 
4578                 /* Check that we're not moving to the same folder */
4579                 if (TNY_IS_FOLDER (moved_folder)) {
4580                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
4581                         if (parent == folder_store)
4582                                 ok_sensitive = FALSE;
4583                         g_object_unref (parent);
4584                 } 
4585
4586                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
4587                         /* Do not allow to move to an account unless it's the
4588                            local folders account */
4589                         if (!is_local_account)
4590                                 ok_sensitive = FALSE;
4591                 } 
4592
4593                 if (ok_sensitive && (moved_folder == folder_store)) {
4594                         /* Do not allow to move to itself */
4595                         ok_sensitive = FALSE;
4596                 }
4597                 g_object_unref (moved_folder);
4598         } else {
4599                 TnyFolder *src_folder = NULL;
4600
4601                 /* Moving a message */
4602                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
4603
4604                         TnyHeader *header = NULL;
4605                         header = modest_msg_view_window_get_header
4606                                 (MODEST_MSG_VIEW_WINDOW (user_data));
4607                         if (!TNY_IS_HEADER(header))
4608                                 g_warning ("%s: could not get source header", __FUNCTION__);
4609                         else
4610                                 src_folder = tny_header_get_folder (header);
4611
4612                         if (header)
4613                                 g_object_unref (header);
4614                 } else {
4615                         src_folder = 
4616                                 TNY_FOLDER (modest_folder_view_get_selected
4617                                             (MODEST_FOLDER_VIEW (folder_view)));
4618                 }
4619
4620                 if (TNY_IS_FOLDER(src_folder)) {
4621                         /* Do not allow to move the msg to the same folder */
4622                         /* Do not allow to move the msg to an account */
4623                         if ((gpointer) src_folder == (gpointer) folder_store ||
4624                             TNY_IS_ACCOUNT (folder_store))
4625                                 ok_sensitive = FALSE;
4626                         g_object_unref (src_folder);
4627                 } else
4628                         g_warning ("%s: could not get source folder", __FUNCTION__);
4629         }
4630
4631  end:
4632         /* Set sensitivity of the OK button */
4633         gtk_widget_set_sensitive (ok_button, ok_sensitive);
4634         /* Set sensitivity of the NEW button */
4635         gtk_widget_set_sensitive (new_button, new_sensitive);
4636 }
4637
4638
4639 #define MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
4640
4641 static GtkWidget*
4642 get_folder_view_from_move_to_dialog (GtkWidget *move_to_dialog)
4643 {
4644         return GTK_WIDGET(g_object_get_data (G_OBJECT(move_to_dialog),
4645                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4646 }
4647
4648 static GtkWidget*
4649 create_move_to_dialog (GtkWindow *win,
4650                        GtkWidget *folder_view,
4651                        GtkWidget **tree_view)
4652 {
4653         GtkWidget *dialog;
4654 #ifdef MODEST_TOOLKIT_HILDON2
4655         GtkWidget *pannable;
4656 #else
4657         GtkWidget *scroll;
4658 #endif
4659         GtkWidget *new_button, *ok_button;
4660
4661         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
4662                                               GTK_WINDOW (win),
4663                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
4664                                               NULL);
4665
4666 #ifndef MODEST_TOOLKIT_GTK
4667         ok_button = gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
4668         /* We do this manually so GTK+ does not associate a response ID for
4669          * the button. */
4670         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
4671         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
4672         gtk_widget_show (new_button);
4673 #ifndef MODEST_TOOLKIT_HILDON2
4674         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
4675 #endif
4676 #else
4677         /* We do this manually so GTK+ does not associate a response ID for
4678          * the button. */
4679         new_button = gtk_button_new_with_label (_("mcen_ti_new_folder"));
4680         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
4681         gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (GTK_DIALOG (dialog)->action_area), new_button, TRUE);
4682         gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
4683         ok_button = gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
4684         gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
4685         gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 24);
4686 #endif
4687         g_object_set_data (G_OBJECT (dialog), MOVE_FOLDER_OK_BUTTON, ok_button);
4688         g_object_set_data (G_OBJECT (dialog), MOVE_FOLDER_NEW_BUTTON, new_button);
4689
4690         /* Create scrolled window */
4691 #ifdef MODEST_TOOLKIT_HILDON2
4692         pannable = hildon_pannable_area_new ();
4693 #else
4694         scroll = gtk_scrolled_window_new (NULL, NULL);
4695         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
4696                                          GTK_POLICY_AUTOMATIC,
4697                                          GTK_POLICY_AUTOMATIC);
4698 #endif
4699
4700 #ifdef MODEST_TOOLKIT_GTK
4701         gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_IN);
4702 #endif
4703
4704         /* Create folder view */
4705         *tree_view = modest_platform_create_folder_view (NULL);
4706
4707         /* Track changes in the selection to
4708          * disable the OK button whenever "Move to" is not possible
4709          * disbale NEW button whenever New is not possible */
4710         g_signal_connect (*tree_view,
4711                           "folder_selection_changed",
4712                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
4713                           win);
4714
4715         /* Listen to clicks on New button */
4716         g_signal_connect (G_OBJECT (new_button), 
4717                           "clicked", 
4718                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
4719                           *tree_view);
4720
4721         /* It could happen that we're trying to move a message from a
4722            window (msg window for example) after the main window was
4723            closed, so we can not just get the model of the folder
4724            view */
4725         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
4726                 const gchar *visible_id = NULL;
4727
4728                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4729                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4730                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
4731                                                MODEST_FOLDER_VIEW(*tree_view));
4732
4733                 visible_id = 
4734                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
4735
4736                 /* Show the same account than the one that is shown in the main window */
4737                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
4738                                                                              visible_id);
4739         } else {
4740                 const gchar *active_account_name = NULL;
4741                 ModestAccountMgr *mgr = NULL;
4742                 ModestAccountSettings *settings = NULL;
4743                 ModestServerAccountSettings *store_settings = NULL;
4744
4745                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4746                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4747                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
4748                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
4749
4750                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
4751                 mgr = modest_runtime_get_account_mgr ();
4752                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
4753
4754                 if (settings) {
4755                         const gchar *store_account_name;
4756                         store_settings = modest_account_settings_get_store_settings (settings);
4757                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
4758
4759                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
4760                                                                                      store_account_name);
4761                         g_object_unref (store_settings);
4762                         g_object_unref (settings);
4763                 }
4764         }
4765
4766         /* we keep a pointer to the embedded folder view, so we can retrieve it with
4767          *   get_folder_view_from_move_to_dialog 
4768          * (see above) later (needed for focus handling) 
4769          */
4770         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, *tree_view);
4771
4772         
4773         /* Hide special folders */
4774         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
4775
4776 #ifdef MODEST_TOOLKIT_HILDON2
4777         gtk_container_add (GTK_CONTAINER (pannable), *tree_view);
4778         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
4779                             pannable, TRUE, TRUE, 0);
4780 #else
4781         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
4782         /* Add scroll to dialog */
4783         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
4784                             scroll, TRUE, TRUE, 0);
4785 #endif
4786
4787
4788         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4789 #ifndef MODEST_TOOLKIT_GTK
4790         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
4791 #else
4792         gtk_window_set_default_size (GTK_WINDOW (dialog), 600, 400);
4793 #endif
4794
4795         return dialog;
4796 }
4797
4798
4799
4800 /*
4801  * Shows a confirmation dialog to the user when we're moving messages
4802  * from a remote server to the local storage. Returns the dialog
4803  * response. If it's other kind of movement then it always returns
4804  * GTK_RESPONSE_OK
4805  *
4806  * This one is used by the next functions:
4807  *      modest_ui_actions_on_paste                      - commented out
4808  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4809  */
4810 gint
4811 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4812                                              TnyFolder *dest_folder,
4813                                              gboolean delete,
4814                                              TnyList *headers)
4815 {
4816         gint response = GTK_RESPONSE_OK;
4817         TnyAccount *account = NULL;
4818         TnyFolder *src_folder = NULL;
4819         TnyIterator *iter = NULL;
4820         TnyHeader *header = NULL;
4821
4822         /* return with OK if the destination is a remote folder */
4823         if (modest_tny_folder_is_remote_folder (dest_folder))
4824                 return GTK_RESPONSE_OK;
4825
4826         /* Get source folder */
4827         iter = tny_list_create_iterator (headers);
4828         header = TNY_HEADER (tny_iterator_get_current (iter));
4829         if (header) {
4830                 src_folder = tny_header_get_folder (header);
4831                 g_object_unref (header);
4832         }
4833         g_object_unref (iter);
4834
4835         /* if no src_folder, message may be an attahcment */
4836         if (src_folder == NULL) 
4837                 return GTK_RESPONSE_CANCEL;
4838
4839         /* If the source is a local or MMC folder */
4840         if (!modest_tny_folder_is_remote_folder (src_folder)) {
4841                 g_object_unref (src_folder);
4842                 return GTK_RESPONSE_OK;
4843         }
4844
4845         /* Get the account */
4846         account = tny_folder_get_account (src_folder);
4847
4848         /* now if offline we ask the user */
4849         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4850                 response = GTK_RESPONSE_OK;
4851         else
4852                 response = GTK_RESPONSE_CANCEL;
4853
4854         /* Frees */
4855         g_object_unref (src_folder);
4856         g_object_unref (account);
4857
4858         return response;
4859 }
4860
4861 static void
4862 move_to_helper_destroyer (gpointer user_data)
4863 {
4864         MoveToHelper *helper = (MoveToHelper *) user_data;
4865
4866         /* Close the "Pasting" information banner */
4867         if (helper->banner) {
4868                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
4869                 g_object_unref (helper->banner);
4870         }
4871         if (gtk_tree_row_reference_valid (helper->reference)) {
4872                 gtk_tree_row_reference_free (helper->reference);
4873                 helper->reference = NULL;
4874         }
4875         g_free (helper);
4876 }
4877
4878 static void
4879 move_to_cb (ModestMailOperation *mail_op, 
4880             gpointer user_data)
4881 {
4882         MoveToHelper *helper = (MoveToHelper *) user_data;
4883
4884         /* Note that the operation could have failed, in that case do
4885            nothing */
4886         if (modest_mail_operation_get_status (mail_op) == 
4887             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4888
4889                 GObject *object = modest_mail_operation_get_source (mail_op);
4890                 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4891                         ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4892
4893                         if (!modest_msg_view_window_select_next_message (self) &&
4894                             !modest_msg_view_window_select_previous_message (self)) {
4895                                 /* No more messages to view, so close this window */
4896                                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4897                         }
4898                 } else if (MODEST_IS_MAIN_WINDOW (object) && 
4899                            gtk_tree_row_reference_valid (helper->reference)) {
4900                         GtkWidget *header_view;
4901                         GtkTreePath *path;
4902                         GtkTreeSelection *sel;
4903
4904                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4905                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4906                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4907                         path = gtk_tree_row_reference_get_path (helper->reference);
4908                         /* We need to unselect the previous one
4909                            because we could be copying instead of
4910                            moving */
4911                         gtk_tree_selection_unselect_all (sel);
4912                         gtk_tree_selection_select_path (sel, path);
4913                         gtk_tree_path_free (path);
4914                 }
4915                 g_object_unref (object);
4916         }
4917         /* Destroy the helper */
4918         move_to_helper_destroyer (helper);
4919 }
4920
4921 static void
4922 folder_move_to_cb (ModestMailOperation *mail_op, 
4923                    TnyFolder *new_folder,
4924                    gpointer user_data)
4925 {
4926         GtkWidget *folder_view;
4927         GObject *object;
4928
4929         object = modest_mail_operation_get_source (mail_op);
4930         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4931                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4932         g_object_ref (folder_view);
4933         g_object_unref (object);
4934         move_to_cb (mail_op, user_data);
4935         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
4936         g_object_unref (folder_view);
4937 }
4938
4939 static void
4940 msgs_move_to_cb (ModestMailOperation *mail_op, 
4941                  gpointer user_data)
4942 {
4943         move_to_cb (mail_op, user_data);
4944 }
4945
4946 void
4947 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
4948                                              gpointer user_data)
4949 {
4950         ModestWindow *main_window = NULL;
4951         
4952         /* Disable next automatic folder selection */
4953         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4954                                                          FALSE); /* don't create */
4955         if (main_window) {
4956                 GObject *win = NULL;
4957                 GtkWidget *folder_view = NULL;
4958         
4959                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4960                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
4961                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4962                 
4963                 if (user_data && TNY_IS_FOLDER (user_data)) {
4964                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), 
4965                                                           TNY_FOLDER (user_data), FALSE);
4966                 }
4967
4968                 /* Show notification dialog only if the main window exists */
4969                 win = modest_mail_operation_get_source (mail_op);
4970                 modest_platform_run_information_dialog ((GtkWindow *) win, 
4971                                                         _("mail_in_ui_folder_move_target_error"), 
4972                                                         FALSE);
4973                 if (win)
4974                         g_object_unref (win);
4975         }
4976 }
4977
4978 static void
4979 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
4980                        TnyHeader *header, 
4981                        gboolean canceled,
4982                        TnyMsg *msg, 
4983                        GError *err,
4984                        gpointer user_data)
4985 {
4986         TnyList *parts;
4987         TnyIterator *iter;
4988         gint pending_purges = 0;
4989         gboolean some_purged = FALSE;
4990         ModestWindow *win = MODEST_WINDOW (user_data);
4991         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4992
4993         /* If there was any error */
4994         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4995                 modest_window_mgr_unregister_header (mgr, header);
4996                 return;
4997         }
4998
4999         /* Once the message has been retrieved for purging, we check if
5000          * it's all ok for purging */
5001
5002         parts = tny_simple_list_new ();
5003         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
5004         iter = tny_list_create_iterator (parts);
5005
5006         while (!tny_iterator_is_done (iter)) {
5007                 TnyMimePart *part;
5008                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5009                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
5010                         if (tny_mime_part_is_purged (part))
5011                                 some_purged = TRUE;
5012                         else
5013                                 pending_purges++;
5014                 }
5015
5016                 if (part)
5017                         g_object_unref (part);
5018
5019                 tny_iterator_next (iter);
5020         }
5021         g_object_unref (iter);
5022         
5023
5024         if (pending_purges>0) {
5025                 gint response;
5026                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
5027
5028                 if (response == GTK_RESPONSE_OK) {
5029                         GtkWidget *info;
5030                         info =
5031                                 modest_platform_animation_banner (GTK_WIDGET (win), NULL, _("mcen_me_inbox_remove_attachments"));
5032                         iter = tny_list_create_iterator (parts);
5033                         while (!tny_iterator_is_done (iter)) {
5034                                 TnyMimePart *part;
5035                                 
5036                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
5037                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
5038                                         tny_mime_part_set_purged (part);
5039
5040                                 if (part)
5041                                         g_object_unref (part);
5042
5043                                 tny_iterator_next (iter);
5044                         }
5045                         g_object_unref (iter);
5046                         
5047                         tny_msg_rewrite_cache (msg);
5048
5049                         gtk_widget_destroy (info);
5050                 }
5051         }
5052
5053         modest_window_mgr_unregister_header (mgr, header);
5054
5055         g_object_unref (parts);
5056 }
5057
5058 static void
5059 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
5060                                                      ModestMainWindow *win)
5061 {
5062         GtkWidget *header_view;
5063         TnyList *header_list;
5064         TnyHeader *header;
5065         TnyHeaderFlags flags;
5066         ModestWindow *msg_view_window =  NULL;
5067         gboolean found;
5068
5069         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5070
5071         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5072                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5073
5074         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5075         if (!header_list) {
5076                 g_warning ("%s: no header selected", __FUNCTION__);
5077                 return;
5078         }
5079         
5080         if (tny_list_get_length (header_list) == 1) {
5081                 TnyIterator *iter = tny_list_create_iterator (header_list);
5082                 header = TNY_HEADER (tny_iterator_get_current (iter));
5083                 g_object_unref (iter);
5084         } else
5085                 return;
5086         
5087         if (!header || !TNY_IS_HEADER(header)) {
5088                 g_warning ("%s: header is not valid", __FUNCTION__);
5089                 return;
5090         }
5091         
5092         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
5093                                                           header, &msg_view_window);
5094         flags = tny_header_get_flags (header);
5095         if (!(flags & TNY_HEADER_FLAG_CACHED))
5096                 return;
5097         if (found) {
5098                 if (msg_view_window != NULL) 
5099                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
5100                 else {
5101                         /* do nothing; uid was registered before, so window is probably on it's way */
5102                         g_warning ("debug: header %p has already been registered", header);
5103                 }
5104         } else {
5105                 ModestMailOperation *mail_op = NULL;
5106                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
5107                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
5108                                                                          modest_ui_actions_disk_operations_error_handler,
5109                                                                          NULL, NULL);
5110                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5111                 modest_mail_operation_get_msg (mail_op, header, FALSE, open_msg_for_purge_cb, win);
5112                 
5113                 g_object_unref (mail_op);
5114         }
5115         if (header)
5116                 g_object_unref (header);
5117         if (header_list)
5118                 g_object_unref (header_list);
5119 }
5120
5121 /*
5122  * Checks if we need a connection to do the transfer and if the user
5123  * wants to connect to complete it
5124  */
5125 void
5126 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
5127                                        TnyFolderStore *src_folder,
5128                                        TnyList *headers,
5129                                        TnyFolder *dst_folder,
5130                                        gboolean delete_originals,
5131                                        gboolean *need_connection,
5132                                        gboolean *do_xfer)
5133 {
5134         TnyAccount *src_account;
5135         gint uncached_msgs = 0;
5136
5137         uncached_msgs = header_list_count_uncached_msgs (headers);
5138
5139         /* We don't need any further check if
5140          *
5141          * 1- the source folder is local OR
5142          * 2- the device is already online
5143          */
5144         if (!modest_tny_folder_store_is_remote (src_folder) ||
5145             tny_device_is_online (modest_runtime_get_device())) {
5146                 *need_connection = FALSE;
5147                 *do_xfer = TRUE;
5148                 return;
5149         }
5150
5151         /* We must ask for a connection when
5152          *
5153          *   - the message(s) is not already cached   OR 
5154          *   - the message(s) is cached but the leave_on_server setting
5155          * is FALSE (because we need to sync the source folder to
5156          * delete the message from the server (for IMAP we could do it
5157          * offline, it'll take place the next time we get a
5158          * connection)
5159          */
5160         src_account = get_account_from_folder_store (src_folder);
5161         if (uncached_msgs > 0) {
5162                 guint num_headers;
5163                 const gchar *msg;
5164
5165                 *need_connection = TRUE;
5166                 num_headers = tny_list_get_length (headers);
5167                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
5168
5169                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
5170                     GTK_RESPONSE_CANCEL) {
5171                         *do_xfer = FALSE;
5172                 } else {
5173                         *do_xfer = TRUE;
5174                 }
5175         } else {
5176                 /* The transfer is possible and the user wants to */
5177                 *do_xfer = TRUE;
5178
5179                 if (remote_folder_has_leave_on_server (src_folder) && delete_originals) {
5180                         const gchar *account_name;
5181                         gboolean leave_on_server;
5182                         
5183                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
5184                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
5185                                                                                   account_name);
5186                         
5187                         if (leave_on_server == TRUE) {
5188                                 *need_connection = FALSE;
5189                         } else {
5190                                 *need_connection = TRUE;
5191                         }
5192                 } else {
5193                         *need_connection = FALSE;
5194                 }
5195         }
5196
5197         /* Frees */
5198         g_object_unref (src_account);
5199 }
5200
5201 static void
5202 xfer_messages_error_handler (ModestMailOperation *mail_op, 
5203                              gpointer user_data)
5204 {
5205         ModestWindow *main_window = NULL;
5206
5207         /* Disable next automatic folder selection */
5208         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5209                                                          FALSE); /* don't create */
5210         if (main_window) {
5211                 GObject *win = modest_mail_operation_get_source (mail_op);
5212                 modest_platform_run_information_dialog ((GtkWindow *) win, 
5213                                                         _("mail_in_ui_folder_move_target_error"), 
5214                                                         FALSE);
5215                 if (win)
5216                         g_object_unref (win);
5217         }
5218         move_to_helper_destroyer (user_data);
5219 }
5220
5221 typedef struct {
5222         TnyFolderStore *dst_folder;
5223         TnyList *headers;
5224 } XferMsgsHelper;
5225
5226 /**
5227  * Utility function that transfer messages from both the main window
5228  * and the msg view window when using the "Move to" dialog
5229  */
5230 static void
5231 xfer_messages_performer  (gboolean canceled, 
5232                           GError *err,
5233                           GtkWindow *parent_window, 
5234                           TnyAccount *account, 
5235                           gpointer user_data)
5236 {
5237         ModestWindow *win = MODEST_WINDOW (parent_window);
5238         TnyAccount *dst_account = NULL;
5239         gboolean dst_forbids_message_add = FALSE;
5240         XferMsgsHelper *helper;
5241         MoveToHelper *movehelper;
5242         ModestMailOperation *mail_op;
5243
5244         helper = (XferMsgsHelper *) user_data;
5245
5246         if (canceled || err) {
5247                 if (!check_memory_full_error ((GtkWidget *) parent_window, err)) {
5248                         /* Show the proper error message */
5249                         modest_ui_actions_on_account_connection_error (parent_window, account);
5250                 }
5251                 goto end;
5252         }
5253
5254         dst_account = tny_folder_get_account (TNY_FOLDER (helper->dst_folder));
5255
5256         /* tinymail will return NULL for local folders it seems */
5257         dst_forbids_message_add = modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
5258                                                                                   modest_tny_account_get_protocol_type (dst_account),
5259                                                                                   MODEST_PROTOCOL_REGISTRY_STORE_FORBID_MESSAGE_ADD);
5260         g_object_unref (dst_account);
5261
5262         if (dst_forbids_message_add) {
5263                 modest_platform_information_banner (GTK_WIDGET (win),
5264                                                     NULL,
5265                                                     ngettext("mail_in_ui_folder_move_target_error",
5266                                                              "mail_in_ui_folder_move_targets_error",
5267                                                              tny_list_get_length (helper->headers)));
5268                 goto end;
5269         }
5270
5271         movehelper = g_new0 (MoveToHelper, 1);
5272         movehelper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
5273                                                                _CS("ckct_nw_pasting"));
5274         if (movehelper->banner != NULL)  {
5275                 g_object_ref (movehelper->banner);
5276                 gtk_widget_show (GTK_WIDGET (movehelper->banner));
5277         }
5278
5279         if (MODEST_IS_MAIN_WINDOW (win)) {
5280                 GtkWidget *header_view = 
5281                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5282                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5283                 movehelper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
5284         }
5285
5286         /* Perform the mail operation */
5287         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT(win),
5288                                                                  xfer_messages_error_handler,
5289                                                                  movehelper, NULL);
5290         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
5291                                          mail_op);
5292
5293         modest_mail_operation_xfer_msgs (mail_op, 
5294                                          helper->headers,
5295                                          TNY_FOLDER (helper->dst_folder),
5296                                          TRUE,
5297                                          msgs_move_to_cb,
5298                                          movehelper);
5299
5300         g_object_unref (G_OBJECT (mail_op));
5301  end:
5302         g_object_unref (helper->dst_folder);
5303         g_object_unref (helper->headers);
5304         g_slice_free (XferMsgsHelper, helper);
5305 }
5306
5307 typedef struct {
5308         TnyFolder *src_folder;
5309         TnyFolderStore *dst_folder;
5310         gboolean delete_original;
5311         GtkWidget *folder_view;
5312 } MoveFolderInfo;
5313
5314 static void
5315 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window, 
5316                 TnyAccount *account, gpointer user_data)
5317 {
5318         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
5319         GtkTreeSelection *sel;
5320         ModestMailOperation *mail_op = NULL;
5321         
5322         if (canceled || err || !MODEST_IS_MAIN_WINDOW (parent_window)) {
5323                 g_object_unref (G_OBJECT (info->src_folder));
5324                 g_object_unref (G_OBJECT (info->dst_folder));
5325                 g_free (info);
5326                 return;
5327         }
5328         
5329         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
5330         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
5331                         _CS("ckct_nw_pasting"));
5332         if (helper->banner != NULL)  {
5333                 g_object_ref (helper->banner);
5334                 gtk_widget_show (GTK_WIDGET(helper->banner));
5335         }
5336         /* Clean folder on header view before moving it */
5337         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
5338         gtk_tree_selection_unselect_all (sel);
5339
5340         /* Let gtk events run. We need that the folder
5341            view frees its reference to the source
5342            folder *before* issuing the mail operation
5343            so we need the signal handler of selection
5344            changed to happen before the mail
5345            operation 
5346         while (gtk_events_pending ())
5347                 gtk_main_iteration ();   */
5348
5349         mail_op =
5350                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
5351                                 modest_ui_actions_move_folder_error_handler,
5352                                 info->src_folder, NULL);
5353         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
5354                         mail_op);
5355
5356         /* Select *after* the changes */
5357         /* TODO: this function hangs UI after transfer */ 
5358         /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
5359         /*                                                        TNY_FOLDER (src_folder), TRUE); */
5360
5361         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
5362                                           TNY_FOLDER (info->dst_folder), TRUE);
5363         modest_mail_operation_xfer_folder (mail_op,
5364                         TNY_FOLDER (info->src_folder),
5365                         info->dst_folder,
5366                         info->delete_original, 
5367                         folder_move_to_cb, 
5368                         helper);
5369         g_object_unref (G_OBJECT (info->src_folder));
5370
5371         /* if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {        */
5372         /* } */
5373         
5374         /* Unref mail operation */
5375         g_object_unref (G_OBJECT (mail_op));
5376         g_object_unref (G_OBJECT (info->dst_folder));
5377         g_free (user_data);
5378 }
5379
5380 static TnyAccount *
5381 get_account_from_folder_store (TnyFolderStore *folder_store) 
5382 {
5383         if (TNY_IS_ACCOUNT (folder_store))
5384                 return g_object_ref (folder_store);
5385         else
5386                 return tny_folder_get_account (TNY_FOLDER (folder_store));
5387 }
5388
5389 /*
5390  * UI handler for the "Move to" action when invoked from the
5391  * ModestMainWindow
5392  */
5393 static void 
5394 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
5395                                           GtkWidget *folder_view,
5396                                           TnyFolderStore *dst_folder,
5397                                           ModestMainWindow *win)
5398 {
5399         ModestHeaderView *header_view = NULL;
5400         TnyFolderStore *src_folder = NULL;
5401
5402         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
5403
5404         /* Get the source folder */
5405         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5406
5407         /* Get header view */
5408         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
5409
5410         /* Get folder or messages to transfer */
5411         if (gtk_widget_is_focus (folder_view)) {
5412                 gboolean do_xfer = TRUE;
5413
5414                 /* Allow only to transfer folders to the local root folder */
5415                 if (TNY_IS_ACCOUNT (dst_folder) && 
5416                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
5417                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
5418                         do_xfer = FALSE;
5419                 } else if (!TNY_IS_FOLDER (src_folder)) {
5420                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
5421                         do_xfer = FALSE;
5422                 }
5423
5424                 if (do_xfer) {                  
5425                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
5426                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5427
5428                         info->src_folder = g_object_ref (src_folder);
5429                         info->dst_folder = g_object_ref (dst_folder);
5430                         info->delete_original = TRUE;
5431                         info->folder_view = folder_view;
5432
5433                         connect_info->callback = on_move_folder_cb;
5434                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
5435                         connect_info->data = info;
5436
5437                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5438                                                                    TNY_FOLDER_STORE (src_folder), 
5439                                                                    connect_info);
5440                 }
5441         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
5442                 TnyList *headers;
5443
5444                 headers = modest_header_view_get_selected_headers(header_view);
5445
5446                 /* Transfer the messages */
5447                 modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder), 
5448                                                             headers, TNY_FOLDER (dst_folder));
5449
5450                 g_object_unref (headers);
5451         }
5452
5453         /* Frees */
5454         g_object_unref (src_folder);
5455 }
5456
5457
5458 void
5459 modest_ui_actions_transfer_messages_helper (GtkWindow *win,
5460                                             TnyFolder *src_folder,
5461                                             TnyList *headers,
5462                                             TnyFolder *dst_folder)
5463 {
5464         gboolean need_connection = TRUE;
5465         gboolean do_xfer = TRUE;
5466         XferMsgsHelper *helper;
5467
5468         g_return_if_fail (TNY_IS_FOLDER (src_folder));
5469         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5470         g_return_if_fail (TNY_IS_LIST (headers));
5471         
5472         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder), 
5473                                                headers, TNY_FOLDER (dst_folder),
5474                                                TRUE, &need_connection, 
5475                                                &do_xfer);
5476
5477         /* If we don't want to transfer just return */
5478         if (!do_xfer)
5479                 return;
5480
5481         /* Create the helper */
5482         helper = g_slice_new (XferMsgsHelper);
5483         helper->dst_folder = g_object_ref (dst_folder);
5484         helper->headers = g_object_ref (headers);
5485
5486         if (need_connection) {
5487                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
5488                 connect_info->callback = xfer_messages_performer;
5489                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
5490                 connect_info->data = helper;
5491                 
5492                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
5493                                                            TNY_FOLDER_STORE (src_folder), 
5494                                                            connect_info);
5495         } else {
5496                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
5497                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
5498                                          src_account, helper);
5499                 g_object_unref (src_account);
5500         }
5501 }
5502
5503 /*
5504  * UI handler for the "Move to" action when invoked from the
5505  * ModestMsgViewWindow
5506  */
5507 static void 
5508 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
5509                                               TnyFolderStore *dst_folder,
5510                                               ModestMsgViewWindow *win)
5511 {
5512         TnyList *headers = NULL;
5513         TnyHeader *header = NULL;
5514         TnyFolder *src_folder = NULL;
5515
5516         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5517
5518         /* Create header list */
5519         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5520         src_folder = TNY_FOLDER (tny_header_get_folder(header));
5521         headers = tny_simple_list_new ();
5522         tny_list_append (headers, G_OBJECT (header));
5523
5524         /* Transfer the messages */
5525         modest_ui_actions_transfer_messages_helper (GTK_WINDOW (win), src_folder, headers, 
5526                                                     TNY_FOLDER (dst_folder));
5527
5528         /* Frees */
5529         g_object_unref (src_folder);
5530         g_object_unref (header);
5531         g_object_unref (headers);
5532 }
5533
5534 void 
5535 modest_ui_actions_on_move_to (GtkAction *action, 
5536                               ModestWindow *win)
5537 {
5538         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
5539         gint result = 0;
5540         TnyFolderStore *dst_folder = NULL;
5541         ModestMainWindow *main_window;
5542
5543         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
5544                           MODEST_IS_MSG_VIEW_WINDOW (win));
5545
5546         /* Get the main window if exists */
5547         if (MODEST_IS_MAIN_WINDOW (win))
5548                 main_window = MODEST_MAIN_WINDOW (win);
5549         else
5550                 main_window = 
5551                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5552                                                                                FALSE)); /* don't create */
5553
5554         /* Get the folder view widget if exists */
5555         if (main_window)
5556                 folder_view = modest_main_window_get_child_widget (main_window,
5557                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5558         else
5559                 folder_view = NULL;
5560
5561         /* Create and run the dialog */
5562         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
5563         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5564         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (dialog), (GtkWindow *) win);
5565         result = gtk_dialog_run (GTK_DIALOG(dialog));
5566         g_object_ref (tree_view);
5567         gtk_widget_destroy (dialog);
5568
5569         if (result != GTK_RESPONSE_ACCEPT)
5570                 return;
5571
5572         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
5573         /* Do window specific stuff */
5574         if (MODEST_IS_MAIN_WINDOW (win)) {
5575                 modest_ui_actions_on_main_window_move_to (action,
5576                                 folder_view,
5577                                 dst_folder,
5578                                 MODEST_MAIN_WINDOW (win));
5579         } else {
5580                 modest_ui_actions_on_msg_view_window_move_to (action,
5581                                 dst_folder,
5582                                 MODEST_MSG_VIEW_WINDOW (win));
5583         }
5584
5585         if (dst_folder)
5586                 g_object_unref (dst_folder);
5587 }
5588
5589 /*
5590  * Calls #HeadersFunc for each header already selected in the main
5591  * window or the message currently being shown in the msg view window
5592  */
5593 static void
5594 do_headers_action (ModestWindow *win, 
5595                    HeadersFunc func,
5596                    gpointer user_data)
5597 {
5598         TnyList *headers_list = NULL;
5599         TnyIterator *iter = NULL;
5600         TnyHeader *header = NULL;
5601         TnyFolder *folder = NULL;
5602
5603         /* Get headers */
5604         headers_list = get_selected_headers (win);
5605         if (!headers_list)
5606                 return;
5607
5608         /* Get the folder */
5609         iter = tny_list_create_iterator (headers_list);
5610         header = TNY_HEADER (tny_iterator_get_current (iter));
5611         if (header) {
5612                 folder = tny_header_get_folder (header);
5613                 g_object_unref (header);
5614         }
5615
5616         /* Call the function for each header */
5617         while (!tny_iterator_is_done (iter)) {
5618                 header = TNY_HEADER (tny_iterator_get_current (iter));
5619                 func (header, win, user_data);
5620                 g_object_unref (header);
5621                 tny_iterator_next (iter);
5622         }
5623
5624         /* Trick: do a poke status in order to speed up the signaling
5625            of observers */
5626         tny_folder_poke_status (folder);
5627
5628         /* Frees */
5629         g_object_unref (folder);
5630         g_object_unref (iter);
5631         g_object_unref (headers_list);
5632 }
5633
5634 void 
5635 modest_ui_actions_view_attachment (GtkAction *action,
5636                                    ModestWindow *window)
5637 {
5638         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5639                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
5640         } else {
5641                 /* not supported window for this action */
5642                 g_return_if_reached ();
5643         }
5644 }
5645
5646 void
5647 modest_ui_actions_save_attachments (GtkAction *action,
5648                                     ModestWindow *window)
5649 {
5650         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5651
5652                 if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
5653                         return;
5654
5655                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
5656         } else {
5657                 /* not supported window for this action */
5658                 g_return_if_reached ();
5659         }
5660 }
5661
5662 void
5663 modest_ui_actions_remove_attachments (GtkAction *action,
5664                                       ModestWindow *window)
5665 {
5666         if (MODEST_IS_MAIN_WINDOW (window)) {
5667                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
5668         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5669                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
5670         } else {
5671                 /* not supported window for this action */
5672                 g_return_if_reached ();
5673         }
5674 }
5675
5676 void 
5677 modest_ui_actions_on_settings (GtkAction *action, 
5678                                ModestWindow *win)
5679 {
5680         GtkWidget *dialog;
5681
5682         dialog = modest_platform_get_global_settings_dialog ();
5683         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
5684         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5685         gtk_widget_show_all (dialog);
5686
5687         gtk_dialog_run (GTK_DIALOG (dialog));
5688
5689         gtk_widget_destroy (dialog);
5690 }
5691
5692 void 
5693 modest_ui_actions_on_help (GtkAction *action, 
5694                            GtkWindow *win)
5695 {
5696         /* Help app is not available at all in fremantle */
5697 #ifndef MODEST_TOOLKIT_HILDON2
5698         const gchar *help_id;
5699
5700         g_return_if_fail (win && GTK_IS_WINDOW(win));
5701         
5702         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
5703
5704         if (help_id)
5705                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5706 #endif
5707 }
5708
5709 void 
5710 modest_ui_actions_on_csm_help (GtkAction *action, 
5711                                GtkWindow *win)
5712 {
5713         /* Help app is not available at all in fremantle */
5714 #ifndef MODEST_TOOLKIT_HILDON2
5715
5716         const gchar* help_id = NULL;
5717         GtkWidget *folder_view;
5718         TnyFolderStore *folder_store;
5719
5720         g_return_if_fail (win && MODEST_IS_MAIN_WINDOW (win));
5721
5722         /* Get selected folder */
5723         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
5724                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5725         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5726
5727         /* Switch help_id */
5728         if (folder_store && TNY_IS_FOLDER (folder_store))
5729                 help_id = modest_tny_folder_get_help_id (TNY_FOLDER (folder_store));
5730
5731         if (folder_store)
5732                 g_object_unref (folder_store);
5733
5734         if (help_id)
5735                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5736         else
5737                 modest_ui_actions_on_help (action, win);
5738 #endif
5739 }
5740
5741 static void     
5742 retrieve_contents_cb (ModestMailOperation *mail_op, 
5743                       TnyHeader *header, 
5744                       gboolean canceled,
5745                       TnyMsg *msg,
5746                       GError *err,
5747                       gpointer user_data)
5748 {
5749         /* We only need this callback to show an error in case of
5750            memory low condition */
5751         modest_ui_actions_msg_retrieval_check (mail_op, header, msg);
5752 }
5753
5754 static void
5755 retrieve_msg_contents_performer (gboolean canceled, 
5756                                  GError *err,
5757                                  GtkWindow *parent_window, 
5758                                  TnyAccount *account, 
5759                                  gpointer user_data)
5760 {
5761         ModestMailOperation *mail_op;
5762         TnyList *headers = TNY_LIST (user_data);
5763
5764         if (err || canceled) {
5765                 check_memory_full_error ((GtkWidget *) parent_window, err);
5766                 goto out;
5767         }
5768
5769         /* Create mail operation */
5770         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
5771                                                                  modest_ui_actions_disk_operations_error_handler, 
5772                                                                  NULL, NULL);
5773         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5774         modest_mail_operation_get_msgs_full (mail_op, headers, retrieve_contents_cb, NULL, NULL);
5775
5776         /* Frees */
5777         g_object_unref (mail_op);
5778  out:
5779         g_object_unref (headers);
5780         g_object_unref (account);
5781 }
5782
5783 void 
5784 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
5785                                             ModestWindow *window)
5786 {
5787         TnyList *headers = NULL;
5788         TnyAccount *account = NULL;
5789         TnyIterator *iter = NULL;
5790         TnyHeader *header = NULL;
5791         TnyFolder *folder = NULL;
5792
5793         /* Get headers */
5794         headers = get_selected_headers (window);
5795         if (!headers)
5796                 return;
5797
5798         /* Pick the account */
5799         iter = tny_list_create_iterator (headers);
5800         header = TNY_HEADER (tny_iterator_get_current (iter));
5801         folder = tny_header_get_folder (header);
5802         account = tny_folder_get_account (folder);
5803         g_object_unref (folder);
5804         g_object_unref (header);
5805         g_object_unref (iter);
5806
5807         /* Connect and perform the message retrieval */
5808         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
5809                                              g_object_ref (account), 
5810                                              retrieve_msg_contents_performer, 
5811                                              g_object_ref (headers));
5812
5813         /* Frees */
5814         g_object_unref (account);
5815         g_object_unref (headers);
5816 }
5817
5818 void
5819 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
5820 {
5821         g_return_if_fail (MODEST_IS_WINDOW (window));
5822
5823         /* Update dimmed */
5824         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
5825 }
5826
5827 void
5828 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
5829 {
5830         g_return_if_fail (MODEST_IS_WINDOW (window));
5831
5832         /* Update dimmed */
5833         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
5834 }
5835
5836 void
5837 modest_ui_actions_on_email_menu_activated (GtkAction *action,
5838                                           ModestWindow *window)
5839 {
5840         g_return_if_fail (MODEST_IS_WINDOW (window));
5841         
5842         /* Update dimmed */
5843         modest_ui_actions_check_menu_dimming_rules (window);
5844 }
5845
5846 void
5847 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
5848                                           ModestWindow *window)
5849 {
5850         g_return_if_fail (MODEST_IS_WINDOW (window));
5851
5852         /* Update dimmed */
5853         modest_ui_actions_check_menu_dimming_rules (window);
5854 }
5855
5856 void
5857 modest_ui_actions_on_view_menu_activated (GtkAction *action,
5858                                           ModestWindow *window)
5859 {
5860         g_return_if_fail (MODEST_IS_WINDOW (window));
5861
5862         /* Update dimmed */
5863         modest_ui_actions_check_menu_dimming_rules (window);
5864 }
5865
5866 void
5867 modest_ui_actions_on_format_menu_activated (GtkAction *action,
5868                                             ModestWindow *window)
5869 {
5870         g_return_if_fail (MODEST_IS_WINDOW (window));
5871
5872         /* Update dimmed */
5873         modest_ui_actions_check_menu_dimming_rules (window);
5874 }
5875
5876 void
5877 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
5878                                           ModestWindow *window)
5879 {
5880         g_return_if_fail (MODEST_IS_WINDOW (window));
5881
5882         /* Update dimmed */
5883         modest_ui_actions_check_menu_dimming_rules (window);
5884 }
5885
5886 void
5887 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
5888                                           ModestWindow *window)
5889 {
5890         g_return_if_fail (MODEST_IS_WINDOW (window));
5891
5892         /* Update dimmed */
5893         modest_ui_actions_check_menu_dimming_rules (window);
5894 }
5895
5896 void
5897 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
5898                                                  ModestWindow *window)
5899 {
5900         g_return_if_fail (MODEST_IS_WINDOW (window));
5901
5902         /* Update dimmed */
5903         modest_ui_actions_check_menu_dimming_rules (window);
5904 }
5905
5906 void
5907 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
5908                                                      ModestWindow *window)
5909 {
5910         g_return_if_fail (MODEST_IS_WINDOW (window));
5911
5912         /* Update dimmed */
5913         modest_ui_actions_check_menu_dimming_rules (window);
5914 }
5915
5916 void
5917 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
5918                                                      ModestWindow *window)
5919 {
5920         g_return_if_fail (MODEST_IS_WINDOW (window));
5921
5922         /* Update dimmed */
5923         modest_ui_actions_check_menu_dimming_rules (window);
5924 }
5925
5926 void
5927 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
5928 {
5929         g_return_if_fail (MODEST_IS_WINDOW (window));
5930
5931         /* we check for low-mem; in that case, show a warning, and don't allow
5932          * searching
5933          */
5934         if (modest_platform_check_memory_low (window, TRUE))
5935                 return;
5936         
5937         modest_platform_show_search_messages (GTK_WINDOW (window));
5938 }
5939
5940 void     
5941 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
5942 {
5943         g_return_if_fail (MODEST_IS_WINDOW (win));
5944
5945
5946         /* we check for low-mem; in that case, show a warning, and don't allow
5947          * for the addressbook
5948          */
5949         if (modest_platform_check_memory_low (win, TRUE))
5950                 return;
5951
5952
5953         modest_platform_show_addressbook (GTK_WINDOW (win));
5954 }
5955
5956
5957 void
5958 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
5959                                           ModestWindow *window)
5960 {
5961         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5962
5963         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
5964 }
5965
5966 static void 
5967 on_send_receive_finished (ModestMailOperation  *mail_op, 
5968                            gpointer user_data)
5969 {
5970         GtkWidget *header_view, *folder_view;
5971         TnyFolderStore *folder_store;
5972         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
5973
5974         /* Set send/receive operation finished */       
5975         modest_main_window_notify_send_receive_completed (main_win);
5976
5977         /* Don't refresh the current folder if there were any errors */
5978         if (modest_mail_operation_get_status (mail_op) !=
5979             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5980                 return;
5981         
5982         /* Refresh the current folder if we're viewing a window. We do
5983            this because the user won't be able to see the new mails in
5984            the selected folder after a Send&Receive because it only
5985            performs a poke_status, i.e, only the number of read/unread
5986            messages is updated, but the new headers are not
5987            downloaded */
5988         folder_view = modest_main_window_get_child_widget (main_win, 
5989                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5990         if (!folder_view)
5991                 return;
5992
5993         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5994         
5995         /* Do not need to refresh INBOX again because the
5996            update_account does it always automatically */
5997         if (folder_store && TNY_IS_FOLDER (folder_store) && 
5998             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
5999                 ModestMailOperation *refresh_op;
6000
6001                 header_view = modest_main_window_get_child_widget (main_win,
6002                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6003                 
6004                 /* We do not need to set the contents style
6005                    because it hasn't changed. We also do not
6006                    need to save the widget status. Just force
6007                    a refresh */
6008                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
6009                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
6010                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
6011                                                       folder_refreshed_cb, main_win);
6012                 g_object_unref (refresh_op);
6013         }
6014         
6015         if (folder_store)
6016                 g_object_unref (folder_store);
6017 }
6018
6019
6020 void 
6021 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
6022                                                 TnyHeader *header, 
6023                                                 TnyMsg *msg, 
6024                                                 GError *err, 
6025                                                 gpointer user_data)
6026 {
6027         const gchar* server_name = NULL;
6028         TnyTransportAccount *server_account;
6029         gchar *message = NULL;
6030
6031         /* Don't show anything if the user cancelled something or the
6032          * send receive request is not interactive. Authentication
6033          * errors are managed by the account store so no need to show
6034          * a dialog here again */
6035         if (err->code == TNY_SYSTEM_ERROR_CANCEL ||
6036             err->code == TNY_SERVICE_ERROR_AUTHENTICATE ||
6037             !modest_tny_send_queue_get_requested_send_receive (MODEST_TNY_SEND_QUEUE (self)))
6038                 return;
6039
6040
6041         /* Get the server name: */
6042         server_account = 
6043                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
6044         if (server_account)
6045                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));          
6046         else
6047                 g_return_if_reached ();
6048
6049         /* Show the appropriate message text for the GError: */
6050         switch (err->code) {
6051         case TNY_SERVICE_ERROR_CONNECT:
6052                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
6053                 break;
6054         case TNY_SERVICE_ERROR_SEND:
6055                 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
6056                 break;
6057         case TNY_SERVICE_ERROR_UNAVAILABLE:
6058                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
6059                 break;
6060         default:
6061                 g_warning ("%s: unexpected ERROR %d",
6062                            __FUNCTION__, err->code);
6063                 message = g_strdup (dgettext("hildon-common-strings", "sfil_ib_unable_to_send"));
6064                 break;  
6065         }
6066
6067         modest_platform_run_information_dialog (NULL, message, FALSE);
6068         g_free (message);
6069         g_object_unref (server_account);
6070 }
6071
6072 void
6073 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
6074                                                 gchar *msg_id, 
6075                                                 guint status,
6076                                                 gpointer user_data)
6077 {
6078         ModestMainWindow *main_window = NULL;
6079         ModestWindowMgr *mgr = NULL;
6080         GtkWidget *folder_view = NULL, *header_view = NULL;
6081         TnyFolderStore *selected_folder = NULL;
6082         TnyFolderType folder_type;
6083
6084         mgr = modest_runtime_get_window_mgr ();
6085         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
6086                                                                              FALSE));/* don't create */
6087         if (!main_window)
6088                 return;
6089
6090         /* Check if selected folder is OUTBOX */
6091         folder_view = modest_main_window_get_child_widget (main_window,
6092                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
6093         header_view = modest_main_window_get_child_widget (main_window,
6094                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6095
6096         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
6097         if (!TNY_IS_FOLDER (selected_folder)) 
6098                 goto frees;
6099
6100         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
6101 #if GTK_CHECK_VERSION(2, 8, 0) 
6102         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
6103         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
6104                 GtkTreeViewColumn *tree_column;
6105
6106                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
6107                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
6108                 if (tree_column)
6109                         gtk_tree_view_column_queue_resize (tree_column);
6110         }
6111 #else
6112         gtk_widget_queue_draw (header_view);
6113 #endif          
6114
6115         /* Rerun dimming rules, because the message could become deletable for example */
6116         modest_window_check_dimming_rules_group (MODEST_WINDOW (main_window), 
6117                                                  MODEST_DIMMING_RULES_TOOLBAR);
6118         modest_window_check_dimming_rules_group (MODEST_WINDOW (main_window), 
6119                                                  MODEST_DIMMING_RULES_MENU);
6120         
6121         /* Free */
6122  frees:
6123         if (selected_folder != NULL)
6124                 g_object_unref (selected_folder);
6125 }
6126
6127 void 
6128 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
6129                                                TnyAccount *account)
6130 {
6131         ModestProtocolType protocol_type;
6132         ModestProtocol *protocol;
6133         gchar *error_note = NULL;
6134         
6135         protocol_type = modest_tny_account_get_protocol_type (account);
6136         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6137                                                                   protocol_type);
6138
6139         error_note = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_ACCOUNT_CONNECTION_ERROR, tny_account_get_hostname (account));
6140         if (error_note == NULL) {
6141                 g_warning ("%s: This should not be reached", __FUNCTION__);
6142         } else {
6143                 modest_platform_run_information_dialog (parent_window, error_note, FALSE);
6144                 g_free (error_note);
6145         }
6146 }
6147
6148 gchar *
6149 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
6150 {
6151         gchar *msg = NULL;
6152         gchar *subject;
6153         TnyFolderStore *folder = NULL;
6154         TnyAccount *account = NULL;
6155         ModestProtocolType proto;
6156         ModestProtocol *protocol;
6157         TnyHeader *header = NULL;
6158
6159         if (MODEST_IS_MAIN_WINDOW (win)) {
6160                 GtkWidget *header_view;
6161                 TnyList* headers = NULL;
6162                 TnyIterator *iter;
6163                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
6164                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
6165                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
6166                 if (!headers || tny_list_get_length (headers) == 0) {
6167                         if (headers)
6168                                 g_object_unref (headers);
6169                         return NULL;
6170                 }
6171                 iter = tny_list_create_iterator (headers);
6172                 header = TNY_HEADER (tny_iterator_get_current (iter));
6173                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6174                 g_object_unref (iter);
6175                 g_object_unref (headers);
6176         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
6177                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
6178                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
6179         }
6180
6181         /* Get the account type */
6182         account = tny_folder_get_account (TNY_FOLDER (folder));
6183         proto = modest_tny_account_get_protocol_type (account);
6184         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6185                                                                   proto);
6186
6187         subject = tny_header_dup_subject (header);
6188         msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
6189         if (subject)
6190                 g_free (subject);
6191         if (msg == NULL) {
6192                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
6193         }
6194
6195         /* Frees */
6196         g_object_unref (account);
6197         g_object_unref (folder);
6198         g_object_unref (header);
6199
6200         return msg;
6201 }
6202
6203 gboolean
6204 modest_ui_actions_on_delete_account (GtkWindow *parent_window,
6205                                      const gchar *account_name,
6206                                      const gchar *account_title)
6207 {
6208         ModestAccountMgr *account_mgr;
6209         gchar *txt = NULL;
6210         gint response;
6211         ModestProtocol *protocol;
6212         gboolean removed = FALSE;
6213
6214         g_return_val_if_fail (account_name, FALSE);
6215         g_return_val_if_fail (account_title, FALSE);
6216
6217         account_mgr = modest_runtime_get_account_mgr();
6218
6219         /* The warning text depends on the account type: */
6220         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6221                                                                   modest_account_mgr_get_store_protocol (account_mgr,
6222                                                                                                          account_name));
6223         txt = modest_protocol_get_translation (protocol,
6224                                                MODEST_PROTOCOL_TRANSLATION_DELETE_MAILBOX,
6225                                                account_title);
6226         if (txt == NULL)
6227                 txt = g_strdup_printf (_("emev_nc_delete_mailbox"), account_title);
6228
6229         response = modest_platform_run_confirmation_dialog (parent_window, txt);
6230         g_free (txt);
6231         txt = NULL;
6232
6233         if (response == GTK_RESPONSE_OK) {
6234                 /* Remove account. If it succeeds then it also removes
6235                    the account from the ModestAccountView: */
6236                 gboolean is_default = FALSE;
6237                 gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr);
6238                 if (default_account_name && (strcmp (default_account_name, account_name) == 0))
6239                         is_default = TRUE;
6240                 g_free (default_account_name);
6241
6242                 removed = modest_account_mgr_remove_account (account_mgr, account_name);
6243                 if (!removed)
6244                         g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__);
6245         }
6246         return removed;
6247 }