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