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