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