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