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