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