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