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