* Fixes NB#92686, migrate the main window menus to the 1,5 specs
[modest] / src / modest-ui-actions.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved. 
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29  
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif /*HAVE_CONFIG_H*/
33
34 #include <glib/gi18n.h>
35 #include <glib/gprintf.h>
36 #include <string.h>
37 #include <modest-runtime.h>
38 #include <modest-tny-folder.h>
39 #include <modest-tny-msg.h>
40 #include <modest-tny-account.h>
41 #include <modest-address-book.h>
42 #include "modest-error.h"
43 #include "modest-ui-actions.h"
44 #include "modest-tny-platform-factory.h"
45 #include "modest-platform.h"
46 #include "modest-debug.h"
47 #include <tny-mime-part.h>
48 #include <tny-camel-folder.h>
49 #include <tny-camel-imap-folder.h>
50 #include <tny-camel-pop-folder.h>
51 #ifdef MODEST_TOOLKIT_HILDON2
52 #include <hildon/hildon-pannable-area.h>
53 #endif
54
55 #ifdef MODEST_PLATFORM_MAEMO
56 #include "maemo/modest-osso-state-saving.h"
57 #endif /* MODEST_PLATFORM_MAEMO */
58 #ifndef MODEST_TOOLKIT_GTK
59 #include "maemo/modest-hildon-includes.h"
60 #include "maemo/modest-connection-specific-smtp-window.h"
61 #endif /* !MODEST_TOOLKIT_GTK */
62 #include <modest-utils.h>
63
64 #include "widgets/modest-ui-constants.h"
65 #include <widgets/modest-main-window.h>
66 #include <widgets/modest-msg-view-window.h>
67 #include <widgets/modest-account-view-window.h>
68 #include <widgets/modest-details-dialog.h>
69 #include <widgets/modest-attachments-view.h>
70 #include "widgets/modest-folder-view.h"
71 #include "widgets/modest-global-settings-dialog.h"
72 #include "modest-account-mgr-helpers.h"
73 #include "modest-mail-operation.h"
74 #include "modest-text-utils.h"
75
76 #ifdef MODEST_HAVE_EASYSETUP
77 #ifdef MODEST_TOOLKIT_HILDON2
78 #include "modest-easysetup-wizard-dialog.h"
79 #else
80 #include "easysetup/modest-easysetup-wizard-dialog.h"
81 #endif
82 #endif /* MODEST_HAVE_EASYSETUP */
83
84 #include <modest-widget-memory.h>
85 #include <tny-error.h>
86 #include <tny-simple-list.h>
87 #include <tny-msg-view.h>
88 #include <tny-device.h>
89 #include <tny-merge-folder.h>
90
91 #include <gtkhtml/gtkhtml.h>
92
93 #define MIN_FREE_SPACE 5 * 1024 * 1024
94 #define MOVE_FOLDER_OK_BUTTON "ok-button"
95 #define MOVE_FOLDER_NEW_BUTTON "new-button"
96
97 typedef struct _GetMsgAsyncHelper {     
98         ModestWindow *window;
99         ModestMailOperation *mail_op;
100         TnyIterator *iter;
101         guint num_ops;
102         GFunc func;     
103         gpointer user_data;
104 } GetMsgAsyncHelper;
105
106 typedef enum _ReplyForwardAction {
107         ACTION_REPLY,
108         ACTION_REPLY_TO_ALL,
109         ACTION_FORWARD
110 } ReplyForwardAction;
111
112 typedef struct _ReplyForwardHelper {
113         guint reply_forward_type;
114         ReplyForwardAction action;
115         gchar *account_name;
116         GtkWidget *parent_window;
117         TnyHeader *header;
118 } ReplyForwardHelper;
119
120 typedef struct _MoveToHelper {
121         GtkTreeRowReference *reference;
122         GtkWidget *banner;
123 } MoveToHelper;
124
125 typedef struct _PasteAsAttachmentHelper {
126         ModestMsgEditWindow *window;
127         GtkWidget *banner;
128 } PasteAsAttachmentHelper;
129
130
131 /*
132  * The do_headers_action uses this kind of functions to perform some
133  * action to each member of a list of headers
134  */
135 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
136
137 static void     do_headers_action     (ModestWindow *win, 
138                                        HeadersFunc func,
139                                        gpointer user_data);
140
141 static void     open_msg_cb            (ModestMailOperation *mail_op, 
142                                         TnyHeader *header, 
143                                         gboolean canceled,
144                                         TnyMsg *msg,
145                                         GError *err,
146                                         gpointer user_data);
147
148 static void     reply_forward_cb       (ModestMailOperation *mail_op, 
149                                         TnyHeader *header, 
150                                         gboolean canceled,
151                                         TnyMsg *msg,
152                                         GError *err,
153                                         gpointer user_data);
154
155 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
156
157 static void     folder_refreshed_cb    (ModestMailOperation *mail_op, 
158                                         TnyFolder *folder, 
159                                         gpointer user_data);
160
161 static void     on_send_receive_finished (ModestMailOperation  *mail_op, 
162                                           gpointer user_data);
163
164 static gint header_list_count_uncached_msgs (TnyList *header_list);
165
166 static gboolean connect_to_get_msg (ModestWindow *win,
167                                     gint num_of_uncached_msgs,
168                                     TnyAccount *account);
169
170 static gboolean remote_folder_has_leave_on_server (TnyFolderStore *folder);
171
172 static void     do_create_folder (GtkWindow *window, 
173                                   TnyFolderStore *parent_folder, 
174                                   const gchar *suggested_name);
175
176 static GtkWidget* get_folder_view_from_move_to_dialog (GtkWidget *move_to_dialog);
177
178 static TnyAccount *get_account_from_folder_store (TnyFolderStore *folder_store);
179
180 /*
181  * This function checks whether a TnyFolderStore is a pop account
182  */
183 static gboolean
184 remote_folder_has_leave_on_server (TnyFolderStore *folder)
185 {
186         TnyAccount *account;
187         gboolean result;
188
189         g_return_val_if_fail (TNY_IS_FOLDER_STORE (folder), FALSE);
190         
191         account = get_account_from_folder_store (folder);
192         result = (modest_protocol_registry_protocol_type_has_leave_on_server (modest_runtime_get_protocol_registry (),
193                                                                               modest_tny_account_get_protocol_type (account)));
194         g_object_unref (account);
195
196         return result;
197 }
198
199 /* FIXME: this should be merged with the similar code in modest-account-view-window */
200 /* Show the account creation wizard dialog.
201  * returns: TRUE if an account was created. FALSE if the user cancelled.
202  */
203 gboolean
204 modest_ui_actions_run_account_setup_wizard (ModestWindow *win)
205 {
206         gboolean result = FALSE;
207         GtkWindow *wizard;
208         gint dialog_response;
209
210         /* there is no such wizard yet */
211         wizard = GTK_WINDOW (modest_platform_get_account_settings_wizard ());
212         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (wizard), (GtkWindow *) win);
213
214         /* always present a main window in the background 
215          * we do it here, so we cannot end up with two wizards (as this
216          * function might be called in modest_window_mgr_get_main_window as well */
217         if (!win) 
218                 win = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr(),
219                                                          TRUE);  /* create if not existent */
220
221         gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
222
223         /* make sure the mainwindow is visible. We need to present the
224            wizard again to give it the focus back. show_all are needed
225            in order to get the widgets properly drawn (MainWindow main
226            paned won't be in its right position and the dialog will be
227            missplaced */
228 #ifndef MODEST_TOOLKIT_HILDON2
229         gtk_widget_show_all (GTK_WIDGET (win));
230         gtk_widget_show_all (GTK_WIDGET (wizard));
231         gtk_window_present (GTK_WINDOW (win));
232         gtk_window_present (GTK_WINDOW (wizard));
233 #endif
234
235         dialog_response = gtk_dialog_run (GTK_DIALOG (wizard));
236         gtk_widget_destroy (GTK_WIDGET (wizard));
237         if (gtk_events_pending ())
238                 gtk_main_iteration ();
239
240         if (dialog_response == GTK_RESPONSE_CANCEL) {
241                 result = FALSE;
242         } else {
243                 /* Check whether an account was created: */
244                 result = modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
245         }
246         return result;
247 }
248
249
250 void   
251 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
252 {
253         GtkWidget *about;
254         const gchar *authors[] = {
255                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
256                 NULL
257         };
258         about = gtk_about_dialog_new ();
259         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
260         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
261         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
262                                         _("Copyright (c) 2006, Nokia Corporation\n"
263                                           "All rights reserved."));
264         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
265                                        _("a modest e-mail client\n\n"
266                                          "design and implementation: Dirk-Jan C. Binnema\n"
267                                          "contributions from the fine people at KC and Ig\n"
268                                          "uses the tinymail email framework written by Philip van Hoof"));
269         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
270         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
271         gtk_window_set_transient_for (GTK_WINDOW (about), GTK_WINDOW (win));
272         gtk_window_set_modal (GTK_WINDOW (about), TRUE);
273         
274         gtk_dialog_run (GTK_DIALOG (about));
275         gtk_widget_destroy(about);
276 }
277
278 /*
279  * Gets the list of currently selected messages. If the win is the
280  * main window, then it returns a newly allocated list of the headers
281  * selected in the header view. If win is the msg view window, then
282  * the value returned is a list with just a single header.
283  *
284  * The caller of this funcion must free the list.
285  */
286 static TnyList *
287 get_selected_headers (ModestWindow *win)
288 {
289         if (MODEST_IS_MAIN_WINDOW(win)) {
290                 GtkWidget *header_view;         
291                 
292                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
293                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
294                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
295                 
296         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
297                 /* for MsgViewWindows, we simply return a list with one element */
298                 TnyHeader *header;
299                 TnyList *list = NULL;
300                 
301                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
302                 if (header != NULL) {
303                         list = tny_simple_list_new ();
304                         tny_list_prepend (list, G_OBJECT(header));
305                         g_object_unref (G_OBJECT(header));
306                 }
307
308                 return list;
309
310         } else
311                 return NULL;
312 }
313
314 static GtkTreeRowReference *
315 get_next_after_selected_headers (ModestHeaderView *header_view)
316 {
317         GtkTreeSelection *sel;
318         GList *selected_rows, *node;
319         GtkTreePath *path;
320         GtkTreeRowReference *result;
321         GtkTreeModel *model;
322
323         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
324         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
325         selected_rows = gtk_tree_selection_get_selected_rows (sel, NULL);
326
327         if (selected_rows == NULL)
328                 return NULL;
329
330         node = g_list_last (selected_rows);
331         path = gtk_tree_path_copy ((GtkTreePath *) node->data);
332         gtk_tree_path_next (path);
333
334         result = gtk_tree_row_reference_new (model, path);
335
336         gtk_tree_path_free (path);
337         g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
338         g_list_free (selected_rows);
339
340         return result;
341 }
342
343 static void
344 headers_action_mark_as_read (TnyHeader *header,
345                              ModestWindow *win,
346                              gpointer user_data)
347 {
348         TnyHeaderFlags flags;
349
350         g_return_if_fail (TNY_IS_HEADER(header));
351
352         flags = tny_header_get_flags (header);
353         if (flags & TNY_HEADER_FLAG_SEEN) return;
354         tny_header_set_flag (header, TNY_HEADER_FLAG_SEEN);
355 }
356
357 static void
358 headers_action_mark_as_unread (TnyHeader *header,
359                                ModestWindow *win,
360                                gpointer user_data)
361 {
362         TnyHeaderFlags flags;
363
364         g_return_if_fail (TNY_IS_HEADER(header));
365
366         flags = tny_header_get_flags (header);
367         if (flags & TNY_HEADER_FLAG_SEEN)  {
368                 tny_header_unset_flag (header, TNY_HEADER_FLAG_SEEN);
369         }
370 }
371
372 /** After deleing a message that is currently visible in a window, 
373  * show the next message from the list, or close the window if there are no more messages.
374  **/
375 void 
376 modest_ui_actions_refresh_message_window_after_delete (ModestMsgViewWindow* win)
377 {
378         /* Close msg view window or select next */
379         if (!modest_msg_view_window_select_next_message (win) &&
380             !modest_msg_view_window_select_previous_message (win)) {
381                 gboolean ret_value;
382                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);       
383         }
384 }
385
386
387 void
388 modest_ui_actions_on_delete_message (GtkAction *action, ModestWindow *win)
389 {
390         TnyList *header_list = NULL;
391         TnyIterator *iter = NULL;
392         TnyHeader *header = NULL;
393         gchar *message = NULL;
394         gchar *desc = NULL;
395         gint response;
396         ModestWindowMgr *mgr;
397         GtkWidget *header_view = NULL;
398
399         g_return_if_fail (MODEST_IS_WINDOW(win));
400         
401         /* Check first if the header view has the focus */
402         if (MODEST_IS_MAIN_WINDOW (win)) {
403                 header_view = 
404                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
405                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
406                 if (!gtk_widget_is_focus (header_view))
407                         return;
408         }
409         
410         /* Get the headers, either from the header view (if win is the main window),
411          * or from the message view window: */
412         header_list = get_selected_headers (win);
413         if (!header_list) return;
414                         
415         /* Check if any of the headers are already opened, or in the process of being opened */
416         if (MODEST_IS_MAIN_WINDOW (win)) {
417                 gint opened_headers = 0;
418
419                 iter = tny_list_create_iterator (header_list);
420                 mgr = modest_runtime_get_window_mgr ();
421                 while (!tny_iterator_is_done (iter)) {
422                         header = TNY_HEADER (tny_iterator_get_current (iter));
423                         if (header) {
424                                 if (modest_window_mgr_find_registered_header (mgr, header, NULL))
425                                         opened_headers++;
426                                 g_object_unref (header);
427                         }
428                         tny_iterator_next (iter);
429                 }
430                 g_object_unref (iter);
431
432                 if (opened_headers > 0) {
433                         gchar *msg;
434
435                         msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"), 
436                                                opened_headers);
437
438                         modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg, FALSE);
439                         
440                         g_free (msg);
441                         g_object_unref (header_list);
442                         return;
443                 }
444         }
445
446         /* Select message */
447         if (tny_list_get_length(header_list) == 1) {
448                 iter = tny_list_create_iterator (header_list);
449                 header = TNY_HEADER (tny_iterator_get_current (iter));
450                 if (header) {
451                         gchar *subject;
452                         subject = tny_header_dup_subject (header);
453                         if (!subject)
454                                 subject = g_strdup (_("mail_va_no_subject"));
455                         desc = g_strdup_printf ("%s", subject); 
456                         g_free (subject);
457                         g_object_unref (header);
458                 }
459
460                 g_object_unref (iter);
461         }
462         message = g_strdup_printf(ngettext("emev_nc_delete_message", "emev_nc_delete_messages", 
463                                            tny_list_get_length(header_list)), desc);
464
465         /* Confirmation dialog */
466         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
467                                                             message);
468         
469
470         if (response == GTK_RESPONSE_OK) {      
471                 ModestWindow *main_window = NULL;
472                 ModestWindowMgr *mgr = NULL;
473                 GtkTreeModel *model = NULL;
474                 GtkTreeSelection *sel = NULL;
475                 GList *sel_list = NULL, *tmp = NULL;
476                 GtkTreeRowReference *next_row_reference = NULL;
477                 GtkTreeRowReference *prev_row_reference = NULL;
478                 GtkTreePath *next_path = NULL;
479                 GtkTreePath *prev_path = NULL;
480                 ModestMailOperation *mail_op = NULL;
481
482                 /* Find last selected row */                    
483                 if (MODEST_IS_MAIN_WINDOW (win)) {
484                         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
485                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
486                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
487                         for (tmp=sel_list; tmp; tmp=tmp->next) {
488                                 if (tmp->next == NULL) {
489                                         prev_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
490                                         next_path = gtk_tree_path_copy((GtkTreePath *) tmp->data);
491
492                                         gtk_tree_path_prev (prev_path);
493                                         gtk_tree_path_next (next_path);
494
495                                         prev_row_reference = gtk_tree_row_reference_new (model, prev_path);
496                                         next_row_reference = gtk_tree_row_reference_new (model, next_path);
497                                 }
498                         }
499                 }
500                 
501                 /* Disable window dimming management */
502                 modest_window_disable_dimming (MODEST_WINDOW(win));
503
504                 /* Remove each header. If it's a view window header_view == NULL */
505                 mail_op = modest_mail_operation_new ((GObject *) win);
506                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
507                                                  mail_op);
508                 modest_mail_operation_remove_msgs (mail_op, header_list, FALSE);
509                 g_object_unref (mail_op);
510                 
511                 /* Enable window dimming management */
512                 if (sel != NULL) {
513                         gtk_tree_selection_unselect_all (sel);
514                 }
515                 modest_window_enable_dimming (MODEST_WINDOW(win));
516                 
517                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
518                         modest_ui_actions_refresh_message_window_after_delete (MODEST_MSG_VIEW_WINDOW (win));
519                         
520                         /* Get main window */
521                         mgr = modest_runtime_get_window_mgr ();
522                         main_window = modest_window_mgr_get_main_window (mgr, FALSE); /* don't create */
523                 } else {                        
524                         /* Move cursor to next row */
525                         main_window = win; 
526
527                         /* Select next or previous row */
528                         if (gtk_tree_row_reference_valid (next_row_reference)) {
529                                 gtk_tree_selection_select_path (sel, next_path);
530                         }
531                         else if (gtk_tree_row_reference_valid (prev_row_reference)) {                           
532                                 gtk_tree_selection_select_path (sel, prev_path);
533                         }
534
535                         /* Free */
536                         if (gtk_tree_row_reference_valid (next_row_reference)) 
537                                 gtk_tree_row_reference_free (next_row_reference);
538                         if (next_path != NULL) 
539                                 gtk_tree_path_free (next_path);                         
540                         if (gtk_tree_row_reference_valid (prev_row_reference)) 
541                                 gtk_tree_row_reference_free (prev_row_reference);
542                         if (prev_path != NULL) 
543                                 gtk_tree_path_free (prev_path);
544                 }
545                 
546                 /* Update toolbar dimming state */
547                 if (main_window) {
548                         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
549                         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
550                 }
551
552                 /* Free */
553                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
554                 g_list_free (sel_list);
555         }
556
557         /* Free*/
558         g_free(message);
559         g_free(desc);
560         g_object_unref (header_list);
561 }
562
563
564
565
566 /* delete either message or folder, based on where we are */
567 void
568 modest_ui_actions_on_delete_message_or_folder (GtkAction *action, ModestWindow *win)
569 {
570         g_return_if_fail (MODEST_IS_WINDOW(win));
571         
572         /* Check first if the header view has the focus */
573         if (MODEST_IS_MAIN_WINDOW (win)) {
574                 GtkWidget *w;
575                 w = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
576                                                          MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
577                 if (gtk_widget_is_focus (w)) {
578                         modest_ui_actions_on_delete_folder (action, MODEST_MAIN_WINDOW(win));
579                         return;
580                 }
581         }
582         modest_ui_actions_on_delete_message (action, win);
583 }
584
585 void
586 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
587 {       
588         ModestWindowMgr *mgr = NULL;
589         
590 #ifdef MODEST_PLATFORM_MAEMO
591         modest_osso_save_state();
592 #endif /* MODEST_PLATFORM_MAEMO */
593
594         g_debug ("closing down, clearing %d item(s) from operation queue",
595                  modest_mail_operation_queue_num_elements
596                  (modest_runtime_get_mail_operation_queue()));
597
598         /* cancel all outstanding operations */
599         modest_mail_operation_queue_cancel_all 
600                 (modest_runtime_get_mail_operation_queue());
601         
602         g_debug ("queue has been cleared");
603
604
605         /* Check if there are opened editing windows */ 
606         mgr = modest_runtime_get_window_mgr ();
607         modest_window_mgr_close_all_windows (mgr);
608
609         /* note: when modest-tny-account-store is finalized,
610            it will automatically set all network connections
611            to offline */
612
613 /*      gtk_main_quit (); */
614 }
615
616 void
617 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
618 {
619         gboolean ret_value;
620
621         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
622
623 /*      if (MODEST_IS_MSG_VIEW_WINDOW (win)) { */
624 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
625 /*      } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) { */
626 /*              gboolean ret_value; */
627 /*              g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value); */
628 /*      } else if (MODEST_IS_WINDOW (win)) { */
629 /*              gtk_widget_destroy (GTK_WIDGET (win)); */
630 /*      } else { */
631 /*              g_return_if_reached (); */
632 /*      } */
633 }
634
635 void
636 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
637 {
638         GtkClipboard *clipboard = NULL;
639         gchar *selection = NULL;
640
641         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
642         selection = gtk_clipboard_wait_for_text (clipboard);
643
644         /* Question: why is the clipboard being used here? 
645          * It doesn't really make a lot of sense. */
646
647         if (selection)
648         {
649                 modest_address_book_add_address (selection);
650                 g_free (selection);
651         }
652 }
653
654 void
655 modest_ui_actions_on_accounts (GtkAction *action, 
656                                ModestWindow *win)
657 {
658         /* This is currently only implemented for Maemo */
659         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE)) {
660                 if (!modest_ui_actions_run_account_setup_wizard (win)) 
661                         g_debug ("%s: wizard was already running", __FUNCTION__);
662                 
663                 return;
664         } else {
665                 /* Show the list of accounts */
666                 GtkWindow *account_win = GTK_WINDOW (modest_account_view_window_new ());
667                 
668                 /* The accounts dialog must be modal */
669                 modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), GTK_WINDOW (account_win), (GtkWindow *) win);
670                 modest_utils_show_dialog_and_forget (GTK_WINDOW (win), GTK_DIALOG (account_win)); 
671         }
672 }
673
674 void
675 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
676 {
677         /* This is currently only implemented for Maemo,
678          * because it requires an API (libconic) to detect different connection 
679          * possiblities.
680          */
681 #ifndef MODEST_TOOLKIT_GTK /* Defined in config.h */
682         
683         /* Create the window if necessary: */
684         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
685         modest_connection_specific_smtp_window_fill_with_connections (
686                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), 
687                 modest_runtime_get_account_mgr());
688
689         /* Show the window: */
690         modest_window_mgr_set_modal (modest_runtime_get_window_mgr (), 
691                                      GTK_WINDOW (specific_window), (GtkWindow *) win);
692         gtk_widget_show (specific_window);
693 #endif /* !MODEST_TOOLKIT_GTK */
694 }
695
696 void
697 modest_ui_actions_compose_msg(ModestWindow *win,
698                               const gchar *to_str,
699                               const gchar *cc_str,
700                               const gchar *bcc_str,
701                               const gchar *subject_str,
702                               const gchar *body_str,
703                               GSList *attachments,
704                               gboolean set_as_modified)
705 {
706         gchar *account_name = NULL;
707         TnyMsg *msg = NULL;
708         TnyAccount *account = NULL;
709         TnyFolder *folder = NULL;
710         gchar *from_str = NULL, *signature = NULL, *body = NULL;
711         gboolean use_signature = FALSE;
712         ModestWindow *msg_win = NULL;
713         ModestAccountMgr *mgr = modest_runtime_get_account_mgr();
714         ModestTnyAccountStore *store = modest_runtime_get_account_store();
715         GnomeVFSFileSize total_size, allowed_size;
716
717         /* we check for low-mem */
718         if (modest_platform_check_memory_low (win, TRUE))
719                 goto cleanup;
720
721 #ifdef MODEST_TOOLKIT_HILDON2
722         account_name = g_strdup (modest_window_get_active_account(win));
723 #endif
724         if (!account_name) {
725                 account_name = modest_account_mgr_get_default_account(mgr);
726         }
727         if (!account_name) {
728                 g_printerr ("modest: no account found\n");
729                 goto cleanup;
730         }
731         account = modest_tny_account_store_get_server_account (store, account_name, TNY_ACCOUNT_TYPE_STORE);
732         if (!account) {
733                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
734                 goto cleanup;
735         }
736         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
737         if (!folder) {
738                 g_printerr ("modest: failed to find Drafts folder\n");
739                 goto cleanup;
740         }
741         from_str = modest_account_mgr_get_from_string (mgr, account_name);
742         if (!from_str) {
743                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
744                 goto cleanup;
745         }
746
747         signature = modest_account_mgr_get_signature (mgr, account_name, &use_signature);
748         if (body_str != NULL) {
749                 body = use_signature ? g_strconcat(body_str, "\n--\n", signature, NULL) : g_strdup(body_str);
750         } else {
751                 body = use_signature ? g_strconcat("\n--\n", signature, NULL) : g_strdup("");
752         }
753
754         msg = modest_tny_msg_new (to_str, from_str, cc_str, bcc_str, subject_str, body, NULL, NULL, NULL);
755         if (!msg) {
756                 g_printerr ("modest: failed to create new msg\n");
757                 goto cleanup;
758         }
759
760         /* Create and register edit window */
761         /* This is destroyed by TODO. */
762         total_size = 0;
763         allowed_size = MODEST_MAX_ATTACHMENT_SIZE;
764         msg_win = modest_msg_edit_window_new (msg, account_name, FALSE);
765
766         if (!modest_window_mgr_register_window (modest_runtime_get_window_mgr(), msg_win, NULL)) {
767                 gtk_widget_destroy (GTK_WIDGET (msg_win));
768                 goto cleanup;
769         }
770         modest_msg_edit_window_set_modified (MODEST_MSG_EDIT_WINDOW (msg_win), set_as_modified);
771         gtk_widget_show_all (GTK_WIDGET (msg_win));
772
773         while (attachments) {
774                 total_size +=
775                         modest_msg_edit_window_attach_file_one((ModestMsgEditWindow *)msg_win,
776                                                                attachments->data, allowed_size);
777
778                 if (total_size > allowed_size) {
779                         g_warning ("%s: total size: %u",
780                                    __FUNCTION__, (unsigned int)total_size);
781                         break;
782                 }
783                 allowed_size -= total_size;
784
785                 attachments = g_slist_next(attachments);
786         }
787
788 cleanup:
789         g_free (from_str);
790         g_free (signature);
791         g_free (body);
792         g_free (account_name);
793         if (account) 
794                 g_object_unref (G_OBJECT(account));
795         if (folder)
796                 g_object_unref (G_OBJECT(folder));
797         if (msg)
798                 g_object_unref (G_OBJECT(msg));
799 }
800
801 void
802 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
803 {
804         /* if there are no accounts yet, just show the wizard */
805         if (!modest_account_mgr_has_accounts (modest_runtime_get_account_mgr(), TRUE))
806                 if (!modest_ui_actions_run_account_setup_wizard (win))
807                         return;
808                 
809         modest_ui_actions_compose_msg(win, NULL, NULL, NULL, NULL, NULL, NULL, FALSE);
810 }
811
812
813 gboolean 
814 modest_ui_actions_msg_retrieval_check (ModestMailOperation *mail_op,
815                                        TnyHeader *header,
816                                        TnyMsg *msg)
817 {
818         ModestMailOperationStatus status;
819
820         /* If there is no message or the operation was not successful */
821         status = modest_mail_operation_get_status (mail_op);
822         if (!msg || status != MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
823                 const GError *error;
824
825                 /* If it's a memory low issue, then show a banner */
826                 error = modest_mail_operation_get_error (mail_op);
827                 if (error && error->domain == MODEST_MAIL_OPERATION_ERROR &&
828                     error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
829                         GObject *source = modest_mail_operation_get_source (mail_op);
830                         modest_platform_run_information_dialog (GTK_IS_WINDOW (source) ? GTK_WINDOW (source) : NULL,
831                                                                 dgettext("ke-recv","memr_ib_operation_disabled"),
832                                                                 TRUE);
833                         g_object_unref (source);
834                 }
835
836                 if (error && ((error->code == TNY_SERVICE_ERROR_NO_SUCH_MESSAGE) ||
837                               error->code == TNY_SERVICE_ERROR_MESSAGE_NOT_AVAILABLE)) {
838                         gchar *subject, *msg;
839                         subject = tny_header_dup_subject (header);
840                         if (!subject)
841                                 subject = g_strdup (_("mail_va_no_subject"));;
842                         msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"),
843                                                subject);
844                         modest_platform_run_information_dialog (NULL, msg, FALSE);
845                         g_free (msg);
846                         g_free (subject);
847                 }
848
849                 /* Remove the header from the preregistered uids */
850                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),  
851                                                      header);
852
853                 return FALSE;
854         }
855
856         return TRUE;
857 }
858
859 typedef struct {
860         guint idle_handler;
861         gchar *message;
862         GtkWidget *banner;
863 } OpenMsgBannerInfo;
864
865 typedef struct {
866         GtkTreeModel *model;
867         TnyList *headers;
868         OpenMsgBannerInfo *banner_info;
869         GHashTable *row_refs_per_header;
870 } OpenMsgHelper;
871
872 gboolean
873 open_msg_banner_idle (gpointer userdata)
874 {
875         OpenMsgBannerInfo *banner_info = (OpenMsgBannerInfo *) userdata;
876
877         gdk_threads_enter ();
878         banner_info->idle_handler = 0;
879         banner_info->banner = modest_platform_animation_banner (NULL, NULL, banner_info->message);
880         if (banner_info)
881                 g_object_ref (banner_info->banner);
882         
883         gdk_threads_leave ();
884
885         return FALSE;
886         
887 }
888
889 static void
890 open_msg_cb (ModestMailOperation *mail_op, 
891              TnyHeader *header,  
892              gboolean canceled,
893              TnyMsg *msg, 
894              GError *err,
895              gpointer user_data)
896 {
897         ModestWindowMgr *mgr = NULL;
898         ModestWindow *parent_win = NULL;
899         ModestWindow *win = NULL;
900         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
901         gchar *account = NULL;
902         TnyFolder *folder;
903         gboolean open_in_editor = FALSE;
904         OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
905         
906         /* Do nothing if there was any problem with the mail
907            operation. The error will be shown by the error_handler of
908            the mail operation */
909         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
910                 return;
911
912         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
913         folder = tny_header_get_folder (header);
914
915         /* Mark header as read */
916         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
917
918         /* Gets folder type (OUTBOX headers will be opened in edit window */
919         if (modest_tny_folder_is_local_folder (folder)) {
920                 folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
921                 if (folder_type == TNY_FOLDER_TYPE_INVALID)
922                         g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
923         }
924
925                 
926         if (folder_type == TNY_FOLDER_TYPE_OUTBOX) {
927                 TnyTransportAccount *traccount = NULL;
928                 ModestTnyAccountStore *accstore = modest_runtime_get_account_store();
929                 traccount = modest_tny_account_store_get_transport_account_from_outbox_header(accstore, header);
930                 if (traccount) {
931                         ModestTnySendQueue *send_queue = NULL;
932                         ModestTnySendQueueStatus status;
933                         gchar *msg_id;
934                         account = g_strdup(modest_tny_account_get_parent_modest_account_name_for_server_account(
935                                                    TNY_ACCOUNT(traccount)));
936                         send_queue = modest_runtime_get_send_queue(traccount, TRUE);
937                         if (TNY_IS_SEND_QUEUE (send_queue)) {
938                                 msg_id = modest_tny_send_queue_get_msg_id (header);
939                                 status = modest_tny_send_queue_get_msg_status(send_queue, msg_id);
940                                 /* Only open messages in outbox with the editor if they are in Failed state */
941                                 if (status == MODEST_TNY_SEND_QUEUE_FAILED) {
942                                         open_in_editor = TRUE;
943                                 }
944                                 g_free(msg_id);
945                         }
946                         g_object_unref(traccount);
947                 } else {
948                         g_warning("Cannot get transport account for message in outbox!!");
949                 }
950         } else if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
951                 open_in_editor = TRUE; /* Open in editor if the message is in the Drafts folder */
952         }
953
954         /* Get account */
955         if (!account)
956                 account = g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
957         if (!account)
958                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
959         
960         if (open_in_editor) {
961                 ModestAccountMgr *mgr = modest_runtime_get_account_mgr ();
962                 gchar *from_header = NULL, *acc_name;
963
964                 from_header = tny_header_dup_from (header);
965
966                 /* we cannot edit without a valid account... */
967                 if (!modest_account_mgr_has_accounts(mgr, TRUE)) {
968                         if (!modest_ui_actions_run_account_setup_wizard(parent_win)) {
969                                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
970                                                                      header);
971                                 g_free (from_header);
972                                 goto cleanup;
973                         }
974                 }
975
976                 acc_name = modest_utils_get_account_name_from_recipient (from_header);
977                 g_free (from_header);
978                 if (acc_name) {
979                         g_free (account);
980                         account = acc_name;
981                 }
982
983                 win = modest_msg_edit_window_new (msg, account, TRUE);
984         } else {
985                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
986                 
987                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
988                         GtkTreeRowReference *row_reference;
989
990                         row_reference = (GtkTreeRowReference *) g_hash_table_lookup (helper->row_refs_per_header, header);
991                                 
992                         win = modest_msg_view_window_new_with_header_model (msg, account, (const gchar*) uid,
993                                                                             helper->model, row_reference);
994                 } else {
995                         win = modest_msg_view_window_new_for_attachment (msg, account, (const gchar*) uid);
996                 }
997                 g_free (uid);
998         }
999         
1000         /* Register and show new window */
1001         if (win != NULL) {
1002                 mgr = modest_runtime_get_window_mgr ();
1003                 if (!modest_window_mgr_register_window (mgr, win, NULL)) {
1004                         gtk_widget_destroy (GTK_WIDGET (win));
1005                         goto cleanup;
1006                 }
1007                 gtk_widget_show_all (GTK_WIDGET(win));
1008         }
1009
1010         /* Update toolbar dimming state */
1011         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
1012                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
1013         }
1014
1015 cleanup:
1016         /* Free */
1017         g_free(account);
1018         g_object_unref (parent_win);
1019         g_object_unref (folder);
1020 }
1021
1022 static gboolean
1023 is_memory_full_error (GError *error)
1024 {
1025         gboolean enough_free_space = TRUE;
1026         GnomeVFSURI *cache_dir_uri;
1027         const gchar *cache_dir;
1028         GnomeVFSFileSize free_space;
1029
1030         cache_dir = tny_account_store_get_cache_dir (TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
1031         cache_dir_uri = gnome_vfs_uri_new (cache_dir);
1032         if (gnome_vfs_get_volume_free_space (cache_dir_uri, &free_space) == GNOME_VFS_OK) {
1033                 if (free_space < MIN_FREE_SPACE)
1034                         enough_free_space = FALSE;
1035         }
1036         gnome_vfs_uri_unref (cache_dir_uri);
1037
1038         if ((error->code == TNY_SYSTEM_ERROR_MEMORY ||
1039              /* When asking for a mail and no space left on device
1040                 tinymail returns this error */
1041              error->code == TNY_SERVICE_ERROR_MESSAGE_NOT_AVAILABLE ||
1042              /* When the folder summary could not be read or
1043                 written */
1044              error->code == TNY_IO_ERROR_WRITE ||
1045              error->code == TNY_IO_ERROR_READ) && 
1046             !enough_free_space) {
1047                 return TRUE;
1048         } else {
1049                 return FALSE;
1050         }
1051 }
1052
1053 static gboolean
1054 check_memory_full_error (GtkWidget *parent_window, GError *err)
1055 {
1056         if (err == NULL)
1057                 return FALSE;
1058
1059         if (is_memory_full_error (err))
1060                 modest_platform_information_banner (parent_window,
1061                                                     NULL, dgettext("ke-recv",
1062                                                                    "cerm_device_memory_full"));
1063         else if (err->code == TNY_SYSTEM_ERROR_MEMORY)
1064                 /* If the account was created in memory full
1065                    conditions then tinymail won't be able to
1066                    connect so it'll return this error code */                           
1067                 modest_platform_information_banner (parent_window,
1068                                                     NULL, _("emev_ui_imap_inbox_select_error"));
1069         else
1070                 return FALSE;
1071
1072         return TRUE;
1073 }
1074
1075 void
1076 modest_ui_actions_disk_operations_error_handler (ModestMailOperation *mail_op,
1077                                                  gpointer user_data)
1078 {
1079         const GError *error;
1080         GObject *win = NULL;
1081         ModestMailOperationStatus status;
1082
1083         win = modest_mail_operation_get_source (mail_op);
1084         error = modest_mail_operation_get_error (mail_op);
1085         status = modest_mail_operation_get_status (mail_op);
1086
1087         /* If the mail op has been cancelled then it's not an error:
1088            don't show any message */
1089         if (status != MODEST_MAIL_OPERATION_STATUS_CANCELED) {
1090                 if (is_memory_full_error ((GError *) error)) {
1091                         modest_platform_information_banner ((GtkWidget *) win,
1092                                                             NULL, dgettext("ke-recv",
1093                                                                            "cerm_device_memory_full"));
1094                 } else if (error->code == TNY_SYSTEM_ERROR_MEMORY) {
1095                         modest_platform_information_banner ((GtkWidget *) win,
1096                                                             NULL, _("emev_ui_imap_inbox_select_error"));
1097                 } else if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
1098                            error->code == MODEST_MAIL_OPERATION_ERROR_FILE_IO) {
1099                         modest_platform_information_banner ((GtkWidget *) win,
1100                                                             NULL, dgettext ("hildon-common-strings", "sfil_ni_unable_to_open_file_not_found"));
1101                 } else if (user_data) {
1102                         modest_platform_information_banner ((GtkWidget *) win, 
1103                                                             NULL, user_data);
1104                 }
1105         }
1106
1107         if (win)
1108                 g_object_unref (win);
1109 }
1110
1111 /**
1112  * Returns the account a list of headers belongs to. It returns a
1113  * *new* reference so don't forget to unref it
1114  */
1115 static TnyAccount*
1116 get_account_from_header_list (TnyList *headers)
1117 {
1118         TnyAccount *account = NULL;
1119
1120         if (tny_list_get_length (headers) > 0) {
1121                 TnyIterator *iter = tny_list_create_iterator (headers);
1122                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
1123                 TnyFolder *folder = tny_header_get_folder (header);
1124                 
1125                 if (!folder) {
1126                         g_object_unref (header);
1127                         
1128                         while (!tny_iterator_is_done (iter)) {
1129                                 header = TNY_HEADER (tny_iterator_get_current (iter));
1130                                 folder = tny_header_get_folder (header);
1131                                 if (folder) 
1132                                         break;
1133                                 g_object_unref (header);
1134                                 header = NULL;
1135                                 tny_iterator_next (iter);
1136                         }
1137                 }
1138
1139                 if (folder) {
1140                         account = tny_folder_get_account (folder);
1141                         g_object_unref (folder);
1142                 }
1143                 
1144                 if (header)
1145                         g_object_unref (header);
1146                 
1147                 g_object_unref (iter);
1148         }
1149         return account;
1150 }
1151
1152 static void 
1153 foreach_unregister_headers (gpointer data,
1154                             gpointer user_data)
1155 {
1156         ModestWindowMgr *mgr = (ModestWindowMgr *) user_data;
1157         TnyHeader *header = TNY_HEADER (data);
1158
1159         modest_window_mgr_unregister_header (mgr, header);
1160 }
1161
1162 static void
1163 open_msgs_helper_destroyer (gpointer user_data)
1164 {
1165         OpenMsgHelper *helper = (OpenMsgHelper *) user_data;
1166
1167         if (helper->banner_info) {
1168                 g_free (helper->banner_info->message);
1169                 if (helper->banner_info->idle_handler > 0) {
1170                         g_source_remove (helper->banner_info->idle_handler);
1171                         helper->banner_info->idle_handler = 0;
1172                 }
1173                 if (helper->banner_info->banner != NULL) {
1174                         gtk_widget_destroy (helper->banner_info->banner);
1175                         g_object_unref (helper->banner_info->banner);
1176                         helper->banner_info->banner = NULL;
1177                 }
1178                 g_slice_free (OpenMsgBannerInfo, helper->banner_info);
1179                 helper->banner_info = NULL;
1180         }
1181         g_object_unref (helper->model);
1182         g_object_unref (helper->headers);
1183         g_hash_table_destroy (helper->row_refs_per_header);
1184         g_slice_free (OpenMsgHelper, helper);
1185 }
1186
1187 static void
1188 open_msgs_performer(gboolean canceled, 
1189                     GError *err,
1190                     GtkWindow *parent_window,
1191                     TnyAccount *account,
1192                     gpointer user_data)
1193 {
1194         ModestMailOperation *mail_op = NULL;
1195         gchar *error_msg;
1196         ModestProtocolType proto;
1197         TnyList *not_opened_headers;
1198         TnyConnectionStatus status;
1199         gboolean show_open_draft = FALSE;
1200         OpenMsgHelper *helper = NULL;
1201
1202         helper = (OpenMsgHelper *) user_data;
1203         not_opened_headers = helper->headers;
1204
1205         status = tny_account_get_connection_status (account);
1206         if (err || canceled) {
1207                 /* Unregister the already registered headers */
1208                 tny_list_foreach (not_opened_headers, foreach_unregister_headers, 
1209                                   modest_runtime_get_window_mgr ());
1210                 /* Free the helper */
1211                 open_msgs_helper_destroyer (helper);
1212
1213                 /* In memory full conditions we could get this error here */
1214                 check_memory_full_error ((GtkWidget *) parent_window, err);
1215
1216                 goto clean;
1217         }
1218
1219         /* Get the error message depending on the protocol */
1220         proto = modest_tny_account_get_protocol_type (account);
1221         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
1222                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
1223         }
1224         
1225         /* Create the error messages */
1226         if (tny_list_get_length (not_opened_headers) == 1) {
1227                 ModestProtocol *protocol;
1228                 ModestProtocolRegistry *protocol_registry;
1229                 TnyIterator *iter;
1230                 TnyHeader *header;
1231                 gchar *subject;
1232
1233                 protocol_registry = modest_runtime_get_protocol_registry ();
1234                 iter = tny_list_create_iterator (not_opened_headers);
1235                 header = TNY_HEADER (tny_iterator_get_current (iter));
1236                 subject = tny_header_dup_subject (header);
1237
1238                 protocol = modest_protocol_registry_get_protocol_by_type (protocol_registry, proto);
1239                 error_msg = modest_protocol_get_translation (protocol, MODEST_PROTOCOL_TRANSLATION_MSG_NOT_AVAILABLE, subject);
1240                 if (subject)
1241                         g_free (subject);
1242                 g_object_unref (header);
1243                 g_object_unref (iter);
1244                 
1245                 if (error_msg == NULL) {
1246                         error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1247                 }
1248
1249                 if (modest_protocol_registry_protocol_type_has_tag (protocol_registry,
1250                                                                     proto,
1251                                                                     MODEST_PROTOCOL_REGISTRY_LOCAL_STORE_PROTOCOLS)) { 
1252                         TnyHeader *header;
1253                         TnyFolder *folder;
1254                         TnyIterator *iter;
1255                         TnyFolderType folder_type;
1256
1257                         iter = tny_list_create_iterator (not_opened_headers);
1258                         header = TNY_HEADER (tny_iterator_get_current (iter));
1259                         folder = tny_header_get_folder (header);
1260                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type (folder);
1261                         show_open_draft = (folder_type == TNY_FOLDER_TYPE_DRAFTS);
1262                         g_object_unref (folder);
1263                         g_object_unref (header);
1264                         g_object_unref (iter);
1265                 }
1266         } else {
1267                 error_msg = g_strdup (_("mail_ni_ui_folder_get_msg_folder_error"));
1268         }
1269
1270         /* Create the mail operation */
1271         mail_op = 
1272                 modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
1273                                                                modest_ui_actions_disk_operations_error_handler,
1274                                                                error_msg, g_free);
1275         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1276                                          mail_op);
1277
1278         if (show_open_draft) {
1279                 helper->banner_info = g_slice_new (OpenMsgBannerInfo);
1280                 helper->banner_info->message = g_strdup (_("mail_ib_opening_draft_message"));
1281                 helper->banner_info->banner = NULL;
1282                 helper->banner_info->idle_handler = g_timeout_add (500, open_msg_banner_idle, 
1283                                                                    helper->banner_info);
1284         }
1285
1286         modest_mail_operation_get_msgs_full (mail_op,
1287                                              not_opened_headers,
1288                                              open_msg_cb,
1289                                              helper,
1290                                              open_msgs_helper_destroyer);
1291
1292         /* Frees */
1293  clean:
1294         if (mail_op)
1295                 g_object_unref (mail_op);
1296         g_object_unref (account);
1297 }
1298
1299 /*
1300  * This function is used by both modest_ui_actions_on_open and
1301  * modest_ui_actions_on_header_activated. This way we always do the
1302  * same when trying to open messages.
1303  */
1304 static void
1305 open_msgs_from_headers (TnyList *headers, ModestWindow *win)
1306 {
1307         ModestWindowMgr *mgr = NULL;
1308         TnyIterator *iter = NULL, *iter_not_opened = NULL;
1309         TnyList *not_opened_headers = NULL;
1310         TnyHeaderFlags flags = 0;
1311         TnyAccount *account;
1312         gint uncached_msgs = 0;
1313         GtkWidget *header_view;
1314         GtkTreeModel *model;
1315         GHashTable *refs_for_headers;
1316         OpenMsgHelper *helper;
1317         GtkTreeSelection *sel;
1318         GList *sel_list = NULL, *sel_list_iter = NULL;
1319                 
1320         g_return_if_fail (headers != NULL);
1321
1322         /* Check that only one message is selected for opening */
1323         if (tny_list_get_length (headers) != 1) {
1324                 modest_platform_information_banner ((win) ? GTK_WIDGET (win) : NULL,
1325                                                     NULL, _("mcen_ib_select_one_message"));
1326                 return;
1327         }
1328
1329         mgr = modest_runtime_get_window_mgr ();
1330         iter = tny_list_create_iterator (headers);
1331
1332         /* Get the account */
1333         account = get_account_from_header_list (headers);
1334
1335         if (!account)
1336                 return;
1337
1338         /* Get the selections, we need to get the references to the
1339            rows here because the treeview/model could dissapear (the
1340            user might want to select another folder)*/
1341         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1342                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1343         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
1344         model = gtk_tree_view_get_model (GTK_TREE_VIEW (header_view));
1345         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
1346         refs_for_headers = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, 
1347                                                   (GDestroyNotify) gtk_tree_row_reference_free);
1348
1349         /* Look if we already have a message view for each header. If
1350            true, then remove the header from the list of headers to
1351            open */
1352         sel_list_iter = sel_list;
1353         not_opened_headers = tny_simple_list_new ();
1354         while (!tny_iterator_is_done (iter) && sel_list_iter) {
1355
1356                 ModestWindow *window = NULL;
1357                 TnyHeader *header = NULL;
1358                 gboolean found = FALSE;
1359                 
1360                 header = TNY_HEADER (tny_iterator_get_current (iter));
1361                 if (header)
1362                         flags = tny_header_get_flags (header);
1363
1364                 window = NULL;
1365                 found = modest_window_mgr_find_registered_header (mgr, header, &window);
1366                 
1367                 /* Do not open again the message and present the
1368                    window to the user */
1369                 if (found) {
1370                         if (window) {
1371 #ifndef MODEST_TOOLKIT_HILDON2
1372                                 gtk_window_present (GTK_WINDOW (window));
1373 #endif
1374                         } else {
1375                                 /* the header has been registered already, we don't do
1376                                  * anything but wait for the window to come up*/
1377                                 g_debug ("header %p already registered, waiting for window", header);
1378                         }
1379                 } else {
1380                         GtkTreeRowReference *row_reference;
1381
1382                         tny_list_append (not_opened_headers, G_OBJECT (header));
1383                         /* Create a new row reference and add it to the hash table */
1384                         row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list_iter->data);
1385                         g_hash_table_insert (refs_for_headers, header, row_reference);
1386                 }
1387
1388                 if (header)
1389                         g_object_unref (header);
1390
1391                 /* Go to next */
1392                 tny_iterator_next (iter);
1393                 sel_list_iter = g_list_next (sel_list_iter);
1394         }
1395         g_object_unref (iter);
1396         iter = NULL;
1397         g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
1398         g_list_free (sel_list);
1399
1400         /* Open each message */
1401         if (tny_list_get_length (not_opened_headers) == 0) {
1402                 g_hash_table_destroy (refs_for_headers);
1403                 goto cleanup;
1404         }
1405         
1406         /* If some messages would have to be downloaded, ask the user to 
1407          * make a connection. It's generally easier to do this here (in the mainloop) 
1408          * than later in a thread:
1409          */
1410         if (tny_list_get_length (not_opened_headers) > 0) {
1411                 uncached_msgs = header_list_count_uncached_msgs (not_opened_headers);
1412
1413                 if (uncached_msgs > 0) {
1414                         /* Allways download if we are online. */
1415                         if (!tny_device_is_online (modest_runtime_get_device ())) {
1416                                 gint response;
1417
1418                                 /* If ask for user permission to download the messages */
1419                                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1420                                                                                     ngettext("mcen_nc_get_msg",
1421                                                                                              "mcen_nc_get_msgs",
1422                                                                                              uncached_msgs));
1423
1424                                 /* End if the user does not want to continue */
1425                                 if (response == GTK_RESPONSE_CANCEL) {
1426                                         g_hash_table_destroy (refs_for_headers);
1427                                         goto cleanup;
1428                                 }
1429                         }
1430                 }
1431         }
1432
1433         /* Register the headers before actually creating the windows: */
1434         iter_not_opened = tny_list_create_iterator (not_opened_headers);
1435         while (!tny_iterator_is_done (iter_not_opened)) {
1436                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
1437                 if (header) {
1438                         modest_window_mgr_register_header (mgr, header, NULL);
1439                         g_object_unref (header);
1440                 }
1441                 tny_iterator_next (iter_not_opened);
1442         }
1443         g_object_unref (iter_not_opened);
1444         iter_not_opened = NULL;
1445
1446         /* Create the helper. We need to get a reference to the model
1447            here because it could change while the message is readed
1448            (the user could switch between folders) */
1449         helper = g_slice_new (OpenMsgHelper);
1450         helper->model = g_object_ref (model);
1451         helper->headers = g_object_ref (not_opened_headers);
1452         helper->row_refs_per_header = refs_for_headers;
1453         helper->banner_info = NULL;
1454
1455         /* Connect to the account and perform */
1456         if (uncached_msgs > 0) {
1457                 modest_platform_connect_and_perform ((GtkWindow *) win, TRUE, g_object_ref (account), 
1458                                                      open_msgs_performer, helper);
1459         } else {
1460                 /* Call directly the performer, do not need to connect */
1461                 open_msgs_performer (FALSE, NULL, (GtkWindow *) win, 
1462                                      g_object_ref (account), helper);
1463         }
1464 cleanup:
1465         /* Clean */
1466         if (account)
1467                 g_object_unref (account);
1468         if (not_opened_headers)
1469                 g_object_unref (not_opened_headers);
1470 }
1471
1472 void
1473 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
1474 {
1475         TnyList *headers;
1476         
1477         /* we check for low-mem; in that case, show a warning, and don't allow
1478          * opening
1479          */
1480         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
1481                 return;
1482
1483         /* Get headers */
1484         headers = get_selected_headers (win);
1485         if (!headers)
1486                 return;
1487
1488         /* Open them */
1489         open_msgs_from_headers (headers, win);
1490
1491         g_object_unref(headers);
1492 }
1493
1494 static ReplyForwardHelper*
1495 create_reply_forward_helper (ReplyForwardAction action, 
1496                              ModestWindow *win,
1497                              guint reply_forward_type,
1498                              TnyHeader *header)
1499 {
1500         ReplyForwardHelper *rf_helper = NULL;
1501         const gchar *active_acc = modest_window_get_active_account (win);
1502
1503         rf_helper = g_slice_new0 (ReplyForwardHelper);
1504         rf_helper->reply_forward_type = reply_forward_type;
1505         rf_helper->action = action;
1506         rf_helper->parent_window = (MODEST_IS_WINDOW (win)) ? GTK_WIDGET (win) : NULL;
1507         rf_helper->header = (header) ? g_object_ref (header) : NULL;
1508         rf_helper->account_name = (active_acc) ? 
1509                 g_strdup (active_acc) :
1510                 modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1511
1512         return rf_helper;
1513 }
1514
1515 static void
1516 free_reply_forward_helper (gpointer data)
1517 {
1518         ReplyForwardHelper *helper;
1519
1520         helper = (ReplyForwardHelper *) data;
1521         g_free (helper->account_name);
1522         if (helper->header)
1523                 g_object_unref (helper->header);
1524         g_slice_free (ReplyForwardHelper, helper);
1525 }
1526
1527 static void
1528 reply_forward_cb (ModestMailOperation *mail_op,  
1529                   TnyHeader *header, 
1530                   gboolean canceled,
1531                   TnyMsg *msg,
1532                   GError *err,
1533                   gpointer user_data)
1534 {
1535         TnyMsg *new_msg = NULL;
1536         ReplyForwardHelper *rf_helper;
1537         ModestWindow *msg_win = NULL;
1538         ModestEditType edit_type;
1539         gchar *from = NULL;
1540         TnyAccount *account = NULL;
1541         ModestWindowMgr *mgr = NULL;
1542         gchar *signature = NULL;
1543         gboolean use_signature;
1544
1545         /* If there was any error. The mail operation could be NULL,
1546            this means that we already have the message downloaded and
1547            that we didn't do a mail operation to retrieve it */
1548         rf_helper = (ReplyForwardHelper *) user_data;
1549         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1550                 goto cleanup;
1551
1552         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1553                                                    rf_helper->account_name);
1554         signature = modest_account_mgr_get_signature (modest_runtime_get_account_mgr(), 
1555                                                       rf_helper->account_name, 
1556                                                       &use_signature);
1557
1558         /* Create reply mail */
1559         switch (rf_helper->action) {
1560         case ACTION_REPLY:
1561                 new_msg = 
1562                         modest_tny_msg_create_reply_msg (msg, header, from, 
1563                                                          (use_signature) ? signature : NULL,
1564                                                          rf_helper->reply_forward_type,
1565                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1566                 break;
1567         case ACTION_REPLY_TO_ALL:
1568                 new_msg = 
1569                         modest_tny_msg_create_reply_msg (msg, header, from, 
1570                                                          (use_signature) ? signature : NULL, 
1571                                                          rf_helper->reply_forward_type,
1572                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1573                 edit_type = MODEST_EDIT_TYPE_REPLY;
1574                 break;
1575         case ACTION_FORWARD:
1576                 new_msg = 
1577                         modest_tny_msg_create_forward_msg (msg, from, (use_signature) ? signature : NULL, 
1578                                                            rf_helper->reply_forward_type);
1579                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1580                 break;
1581         default:
1582                 modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1583                                                      header);
1584                 g_return_if_reached ();
1585                 return;
1586         }
1587
1588         g_free (from);
1589         g_free (signature);
1590
1591         if (!new_msg) {
1592                 g_warning ("%s: failed to create message\n", __FUNCTION__);
1593                 goto cleanup;
1594         }
1595
1596         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1597                                                                        rf_helper->account_name,
1598                                                                        TNY_ACCOUNT_TYPE_STORE);
1599         if (!account) {
1600                 g_warning ("%s: failed to get tnyaccount for '%s'\n", __FUNCTION__, rf_helper->account_name);
1601                 goto cleanup;
1602         }
1603
1604         /* Create and register the windows */
1605         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name, FALSE);
1606         mgr = modest_runtime_get_window_mgr ();
1607         modest_window_mgr_register_window (mgr, msg_win, (ModestWindow *) rf_helper->parent_window);
1608
1609         if (rf_helper->parent_window != NULL) {
1610                 gdouble parent_zoom;
1611
1612                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1613                 modest_window_set_zoom (msg_win, parent_zoom);
1614         }
1615
1616         /* Show edit window */
1617         gtk_widget_show_all (GTK_WIDGET (msg_win));
1618
1619 cleanup:
1620         /* We always unregister the header because the message is
1621            forwarded or replied so the original one is no longer
1622            opened */
1623         modest_window_mgr_unregister_header (modest_runtime_get_window_mgr (),
1624                                              header);
1625         if (new_msg)
1626                 g_object_unref (G_OBJECT (new_msg));
1627         if (account)
1628                 g_object_unref (G_OBJECT (account));
1629         free_reply_forward_helper (rf_helper);
1630 }
1631
1632 /* Checks a list of headers. If any of them are not currently
1633  * downloaded (CACHED) then returns TRUE else returns FALSE.
1634  */
1635 static gint
1636 header_list_count_uncached_msgs (TnyList *header_list)
1637 {
1638         TnyIterator *iter;
1639         gint uncached_messages = 0;
1640
1641         iter = tny_list_create_iterator (header_list);
1642         while (!tny_iterator_is_done (iter)) {
1643                 TnyHeader *header;
1644
1645                 header = TNY_HEADER (tny_iterator_get_current (iter));
1646                 if (header) {
1647                         if (!(tny_header_get_flags (header) & TNY_HEADER_FLAG_CACHED))
1648                                 uncached_messages ++;
1649                         g_object_unref (header);
1650                 }
1651
1652                 tny_iterator_next (iter);
1653         }
1654         g_object_unref (iter);
1655
1656         return uncached_messages;
1657 }
1658
1659 /* Returns FALSE if the user does not want to download the
1660  * messages. Returns TRUE if the user allowed the download.
1661  */
1662 static gboolean
1663 connect_to_get_msg (ModestWindow *win,
1664                     gint num_of_uncached_msgs,
1665                     TnyAccount *account)
1666 {
1667         GtkResponseType response;
1668
1669         /* Allways download if we are online. */
1670         if (tny_device_is_online (modest_runtime_get_device ()))
1671                 return TRUE;
1672
1673         /* If offline, then ask for user permission to download the messages */
1674         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1675                         ngettext("mcen_nc_get_msg",
1676                         "mcen_nc_get_msgs",
1677                         num_of_uncached_msgs));
1678
1679         if (response == GTK_RESPONSE_CANCEL)
1680                 return FALSE;
1681
1682         return modest_platform_connect_and_wait((GtkWindow *) win, account);
1683 }
1684
1685 static void
1686 reply_forward_performer (gboolean canceled, 
1687                          GError *err,
1688                          GtkWindow *parent_window, 
1689                          TnyAccount *account, 
1690                          gpointer user_data)
1691 {
1692         ReplyForwardHelper *rf_helper = NULL;
1693         ModestMailOperation *mail_op;
1694
1695         rf_helper = (ReplyForwardHelper *) user_data;
1696
1697         if (canceled || err) {
1698                 free_reply_forward_helper (rf_helper);
1699                 return;
1700         }
1701
1702         /* Retrieve the message */
1703         modest_window_mgr_register_header (modest_runtime_get_window_mgr (), rf_helper->header, NULL);
1704         mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (parent_window),
1705                                                                  modest_ui_actions_disk_operations_error_handler,
1706                                                                  NULL, NULL);
1707         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1708         modest_mail_operation_get_msg (mail_op, rf_helper->header, TRUE, reply_forward_cb, rf_helper);
1709
1710         /* Frees */
1711         g_object_unref(mail_op);
1712 }
1713
1714 /*
1715  * Common code for the reply and forward actions
1716  */
1717 static void
1718 reply_forward (ReplyForwardAction action, ModestWindow *win)
1719 {
1720         ReplyForwardHelper *rf_helper = NULL;
1721         guint reply_forward_type;
1722         
1723         g_return_if_fail (MODEST_IS_WINDOW(win));
1724                         
1725         /* we check for low-mem; in that case, show a warning, and don't allow
1726          * reply/forward (because it could potentially require a lot of memory */
1727         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
1728                 return;
1729
1730
1731         /* we need an account when editing */
1732         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1733                 if (!modest_ui_actions_run_account_setup_wizard (win))
1734                         return;
1735         }
1736         
1737         reply_forward_type =
1738                 modest_conf_get_int (modest_runtime_get_conf (),
1739                                      (action == ACTION_FORWARD) ? 
1740                                      MODEST_CONF_FORWARD_TYPE :
1741                                      MODEST_CONF_REPLY_TYPE,
1742                                      NULL);
1743
1744         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1745                 TnyMsg *msg = NULL;
1746                 TnyHeader *header = NULL;
1747                 /* Get header and message. Do not free them here, the
1748                    reply_forward_cb must do it */
1749                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1750                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
1751
1752                 if (msg && header) {
1753                         /* Create helper */
1754                         rf_helper = create_reply_forward_helper (action, win, 
1755                                                                  reply_forward_type, header);
1756                         reply_forward_cb (NULL, header, FALSE, msg, NULL, rf_helper);
1757                 } else {
1758                         g_warning("%s: no message or header found in viewer\n", __FUNCTION__);
1759                 }
1760                 
1761                 if (msg)
1762                         g_object_unref (msg);
1763                 if (header)
1764                         g_object_unref (header);
1765         } else {
1766                 TnyHeader *header = NULL;
1767                 TnyIterator *iter;
1768                 gboolean do_retrieve = TRUE;
1769                 TnyList *header_list = NULL;
1770
1771                 header_list = get_selected_headers (win);
1772                 if (!header_list)
1773                         return;
1774                 /* Check that only one message is selected for replying */
1775                 if (tny_list_get_length (header_list) != 1) {
1776                         modest_platform_information_banner ((win) ? GTK_WIDGET (win) : NULL,
1777                                                             NULL, _("mcen_ib_select_one_message"));
1778                         g_object_unref (header_list);
1779                         return;
1780                 }
1781
1782                 /* Only reply/forward to one message */
1783                 iter = tny_list_create_iterator (header_list);
1784                 header = TNY_HEADER (tny_iterator_get_current (iter));
1785                 g_object_unref (iter);
1786
1787                 /* Retrieve messages */
1788                 do_retrieve = (action == ACTION_FORWARD) ||
1789                         (reply_forward_type != MODEST_TNY_MSG_REPLY_TYPE_CITE);
1790
1791                 if (do_retrieve) {
1792                         TnyAccount *account = NULL;
1793                         TnyFolder *folder = NULL;
1794                         gdouble download = TRUE;
1795                         guint uncached_msgs = 0;
1796
1797                         folder = tny_header_get_folder (header);
1798                         if (!folder)
1799                                 goto do_retrieve_frees;
1800                         account = tny_folder_get_account (folder);
1801                         if (!account)
1802                                 goto do_retrieve_frees;
1803
1804                         uncached_msgs = header_list_count_uncached_msgs (header_list);
1805
1806                         if (uncached_msgs > 0) {
1807                                 /* Allways download if we are online. */
1808                                 if (!tny_device_is_online (modest_runtime_get_device ())) {
1809                                         gint response;
1810                                         
1811                                         /* If ask for user permission to download the messages */
1812                                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1813                                                                                             ngettext("mcen_nc_get_msg",
1814                                                                                                      "mcen_nc_get_msgs",
1815                                                                                                      uncached_msgs));
1816                                         
1817                                         /* End if the user does not want to continue */
1818                                         if (response == GTK_RESPONSE_CANCEL)
1819                                                 download = FALSE;
1820                                 }
1821                         }
1822                         
1823                         if (download) {
1824                                 /* Create helper */
1825                                 rf_helper = create_reply_forward_helper (action, win, 
1826                                                                          reply_forward_type, header);
1827                                 if (uncached_msgs > 0) {
1828                                         modest_platform_connect_and_perform (GTK_WINDOW (win), 
1829                                                                              TRUE, account, 
1830                                                                              reply_forward_performer, 
1831                                                                              rf_helper);
1832                                 } else {
1833                                         reply_forward_performer (FALSE, NULL, GTK_WINDOW (win), 
1834                                                                  account, rf_helper);
1835                                 }
1836                         }
1837                 do_retrieve_frees:
1838                         if (account)
1839                                 g_object_unref (account);
1840                         if (folder)
1841                                 g_object_unref (folder);
1842                 } else {
1843                         reply_forward_cb (NULL, header, FALSE, NULL, NULL, rf_helper);
1844                 }
1845                 /* Frees */
1846                 g_object_unref (header_list);
1847                 g_object_unref (header);
1848         }
1849 }
1850
1851 void
1852 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1853 {
1854         g_return_if_fail (MODEST_IS_WINDOW(win));
1855
1856         reply_forward (ACTION_REPLY, win);
1857 }
1858
1859 void
1860 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1861 {
1862         g_return_if_fail (MODEST_IS_WINDOW(win));
1863
1864         reply_forward (ACTION_FORWARD, win);
1865 }
1866
1867 void
1868 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1869 {
1870         g_return_if_fail (MODEST_IS_WINDOW(win));
1871
1872         reply_forward (ACTION_REPLY_TO_ALL, win);
1873 }
1874
1875 void 
1876 modest_ui_actions_on_next (GtkAction *action, 
1877                            ModestWindow *window)
1878 {
1879         if (MODEST_IS_MAIN_WINDOW (window)) {
1880                 GtkWidget *header_view;
1881
1882                 header_view = modest_main_window_get_child_widget (
1883                                 MODEST_MAIN_WINDOW(window),
1884                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1885                 if (!header_view)
1886                         return;
1887         
1888                 modest_header_view_select_next (
1889                                 MODEST_HEADER_VIEW(header_view)); 
1890         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1891                 modest_msg_view_window_select_next_message (
1892                                 MODEST_MSG_VIEW_WINDOW (window));
1893         } else {
1894                 g_return_if_reached ();
1895         }
1896 }
1897
1898 void 
1899 modest_ui_actions_on_prev (GtkAction *action, 
1900                            ModestWindow *window)
1901 {
1902         g_return_if_fail (MODEST_IS_WINDOW(window));
1903
1904         if (MODEST_IS_MAIN_WINDOW (window)) {
1905                 GtkWidget *header_view;
1906                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1907                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1908                 if (!header_view)
1909                         return;
1910                 
1911                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1912         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1913                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1914         } else {
1915                 g_return_if_reached ();
1916         }
1917 }
1918
1919 void 
1920 modest_ui_actions_on_sort (GtkAction *action, 
1921                            ModestWindow *window)
1922 {
1923         g_return_if_fail (MODEST_IS_WINDOW(window));
1924
1925         if (MODEST_IS_MAIN_WINDOW (window)) {
1926                 GtkWidget *header_view;
1927                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1928                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
1929                 if (!header_view) {
1930                         modest_platform_information_banner (NULL, NULL, _CS("ckdg_ib_nothing_to_sort"));
1931
1932                         return;
1933                 }
1934
1935                 /* Show sorting dialog */
1936                 modest_utils_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);        
1937         }
1938 }
1939
1940 static void
1941 new_messages_arrived (ModestMailOperation *self, 
1942                       TnyList *new_headers,
1943                       gpointer user_data)
1944 {
1945         GObject *source;
1946         gboolean show_visual_notifications;
1947
1948         source = modest_mail_operation_get_source (self);
1949         show_visual_notifications = (source) ? FALSE : TRUE;
1950         if (source)
1951                 g_object_unref (source);
1952
1953         /* Notify new messages have been downloaded. If the
1954            send&receive was invoked by the user then do not show any
1955            visual notification, only play a sound and activate the LED
1956            (for the Maemo version) */
1957         if (TNY_IS_LIST(new_headers) && (tny_list_get_length (new_headers)) > 0)
1958                 modest_platform_on_new_headers_received (new_headers, 
1959                                                          show_visual_notifications);
1960
1961 }
1962
1963 gboolean
1964 retrieve_all_messages_cb (GObject *source,
1965                           guint num_msgs,
1966                           guint retrieve_limit)
1967 {
1968         GtkWindow *window;
1969         gchar *msg;
1970         gint response;
1971
1972         window = GTK_WINDOW (source);
1973         msg = g_strdup_printf (_("mail_nc_msg_count_limit_exceeded"), 
1974                                num_msgs, retrieve_limit);
1975
1976         /* Ask the user if they want to retrieve all the messages */
1977         response = 
1978                 modest_platform_run_confirmation_dialog_with_buttons (window, msg,
1979                                                                       _("mcen_bd_get_all"),
1980                                                                       _("mcen_bd_newest_only"));
1981         /* Free and return */
1982         g_free (msg);
1983         return (response == GTK_RESPONSE_ACCEPT) ? TRUE : FALSE;
1984 }
1985
1986 typedef struct {
1987         TnyAccount *account;
1988         ModestWindow *win;
1989         gchar *account_name;
1990         gboolean poke_status;
1991         gboolean interactive;
1992         ModestMailOperation *mail_op;
1993 } SendReceiveInfo;
1994
1995 static void
1996 do_send_receive_performer (gboolean canceled, 
1997                            GError *err,
1998                            GtkWindow *parent_window, 
1999                            TnyAccount *account, 
2000                            gpointer user_data)
2001 {
2002         SendReceiveInfo *info;
2003
2004         info = (SendReceiveInfo *) user_data;
2005
2006         if (err || canceled) {
2007                 /* In memory full conditions we could get this error here */
2008                 check_memory_full_error ((GtkWidget *) parent_window, err);
2009
2010                 if (info->mail_op) {
2011                         modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (),
2012                                                             info->mail_op);
2013                 }
2014                 goto clean;
2015         }
2016
2017         /* Set send/receive operation in progress */    
2018         if (info->win && MODEST_IS_MAIN_WINDOW (info->win)) {
2019                 modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW (info->win));
2020         }
2021
2022         if (info->win && MODEST_IS_MAIN_WINDOW (info->win))
2023                 g_signal_connect (G_OBJECT (info->mail_op), "operation-finished", 
2024                                   G_CALLBACK (on_send_receive_finished), 
2025                                   info->win);
2026
2027         /* Send & receive. */
2028         modest_mail_operation_update_account (info->mail_op, info->account_name, info->poke_status, info->interactive,
2029                                               (info->win) ? retrieve_all_messages_cb : NULL, 
2030                                               new_messages_arrived, info->win);
2031         
2032  clean:
2033         /* Frees */
2034         if (info->mail_op)
2035                 g_object_unref (G_OBJECT (info->mail_op));
2036         if (info->account_name)
2037                 g_free (info->account_name);
2038         if (info->win)
2039                 g_object_unref (info->win);
2040         if (info->account)
2041                 g_object_unref (info->account);
2042         g_slice_free (SendReceiveInfo, info);
2043 }
2044
2045 /*
2046  * This function performs the send & receive required actions. The
2047  * window is used to create the mail operation. Typically it should
2048  * always be the main window, but we pass it as argument in order to
2049  * be more flexible.
2050  */
2051 void
2052 modest_ui_actions_do_send_receive (const gchar *account_name, 
2053                                    gboolean force_connection,
2054                                    gboolean poke_status,
2055                                    gboolean interactive,
2056                                    ModestWindow *win)
2057 {
2058         gchar *acc_name = NULL;
2059         SendReceiveInfo *info;
2060         ModestTnyAccountStore *acc_store;
2061
2062         /* If no account name was provided then get the current account, and if
2063            there is no current account then pick the default one: */
2064         if (!account_name) {
2065                 if (win)
2066                         acc_name = g_strdup (modest_window_get_active_account (win));
2067                 if (!acc_name)
2068                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
2069                 if (!acc_name) {
2070                         g_printerr ("modest: cannot get default account\n");
2071                         return;
2072                 }
2073         } else {
2074                 acc_name = g_strdup (account_name);
2075         }
2076
2077         acc_store = modest_runtime_get_account_store ();
2078
2079         /* Create the info for the connect and perform */
2080         info = g_slice_new (SendReceiveInfo);
2081         info->account_name = acc_name;
2082         info->win = (win) ? g_object_ref (win) : NULL;
2083         info->poke_status = poke_status;
2084         info->interactive = interactive;
2085         info->account = modest_tny_account_store_get_server_account (acc_store, acc_name,
2086                                                                      TNY_ACCOUNT_TYPE_STORE);
2087         /* We need to create the operation here, because otherwise it
2088            could happen that the queue emits the queue-empty signal
2089            while we're trying to connect the account */
2090         info->mail_op = modest_mail_operation_new_with_error_handling ((info->win) ? G_OBJECT (info->win) : NULL,
2091                                                                        modest_ui_actions_disk_operations_error_handler,
2092                                                                        NULL, NULL);
2093         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), info->mail_op);
2094
2095         /* Invoke the connect and perform */
2096         modest_platform_connect_and_perform ((win) ? GTK_WINDOW (win) : NULL, 
2097                                              force_connection, info->account, 
2098                                              do_send_receive_performer, info);
2099 }
2100
2101
2102 static void
2103 modest_ui_actions_do_cancel_send (const gchar *account_name,  
2104                                   ModestWindow *win)
2105 {
2106         TnyTransportAccount *transport_account;
2107         TnySendQueue *send_queue = NULL;
2108         GError *error = NULL;
2109
2110         /* Get transport account */
2111         transport_account =
2112                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2113                                       (modest_runtime_get_account_store(),
2114                                        account_name,
2115                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2116         if (!transport_account) {
2117                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2118                 goto frees;
2119         }
2120
2121         /* Get send queue*/
2122         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account, TRUE));
2123         if (!TNY_IS_SEND_QUEUE(send_queue)) {
2124                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
2125                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
2126                              "modest: could not find send queue for account\n");
2127         } else {
2128                 /* Cancel the current send */
2129                 tny_account_cancel (TNY_ACCOUNT (transport_account));
2130
2131                 /* Suspend all pending messages */
2132                 tny_send_queue_cancel (send_queue, TNY_SEND_QUEUE_CANCEL_ACTION_SUSPEND, &error);
2133         }
2134
2135  frees:
2136         if (transport_account != NULL) 
2137                 g_object_unref (G_OBJECT (transport_account));
2138 }
2139
2140 static void
2141 modest_ui_actions_cancel_send_all (ModestWindow *win) 
2142 {
2143         GSList *account_names, *iter;
2144
2145         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
2146                                                           TRUE);
2147
2148         iter = account_names;
2149         while (iter) {                  
2150                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
2151                 iter = g_slist_next (iter);
2152         }
2153
2154         modest_account_mgr_free_account_names (account_names);
2155         account_names = NULL;
2156 }
2157
2158 void
2159 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
2160
2161 {
2162         /* Check if accounts exist */
2163         gboolean accounts_exist = 
2164                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2165         
2166         /* If not, allow the user to create an account before trying to send/receive. */
2167         if (!accounts_exist)
2168                 modest_ui_actions_on_accounts (NULL, win);
2169         
2170         /* Cancel all sending operaitons */     
2171         modest_ui_actions_cancel_send_all (win);
2172 }
2173
2174 /*
2175  * Refreshes all accounts. This function will be used by automatic
2176  * updates
2177  */
2178 void
2179 modest_ui_actions_do_send_receive_all (ModestWindow *win, 
2180                                        gboolean force_connection,
2181                                        gboolean poke_status,
2182                                        gboolean interactive)
2183 {
2184         GSList *account_names, *iter;
2185
2186         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
2187                                                           TRUE);
2188
2189         iter = account_names;
2190         while (iter) {                  
2191                 modest_ui_actions_do_send_receive ((const char*) iter->data, 
2192                                                    force_connection, 
2193                                                    poke_status, interactive, win);
2194                 iter = g_slist_next (iter);
2195         }
2196
2197         modest_account_mgr_free_account_names (account_names);
2198         account_names = NULL;
2199 }
2200
2201 /*
2202  * Handler of the click on Send&Receive button in the main toolbar
2203  */
2204 void
2205 modest_ui_actions_on_send_receive (GtkAction *action, ModestWindow *win)
2206 {
2207         /* Check if accounts exist */
2208         gboolean accounts_exist;
2209
2210         accounts_exist =
2211                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
2212         
2213         /* If not, allow the user to create an account before trying to send/receive. */
2214         if (!accounts_exist)
2215                 modest_ui_actions_on_accounts (NULL, win);
2216         
2217         /* Refresh the current folder. The if is always TRUE it's just an extra check */
2218         if (MODEST_IS_MAIN_WINDOW (win)) {
2219                 GtkWidget *folder_view;
2220                 TnyFolderStore *folder_store;
2221
2222                 folder_view = 
2223                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
2224                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2225                 if (!folder_view)
2226                         return;
2227                 
2228                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2229         
2230                 if (folder_store)
2231                         g_object_unref (folder_store);
2232         }       
2233         
2234         /* Refresh the active account. Force the connection if needed
2235            and poke the status of all folders */
2236         modest_ui_actions_do_send_receive (NULL, TRUE, TRUE, TRUE, win);
2237 }
2238
2239
2240 void
2241 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
2242 {
2243         ModestConf *conf;
2244         GtkWidget *header_view;
2245         
2246         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2247
2248         header_view = modest_main_window_get_child_widget (main_window,
2249                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2250         if (!header_view)
2251                 return;
2252
2253         conf = modest_runtime_get_conf ();
2254         
2255         /* what is saved/restored is depending on the style; thus; we save with
2256          * old style, then update the style, and restore for this new style
2257          */
2258         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
2259         
2260         if (modest_header_view_get_style
2261             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
2262                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2263                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
2264         else
2265                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
2266                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
2267
2268         modest_widget_memory_restore (conf, G_OBJECT(header_view),
2269                                       MODEST_CONF_HEADER_VIEW_KEY);
2270 }
2271
2272
2273 void 
2274 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
2275                                       TnyHeader *header,
2276                                       ModestMainWindow *main_window)
2277 {
2278         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2279         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
2280         
2281         /* in the case the folder is empty, show the empty folder message and focus
2282          * folder view */
2283         if (!header && gtk_widget_is_focus (GTK_WIDGET (header_view))) {
2284                 if (modest_header_view_is_empty (header_view)) {
2285                         TnyFolder *folder = modest_header_view_get_folder (header_view);
2286                         GtkWidget *folder_view = 
2287                                 modest_main_window_get_child_widget (main_window,
2288                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2289                         if (folder != NULL) {
2290                                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), folder, FALSE);
2291                                 g_object_unref (folder);
2292                         }
2293                         gtk_widget_grab_focus (GTK_WIDGET (folder_view));
2294                         return;
2295                 }
2296         }
2297         /* If no header has been selected then exit */
2298         if (!header)
2299                 return;
2300
2301         /* Update focus */
2302         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
2303             gtk_widget_grab_focus (GTK_WIDGET(header_view));
2304
2305         /* Update toolbar dimming state */
2306         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2307         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2308 }
2309
2310 void
2311 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
2312                                        TnyHeader *header,
2313                                        ModestMainWindow *main_window)
2314 {
2315         TnyList *headers;
2316
2317         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2318
2319         if (!header)
2320                 return;
2321
2322         if (modest_header_view_count_selected_headers (header_view) > 1) {
2323                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_select_one_message"));
2324                 return;
2325         }
2326
2327         /* we check for low-mem; in that case, show a warning, and don't allow
2328          * activating headers
2329          */
2330         if (modest_platform_check_memory_low (MODEST_WINDOW(main_window), TRUE))
2331                 return;
2332
2333         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2334
2335         headers = modest_header_view_get_selected_headers (header_view);
2336
2337         open_msgs_from_headers (headers, MODEST_WINDOW (main_window));
2338
2339         g_object_unref (headers);
2340 }
2341
2342 static void
2343 set_active_account_from_tny_account (TnyAccount *account,
2344                                      ModestWindow *window)
2345 {
2346         const gchar *server_acc_name = tny_account_get_id (account);
2347         
2348         /* We need the TnyAccount provided by the
2349            account store because that is the one that
2350            knows the name of the Modest account */
2351         TnyAccount *modest_server_account = modest_server_account = 
2352                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
2353                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
2354                                                              server_acc_name);
2355         if (!modest_server_account) {
2356                 g_warning ("%s: could not get tny account\n", __FUNCTION__);
2357                 return;
2358         }
2359
2360         /* Update active account, but only if it's not a pseudo-account */
2361         if ((!modest_tny_account_is_virtual_local_folders(modest_server_account)) &&
2362             (!modest_tny_account_is_memory_card_account(modest_server_account))) {
2363                 const gchar *modest_acc_name = 
2364                         modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
2365                 if (modest_acc_name)
2366                         modest_window_set_active_account (window, modest_acc_name);
2367         }
2368         
2369         g_object_unref (modest_server_account);
2370 }
2371
2372
2373 static void
2374 folder_refreshed_cb (ModestMailOperation *mail_op, 
2375                      TnyFolder *folder, 
2376                      gpointer user_data)
2377 {
2378         ModestMainWindow *win = NULL;
2379         GtkWidget *folder_view;
2380         const GError *error;
2381
2382         g_return_if_fail (TNY_IS_FOLDER (folder));
2383
2384         win = MODEST_MAIN_WINDOW (user_data);
2385
2386         /* Check if the operation failed due to memory low conditions */
2387         error = modest_mail_operation_get_error (mail_op);
2388         if (error && error->domain == MODEST_MAIL_OPERATION_ERROR && 
2389             error->code == MODEST_MAIL_OPERATION_ERROR_LOW_MEMORY) {
2390                 modest_platform_run_information_dialog (GTK_WINDOW (win),
2391                                                         dgettext("ke-recv","memr_ib_operation_disabled"),
2392                                                         TRUE);
2393                 return;
2394         }
2395
2396         folder_view = 
2397                 modest_main_window_get_child_widget(win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2398
2399         if (folder_view) {
2400                 TnyFolderStore *current_folder;
2401
2402                 current_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2403                 if (current_folder) {
2404                         gboolean different = ((TnyFolderStore *) folder != current_folder);
2405                         g_object_unref (current_folder);
2406                         if (different)
2407                                 return;
2408                 }
2409         }
2410
2411         /* Check if folder is empty and set headers view contents style */
2412         if (tny_folder_get_all_count (folder) == 0)
2413                 modest_main_window_set_contents_style (win,
2414                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
2415
2416 }
2417
2418 void 
2419 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
2420                                                TnyFolderStore *folder_store, 
2421                                                gboolean selected,
2422                                                ModestMainWindow *main_window)
2423 {
2424         ModestConf *conf;
2425         GtkWidget *header_view;
2426
2427         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2428
2429         header_view = modest_main_window_get_child_widget(main_window,
2430                                                           MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2431         if (!header_view)
2432                 return;
2433         
2434         conf = modest_runtime_get_conf ();
2435
2436         if (TNY_IS_ACCOUNT (folder_store)) {
2437                 if (selected) {
2438                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
2439                         
2440                         /* Show account details */
2441                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
2442                 }
2443         } else {
2444                 if (TNY_IS_FOLDER (folder_store) && selected) {
2445                         TnyAccount *account;
2446                         const gchar *account_name = NULL;
2447
2448                         /* Update the active account */
2449                         account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
2450                         if (account) {
2451                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
2452                                 account_name = 
2453                                         modest_tny_account_get_parent_modest_account_name_for_server_account (account);
2454                                 g_object_unref (account);
2455                                 account = NULL;
2456                         }
2457
2458                         /* Set the header style by default, it could
2459                            be changed later by the refresh callback to
2460                            empty */
2461                         modest_main_window_set_contents_style (main_window, 
2462                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
2463
2464                         /* Set folder on header view. This function
2465                            will call tny_folder_refresh_async so we
2466                            pass a callback that will be called when
2467                            finished. We use that callback to set the
2468                            empty view if there are no messages */
2469                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
2470                                                        TNY_FOLDER (folder_store),
2471                                                        TRUE,
2472                                                        folder_refreshed_cb,
2473                                                        main_window);
2474                         
2475                         /* Restore configuration. We need to do this
2476                            *after* the set_folder because the widget
2477                            memory asks the header view about its
2478                            folder  */
2479                         modest_widget_memory_restore (modest_runtime_get_conf (), 
2480                                                       G_OBJECT(header_view),
2481                                                       MODEST_CONF_HEADER_VIEW_KEY);
2482                 } else {
2483                         /* No need to save the header view
2484                            configuration for Maemo because it only
2485                            saves the sorting stuff and that it's
2486                            already being done by the sort
2487                            dialog. Remove it when the GNOME version
2488                            has the same behaviour */
2489 #ifdef MODEST_TOOLKIT_GTK
2490                         if (modest_main_window_get_contents_style (main_window) ==
2491                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
2492                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
2493                                                            MODEST_CONF_HEADER_VIEW_KEY);
2494 #endif
2495                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
2496                 }
2497         }
2498
2499         /* Update dimming state */
2500         modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (main_window));
2501         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
2502 }
2503
2504 void 
2505 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
2506                                      ModestWindow *win)
2507 {
2508         GtkWidget *dialog;
2509         gchar *txt, *item;
2510         gboolean online;
2511
2512         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
2513         
2514         online = tny_device_is_online (modest_runtime_get_device());
2515
2516         if (online) {
2517                 /* already online -- the item is simply not there... */
2518                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
2519                                                  GTK_DIALOG_MODAL,
2520                                                  GTK_MESSAGE_WARNING,
2521                                                  GTK_BUTTONS_NONE,
2522                                                  _("The %s you selected cannot be found"),
2523                                                  item);
2524                 gtk_dialog_add_button (GTK_DIALOG (dialog),_("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
2525                 gtk_dialog_run (GTK_DIALOG(dialog));
2526         } else {
2527                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
2528                                                       GTK_WINDOW (win),
2529                                                       GTK_DIALOG_MODAL,
2530                                                       _("mcen_bd_dialog_cancel"),
2531                                                       GTK_RESPONSE_REJECT,
2532                                                       _("mcen_bd_dialog_ok"),
2533                                                       GTK_RESPONSE_ACCEPT,
2534                                                       NULL);
2535                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
2536                                          "Do you want to get online?"), item);
2537                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
2538                                     gtk_label_new (txt), FALSE, FALSE, 0);
2539                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2540                 g_free (txt);
2541
2542                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
2543                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2544                         /* TODO: Comment about why is this commented out: */
2545                         /* modest_platform_connect_and_wait (); */
2546                 }
2547         }
2548         gtk_widget_destroy (dialog);
2549 }
2550
2551 void
2552 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
2553                                      ModestWindow *win)
2554 {
2555         /* g_message ("%s %s", __FUNCTION__, link); */
2556 }       
2557
2558
2559 void
2560 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
2561                                         ModestWindow *win)
2562 {
2563         modest_platform_activate_uri (link);
2564 }
2565
2566 void
2567 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
2568                                           ModestWindow *win)
2569 {
2570         modest_platform_show_uri_popup (link);
2571 }
2572
2573 void
2574 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
2575                                              ModestWindow *win)
2576 {               
2577         /* we check for low-mem; in that case, show a warning, and don't allow
2578          * viewing attachments
2579          */
2580         if (modest_platform_check_memory_low (MODEST_WINDOW(win), TRUE))
2581                 return;
2582
2583         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
2584 }
2585
2586 void
2587 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
2588                                           const gchar *address,
2589                                           ModestWindow *win)
2590 {
2591         /* g_message ("%s %s", __FUNCTION__, address); */
2592 }
2593
2594 static void
2595 on_save_to_drafts_cb (ModestMailOperation *mail_op, 
2596                       TnyMsg *saved_draft,
2597                       gpointer user_data)
2598 {
2599         ModestMsgEditWindow *edit_window;
2600         ModestMainWindow *win;
2601
2602         /* FIXME. Make the header view sensitive again. This is a
2603          * temporary hack. See modest_ui_actions_on_save_to_drafts()
2604          * for details */
2605         win = MODEST_MAIN_WINDOW(modest_window_mgr_get_main_window(
2606                                          modest_runtime_get_window_mgr(), FALSE));
2607         if (win != NULL) {
2608                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2609                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2610                 if (hdrview) gtk_widget_set_sensitive(hdrview, TRUE);
2611         }
2612
2613         edit_window = MODEST_MSG_EDIT_WINDOW (user_data);
2614
2615         /* Set draft is there was no error */
2616         if (!modest_mail_operation_get_error (mail_op))
2617                 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2618
2619         g_object_unref(edit_window);
2620 }
2621
2622 static gboolean
2623 enough_space_for_message (ModestMsgEditWindow *edit_window,
2624                           MsgData *data)
2625 {
2626         TnyAccountStore *acc_store;
2627         guint64 available_disk, expected_size;
2628         gint parts_count;
2629         guint64 parts_size;
2630
2631         /* Check size */
2632         acc_store = TNY_ACCOUNT_STORE (modest_runtime_get_account_store());
2633         available_disk = modest_utils_get_available_space (NULL);
2634         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2635         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2636                                                       data->html_body,
2637                                                       parts_count,
2638                                                       parts_size);
2639
2640         /* Double check: memory full condition or message too big */
2641         if (available_disk < MIN_FREE_SPACE || 
2642             expected_size > available_disk) {
2643
2644                 modest_platform_information_banner (NULL, NULL, 
2645                                                     dgettext("ke-recv", 
2646                                                              "cerm_device_memory_full"));
2647                 return FALSE;
2648         }
2649
2650         /*
2651          * djcb: if we're in low-memory state, we only allow for
2652          * saving messages smaller than
2653          * MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE (see modest-defs.h) this
2654          * should still allow for sending anything critical...
2655          */
2656         if ((expected_size > MODEST_MAX_LOW_MEMORY_MESSAGE_SIZE) &&
2657             modest_platform_check_memory_low (MODEST_WINDOW(edit_window), TRUE))
2658                 return FALSE;
2659
2660         /*
2661          * djcb: we also make sure that the attachments are smaller than the max size
2662          * this is for the case where we'd try to forward a message with attachments 
2663          * bigger than our max allowed size, or sending an message from drafts which
2664          * somehow got past our checks when attaching.
2665          */
2666         if (expected_size > MODEST_MAX_ATTACHMENT_SIZE) {
2667                 modest_platform_run_information_dialog (
2668                         GTK_WINDOW(edit_window),
2669                         dgettext("ke-recv","memr_ib_operation_disabled"),
2670                         TRUE);
2671                 return FALSE;
2672         }
2673
2674         return TRUE;
2675 }
2676
2677 gboolean
2678 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2679 {
2680         TnyTransportAccount *transport_account;
2681         ModestMailOperation *mail_operation;
2682         MsgData *data;
2683         gchar *account_name, *from;
2684         ModestAccountMgr *account_mgr;
2685         gboolean had_error = FALSE;
2686         ModestMainWindow *win = NULL;
2687
2688         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
2689         
2690         data = modest_msg_edit_window_get_msg_data (edit_window);
2691
2692         /* Check size */
2693         if (!enough_space_for_message (edit_window, data)) {
2694                 modest_msg_edit_window_free_msg_data (edit_window, data);
2695                 return FALSE;
2696         }
2697
2698         account_name = g_strdup (data->account_name);
2699         account_mgr = modest_runtime_get_account_mgr();
2700         if (!account_name)
2701                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2702         if (!account_name) 
2703                 account_name = modest_account_mgr_get_default_account (account_mgr);
2704         if (!account_name) {
2705                 g_printerr ("modest: no account found\n");
2706                 modest_msg_edit_window_free_msg_data (edit_window, data);
2707                 return FALSE;
2708         }
2709
2710         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2711                 account_name = g_strdup (data->account_name);
2712         }
2713
2714         transport_account =
2715                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2716                                       (modest_runtime_get_account_store (),
2717                                        account_name,
2718                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2719         if (!transport_account) {
2720                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2721                 g_free (account_name);
2722                 modest_msg_edit_window_free_msg_data (edit_window, data);
2723                 return FALSE;
2724         }
2725         from = modest_account_mgr_get_from_string (account_mgr, account_name);
2726
2727         /* Create the mail operation */         
2728         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler,
2729                                                                         NULL, NULL);
2730         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2731
2732         modest_mail_operation_save_to_drafts (mail_operation,
2733                                               transport_account,
2734                                               data->draft_msg,
2735                                               from,
2736                                               data->to, 
2737                                               data->cc, 
2738                                               data->bcc,
2739                                               data->subject, 
2740                                               data->plain_body, 
2741                                               data->html_body,
2742                                               data->attachments,
2743                                               data->images,
2744                                               data->priority_flags,
2745                                               on_save_to_drafts_cb,
2746                                               g_object_ref(edit_window));
2747
2748 #ifdef MODEST_TOOLKIT_HILDON2
2749         /* In hildon2 we always show the information banner on saving to drafts.
2750          * It will be a system information banner in this case.
2751          */
2752         gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2753         modest_platform_information_banner (NULL, NULL, text);
2754         g_free (text);
2755 #else
2756         /* Use the main window as the parent of the banner, if the
2757            main window does not exist it won't be shown, if the parent
2758            window exists then it's properly shown. We don't use the
2759            editor window because it could be closed (save to drafts
2760            could happen after closing the window */
2761         win = (ModestMainWindow *)
2762                 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
2763         if (win) {
2764                 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2765                 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
2766                 g_free (text);
2767         }
2768 #endif
2769         modest_msg_edit_window_set_modified (edit_window, FALSE);
2770
2771         /* Frees */
2772         g_free (from);
2773         g_free (account_name);
2774         g_object_unref (G_OBJECT (transport_account));
2775         g_object_unref (G_OBJECT (mail_operation));
2776
2777         modest_msg_edit_window_free_msg_data (edit_window, data);
2778
2779         /* ** FIXME **
2780          * If the drafts folder is selected then make the header view
2781          * insensitive while the message is being saved to drafts
2782          * (it'll be sensitive again in on_save_to_drafts_cb()). This
2783          * is not very clean but it avoids letting the drafts folder
2784          * in an inconsistent state: the user could edit the message
2785          * being saved and undesirable things would happen.
2786          * In the average case the user won't notice anything at
2787          * all. In the worst case (the user is editing a really big
2788          * file from Drafts) the header view will be insensitive
2789          * during the saving process (10 or 20 seconds, depending on
2790          * the message). Anyway this is just a quick workaround: once
2791          * we find a better solution it should be removed
2792          * See NB#65125 (commend #18) for details.
2793          */
2794         if (!had_error && win != NULL) {
2795                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
2796                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
2797                 if (view != NULL) {
2798                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
2799                         if (folder) {
2800                                 if (modest_tny_folder_is_local_folder(folder)) {
2801                                         TnyFolderType folder_type;
2802                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
2803                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
2804                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2805                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2806                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
2807                                         }
2808                                 }
2809                         }
2810                         if (folder != NULL) g_object_unref(folder);
2811                 }
2812         }
2813
2814         return !had_error;
2815 }
2816
2817 /* For instance, when clicking the Send toolbar button when editing a message: */
2818 gboolean
2819 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2820 {
2821         TnyTransportAccount *transport_account = NULL;
2822         gboolean had_error = FALSE;
2823         MsgData *data;
2824         ModestAccountMgr *account_mgr;
2825         gchar *account_name;
2826         gchar *from;
2827         ModestMailOperation *mail_operation;
2828
2829         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
2830
2831         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2832                 return TRUE;
2833         
2834         data = modest_msg_edit_window_get_msg_data (edit_window);
2835
2836         /* Check size */
2837         if (!enough_space_for_message (edit_window, data)) {
2838                 modest_msg_edit_window_free_msg_data (edit_window, data);
2839                 return FALSE;
2840         }
2841
2842         account_mgr = modest_runtime_get_account_mgr();
2843         account_name = g_strdup (data->account_name);
2844         if (!account_name)
2845                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2846
2847         if (!account_name) 
2848                 account_name = modest_account_mgr_get_default_account (account_mgr);
2849                 
2850         if (!account_name) {
2851                 modest_msg_edit_window_free_msg_data (edit_window, data);
2852                 /* Run account setup wizard */
2853                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
2854                         return TRUE;
2855                 }
2856         }
2857         
2858         /* Get the currently-active transport account for this modest account: */
2859         if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
2860                 transport_account = 
2861                         TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2862                                               (modest_runtime_get_account_store (), 
2863                                                account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
2864         }
2865         
2866         if (!transport_account) {
2867                 modest_msg_edit_window_free_msg_data (edit_window, data);
2868                 /* Run account setup wizard */
2869                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
2870                         return TRUE;
2871         }
2872         
2873
2874         /* Create the mail operation */
2875         from = modest_account_mgr_get_from_string (account_mgr, account_name);
2876         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler, NULL, NULL);
2877         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2878
2879         modest_mail_operation_send_new_mail (mail_operation,
2880                                              transport_account,
2881                                              data->draft_msg,
2882                                              from,
2883                                              data->to,
2884                                              data->cc, 
2885                                              data->bcc,
2886                                              data->subject, 
2887                                              data->plain_body, 
2888                                              data->html_body,
2889                                              data->attachments,
2890                                              data->images,
2891                                              data->priority_flags);
2892
2893         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2894                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
2895
2896
2897         if (modest_mail_operation_get_error (mail_operation) != NULL) {
2898                 const GError *error = modest_mail_operation_get_error (mail_operation);
2899                 if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
2900                     error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
2901                         g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
2902                         modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
2903                         had_error = TRUE;
2904                 }
2905         }
2906                                              
2907         /* Free data: */
2908         g_free (from);
2909         g_free (account_name);
2910         g_object_unref (G_OBJECT (transport_account));
2911         g_object_unref (G_OBJECT (mail_operation));
2912
2913         modest_msg_edit_window_free_msg_data (edit_window, data);
2914
2915         if (!had_error) {
2916                 modest_msg_edit_window_set_sent (edit_window, TRUE);
2917
2918                 /* Save settings and close the window: */
2919                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2920         }
2921
2922         return !had_error;
2923 }
2924
2925 void 
2926 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2927                                   ModestMsgEditWindow *window)
2928 {
2929         ModestMsgEditFormatState *format_state = NULL;
2930
2931         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2932         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2933
2934         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2935                 return;
2936
2937         format_state = modest_msg_edit_window_get_format_state (window);
2938         g_return_if_fail (format_state != NULL);
2939
2940         format_state->bold = gtk_toggle_action_get_active (action);
2941         modest_msg_edit_window_set_format_state (window, format_state);
2942         g_free (format_state);
2943         
2944 }
2945
2946 void 
2947 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2948                                      ModestMsgEditWindow *window)
2949 {
2950         ModestMsgEditFormatState *format_state = NULL;
2951
2952         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2953         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2954
2955         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2956                 return;
2957
2958         format_state = modest_msg_edit_window_get_format_state (window);
2959         g_return_if_fail (format_state != NULL);
2960
2961         format_state->italics = gtk_toggle_action_get_active (action);
2962         modest_msg_edit_window_set_format_state (window, format_state);
2963         g_free (format_state);
2964         
2965 }
2966
2967 void 
2968 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2969                                      ModestMsgEditWindow *window)
2970 {
2971         ModestMsgEditFormatState *format_state = NULL;
2972
2973         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2974         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2975
2976         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2977                 return;
2978
2979         format_state = modest_msg_edit_window_get_format_state (window);
2980         g_return_if_fail (format_state != NULL);
2981
2982         format_state->bullet = gtk_toggle_action_get_active (action);
2983         modest_msg_edit_window_set_format_state (window, format_state);
2984         g_free (format_state);
2985         
2986 }
2987
2988 void 
2989 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2990                                      GtkRadioAction *selected,
2991                                      ModestMsgEditWindow *window)
2992 {
2993         ModestMsgEditFormatState *format_state = NULL;
2994         GtkJustification value;
2995
2996         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2997
2998         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2999                 return;
3000
3001         value = gtk_radio_action_get_current_value (selected);
3002
3003         format_state = modest_msg_edit_window_get_format_state (window);
3004         g_return_if_fail (format_state != NULL);
3005
3006         format_state->justification = value;
3007         modest_msg_edit_window_set_format_state (window, format_state);
3008         g_free (format_state);
3009 }
3010
3011 void 
3012 modest_ui_actions_on_select_editor_color (GtkAction *action,
3013                                           ModestMsgEditWindow *window)
3014 {
3015         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3016         g_return_if_fail (GTK_IS_ACTION (action));
3017
3018         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3019                 return;
3020
3021         modest_msg_edit_window_select_color (window);
3022 }
3023
3024 void 
3025 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
3026                                                      ModestMsgEditWindow *window)
3027 {
3028         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3029         g_return_if_fail (GTK_IS_ACTION (action));
3030
3031         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3032                 return;
3033
3034         modest_msg_edit_window_select_background_color (window);
3035 }
3036
3037 void 
3038 modest_ui_actions_on_insert_image (GtkAction *action,
3039                                    ModestMsgEditWindow *window)
3040 {
3041         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3042         g_return_if_fail (GTK_IS_ACTION (action));
3043
3044
3045         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3046                 return;
3047
3048         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
3049                 return;
3050
3051         modest_msg_edit_window_insert_image (window);
3052 }
3053
3054 void 
3055 modest_ui_actions_on_attach_file (GtkAction *action,
3056                                   ModestMsgEditWindow *window)
3057 {
3058         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3059         g_return_if_fail (GTK_IS_ACTION (action));
3060
3061         if (modest_platform_check_memory_low (MODEST_WINDOW(window), TRUE))
3062                 return;
3063         
3064         modest_msg_edit_window_offer_attach_file (window);
3065 }
3066
3067 void 
3068 modest_ui_actions_on_remove_attachments (GtkAction *action,
3069                                          ModestMsgEditWindow *window)
3070 {
3071         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3072         g_return_if_fail (GTK_IS_ACTION (action));
3073
3074         modest_msg_edit_window_remove_attachments (window, NULL);
3075 }
3076
3077
3078 #ifndef MODEST_TOOLKIT_GTK
3079 typedef struct {
3080         guint handler;
3081         gchar *name;
3082         GtkWindow *win;
3083         TnyFolderStore *folder;
3084 } CreateFolderHelper;
3085
3086 static gboolean
3087 show_create_folder_in_timeout (gpointer data)
3088 {
3089         CreateFolderHelper *helper = (CreateFolderHelper *) data;
3090
3091         /* Remove the timeout ASAP, we can not wait until the dialog
3092            is shown because it could take a lot of time and so the
3093            timeout could be called twice or more times */
3094         g_source_remove (helper->handler);
3095
3096         gdk_threads_enter ();
3097         do_create_folder (helper->win, helper->folder, helper->name);
3098         gdk_threads_leave ();
3099
3100         g_object_unref (helper->win);
3101         g_object_unref (helper->folder);
3102         g_free (helper->name);
3103         g_slice_free (CreateFolderHelper, helper);
3104
3105         return FALSE;
3106 }
3107 #endif
3108
3109 static void
3110 do_create_folder_cb (ModestMailOperation *mail_op,
3111                      TnyFolderStore *parent_folder, 
3112                      TnyFolder *new_folder,
3113                      gpointer user_data)
3114 {
3115         gchar *suggested_name = (gchar *) user_data;
3116         GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
3117
3118         if (modest_mail_operation_get_error (mail_op)) {
3119
3120                 /* Show an error. If there was some problem writing to
3121                    disk, show it, otherwise show the generic folder
3122                    create error. We do it here and not in an error
3123                    handler because the call to do_create_folder will
3124                    stop the main loop in a gtk_dialog_run and then,
3125                    the message won't be shown until that dialog is
3126                    closed */
3127                 modest_ui_actions_disk_operations_error_handler (mail_op,
3128                                                                  _("mail_in_ui_folder_create_error"));
3129
3130                 /* Try again. Do *NOT* show any error because the mail
3131                    operations system will do it for us because we
3132                    created the mail_op with new_with_error_handler */
3133 #ifndef MODEST_TOOLKIT_GTK
3134                 CreateFolderHelper *helper;
3135                 helper = g_slice_new0 (CreateFolderHelper);
3136                 helper->name = g_strdup (suggested_name);
3137                 helper->folder = g_object_ref (parent_folder);
3138                 helper->win = g_object_ref (source_win);
3139
3140                 /* Ugly but neccesary stuff. The problem is that the
3141                    dialog when is shown calls a function that destroys
3142                    all the temporary windows, so the banner is
3143                    destroyed */
3144                 helper->handler = g_timeout_add (2000, show_create_folder_in_timeout, helper);
3145 #else
3146                 do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
3147 #endif
3148         } else {
3149                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
3150                  * FIXME: any other? */         
3151                 GtkWidget *folder_view;
3152
3153                 if (MODEST_IS_MAIN_WINDOW(source_win)) 
3154                         folder_view = 
3155                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
3156                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3157                 else
3158                         folder_view =
3159                                 get_folder_view_from_move_to_dialog (GTK_WIDGET(source_win));
3160                 
3161                 /* Select the newly created folder. It could happen
3162                    that the widget is no longer there (i.e. the window
3163                    has been destroyed, so we need to check this */
3164                 if (folder_view)
3165                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
3166                                                           new_folder, FALSE);
3167                 g_object_unref (new_folder);
3168         }
3169         /* Free. Note that the first time it'll be NULL so noop */
3170         g_free (suggested_name);
3171         g_object_unref (source_win);
3172 }
3173
3174 static void
3175 do_create_folder (GtkWindow *parent_window, 
3176                   TnyFolderStore *parent_folder, 
3177                   const gchar *suggested_name)
3178 {
3179         gint result;
3180         gchar *folder_name = NULL;
3181
3182         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
3183                                                         parent_folder,
3184                                                         (gchar *) suggested_name,
3185                                                         &folder_name);
3186         
3187         if (result == GTK_RESPONSE_ACCEPT) {
3188                 ModestMailOperation *mail_op;
3189                 
3190                 mail_op  = modest_mail_operation_new ((GObject *) parent_window);
3191                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3192                                                  mail_op);
3193                 modest_mail_operation_create_folder (mail_op,
3194                                                      parent_folder,
3195                                                      (const gchar *) folder_name,
3196                                                      do_create_folder_cb,
3197                                                      folder_name);
3198                 g_object_unref (mail_op);
3199         }
3200 }
3201
3202 static void
3203 create_folder_performer (gboolean canceled, 
3204                          GError *err,
3205                          GtkWindow *parent_window, 
3206                          TnyAccount *account, 
3207                          gpointer user_data)
3208 {
3209         TnyFolderStore *parent_folder = TNY_FOLDER_STORE (user_data);
3210
3211         if (canceled || err) {
3212                 /* In memory full conditions we could get this error here */
3213                 check_memory_full_error ((GtkWidget *) parent_window, err);
3214                 goto frees;
3215         }
3216
3217         /* Run the new folder dialog */
3218         do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
3219
3220  frees:
3221         g_object_unref (parent_folder);
3222 }
3223
3224 static void
3225 modest_ui_actions_create_folder(GtkWidget *parent_window,
3226                                 GtkWidget *folder_view)
3227 {
3228         TnyFolderStore *parent_folder;
3229
3230         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3231         
3232         if (parent_folder) {
3233                 /* The parent folder will be freed in the callback */
3234                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window), 
3235                                                                TRUE,
3236                                                                parent_folder,
3237                                                                create_folder_performer, 
3238                                                                parent_folder);
3239         }
3240 }
3241
3242 void 
3243 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
3244 {
3245         GtkWidget *folder_view;
3246         
3247         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3248
3249         folder_view = modest_main_window_get_child_widget (main_window,
3250                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3251         if (!folder_view)
3252                 return;
3253
3254         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
3255 }
3256
3257 static void
3258 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
3259                                                gpointer user_data)
3260 {
3261         const GError *error = NULL;
3262         const gchar *message = NULL;
3263         
3264         /* Get error message */
3265         error = modest_mail_operation_get_error (mail_op);
3266         if (!error)
3267                 g_return_if_reached ();
3268
3269         if (error->domain == MODEST_MAIL_OPERATION_ERROR &&
3270             error->code == MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS) {
3271                 message = _CS("ckdg_ib_folder_already_exists");
3272         } else if (error->domain == TNY_ERROR_DOMAIN &&
3273                    error->code == TNY_SERVICE_ERROR_STATE) {
3274                 /* This means that the folder is already in use (a
3275                    message is opened for example */
3276                 message = _("emev_ni_internal_error");
3277         } else {
3278                 message = _("emev_ib_ui_imap_unable_to_rename");
3279         }
3280
3281         /* We don't set a parent for the dialog because the dialog
3282            will be destroyed so the banner won't appear */
3283         modest_platform_information_banner (NULL, NULL, message);
3284 }
3285
3286 typedef struct {
3287         TnyFolderStore *folder;
3288         gchar *new_name;
3289 } RenameFolderInfo;
3290
3291 static void
3292 on_rename_folder_cb (ModestMailOperation *mail_op, 
3293                      TnyFolder *new_folder,
3294                      gpointer user_data)
3295 {
3296         ModestFolderView *folder_view;
3297
3298         /* If the window was closed when renaming a folder this could
3299            happen */
3300         if (!MODEST_IS_FOLDER_VIEW (user_data))
3301                 return;
3302
3303         folder_view = MODEST_FOLDER_VIEW (user_data);
3304         /* Note that if the rename fails new_folder will be NULL */
3305         if (new_folder) {
3306                 modest_folder_view_select_folder (folder_view, new_folder, FALSE);
3307         } else {
3308                 modest_folder_view_select_first_inbox_or_local (folder_view);
3309         }
3310         gtk_widget_grab_focus (GTK_WIDGET (folder_view));       
3311 }
3312
3313 static void
3314 on_rename_folder_performer (gboolean canceled, 
3315                             GError *err, 
3316                             GtkWindow *parent_window, 
3317                             TnyAccount *account, 
3318                             gpointer user_data)
3319 {
3320         ModestMailOperation *mail_op = NULL;
3321         GtkTreeSelection *sel = NULL;
3322         GtkWidget *folder_view = NULL;
3323         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
3324
3325         if (canceled || err) {
3326                 /* In memory full conditions we could get this error here */
3327                 check_memory_full_error ((GtkWidget *) parent_window, err);
3328         } else if (MODEST_IS_MAIN_WINDOW(parent_window)) {
3329
3330                 folder_view = modest_main_window_get_child_widget (
3331                                 MODEST_MAIN_WINDOW (parent_window),
3332                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3333
3334                 mail_op = 
3335                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3336                                         modest_ui_actions_rename_folder_error_handler,
3337                                         parent_window, NULL);
3338
3339                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3340                                 mail_op);
3341
3342                 /* Clear the headers view */
3343                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3344                 gtk_tree_selection_unselect_all (sel);
3345
3346                 /* Actually rename the folder */
3347                 modest_mail_operation_rename_folder (mail_op,
3348                                                      TNY_FOLDER (data->folder),
3349                                                      (const gchar *) (data->new_name),
3350                                                      on_rename_folder_cb,
3351                                                      folder_view);
3352                 g_object_unref (data->folder);
3353                 g_object_unref (mail_op);
3354         }
3355
3356         g_free (data->new_name);
3357         g_free (data);
3358 }
3359
3360 void 
3361 modest_ui_actions_on_rename_folder (GtkAction *action,
3362                                      ModestMainWindow *main_window)
3363 {
3364         TnyFolderStore *folder;
3365         GtkWidget *folder_view;
3366         GtkWidget *header_view; 
3367
3368         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3369
3370         folder_view = modest_main_window_get_child_widget (main_window,
3371                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3372         if (!folder_view)
3373                 return;
3374
3375         header_view = modest_main_window_get_child_widget (main_window,
3376                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3377         
3378         if (!header_view)
3379                 return;
3380
3381         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
3382
3383         if (!folder)
3384                 return;
3385
3386         if (TNY_IS_FOLDER (folder)) {
3387                 gchar *folder_name = NULL;
3388                 gint response;
3389                 const gchar *current_name;
3390                 TnyFolderStore *parent;
3391                 gboolean do_rename = TRUE;
3392
3393                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
3394                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
3395                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
3396                                                                      parent, current_name, 
3397                                                                      &folder_name);
3398                 g_object_unref (parent);
3399
3400                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
3401                         do_rename = FALSE;
3402                 } else {
3403                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
3404                         rename_folder_data->folder = g_object_ref (folder);
3405                         rename_folder_data->new_name = folder_name;
3406                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(main_window), TRUE,
3407                                         folder, on_rename_folder_performer, rename_folder_data);
3408                 }
3409         }
3410         g_object_unref (folder);
3411 }
3412
3413 static void
3414 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3415                                                gpointer user_data)
3416 {
3417         GObject *win = modest_mail_operation_get_source (mail_op);
3418
3419         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3420                                                 _("mail_in_ui_folder_delete_error"),
3421                                                 FALSE);
3422         g_object_unref (win);
3423 }
3424
3425 typedef struct {
3426         TnyFolderStore *folder;
3427         gboolean move_to_trash;
3428 } DeleteFolderInfo;
3429
3430 static void
3431 on_delete_folder_cb (gboolean canceled, 
3432                   GError *err,
3433                   GtkWindow *parent_window, 
3434                   TnyAccount *account, 
3435                   gpointer user_data)
3436 {
3437         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3438         GtkWidget *folder_view;
3439         ModestMailOperation *mail_op;
3440         GtkTreeSelection *sel;
3441         
3442         if (!MODEST_IS_MAIN_WINDOW(parent_window) || canceled || (err!=NULL)) {
3443                 g_object_unref (G_OBJECT (info->folder));
3444                 g_free (info);
3445                 return;
3446         }
3447         
3448         folder_view = modest_main_window_get_child_widget (
3449                         MODEST_MAIN_WINDOW (parent_window),
3450                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3451
3452         /* Unselect the folder before deleting it to free the headers */
3453         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3454         gtk_tree_selection_unselect_all (sel);
3455
3456         /* Create the mail operation */
3457         mail_op =
3458                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3459                                 modest_ui_actions_delete_folder_error_handler,
3460                                 NULL, NULL);
3461
3462         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3463                         mail_op);
3464         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3465         
3466         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3467
3468         g_object_unref (G_OBJECT (mail_op));
3469         g_object_unref (G_OBJECT (info->folder));
3470         g_free (info);
3471 }
3472
3473 static void
3474 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
3475 {
3476         TnyFolderStore *folder;
3477         GtkWidget *folder_view;
3478         gint response;
3479         gchar *message;
3480         
3481         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3482
3483         folder_view = modest_main_window_get_child_widget (main_window,
3484                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3485         if (!folder_view)
3486                 return;
3487
3488         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3489
3490         /* Show an error if it's an account */
3491         if (!TNY_IS_FOLDER (folder)) {
3492                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
3493                                                         _("mail_in_ui_folder_delete_error"),
3494                                                         FALSE);
3495                 g_object_unref (G_OBJECT (folder));
3496                 return;
3497         }
3498
3499         /* Ask the user */      
3500         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
3501                                     tny_folder_get_name (TNY_FOLDER (folder)));
3502         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
3503                                                             (const gchar *) message);
3504         g_free (message);
3505
3506         if (response == GTK_RESPONSE_OK) {
3507                 DeleteFolderInfo *info;
3508                 info = g_new0(DeleteFolderInfo, 1);
3509                 info->folder = folder;
3510                 info->move_to_trash = move_to_trash;
3511                 g_object_ref (G_OBJECT (info->folder));
3512                 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder));
3513                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (main_window), 
3514                                                                TRUE,
3515                                                                TNY_FOLDER_STORE (account), 
3516                                                                on_delete_folder_cb, info);
3517                 g_object_unref (account);
3518         }
3519         g_object_unref (G_OBJECT (folder));
3520 }
3521
3522 void 
3523 modest_ui_actions_on_delete_folder (GtkAction *action,
3524                                      ModestMainWindow *main_window)
3525 {
3526         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3527         
3528         delete_folder (main_window, FALSE);
3529 }
3530
3531 void 
3532 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
3533 {
3534         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3535         
3536         delete_folder (main_window, TRUE);
3537 }
3538
3539
3540 typedef struct _PasswordDialogFields {
3541         GtkWidget *username;
3542         GtkWidget *password;
3543         GtkWidget *dialog;
3544 } PasswordDialogFields;
3545
3546 static void
3547 password_dialog_check_field (GtkEditable *editable,
3548                              PasswordDialogFields *fields)
3549 {
3550         const gchar *value;
3551         gboolean any_value_empty = FALSE;
3552
3553         value = gtk_entry_get_text (GTK_ENTRY (fields->username));
3554         if ((value == NULL) || value[0] == '\0') {
3555                 any_value_empty = TRUE;
3556         }
3557         value = gtk_entry_get_text (GTK_ENTRY (fields->password));
3558         if ((value == NULL) || value[0] == '\0') {
3559                 any_value_empty = TRUE;
3560         }
3561         gtk_dialog_set_response_sensitive (GTK_DIALOG (fields->dialog), GTK_RESPONSE_ACCEPT, !any_value_empty);
3562 }
3563
3564 void
3565 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
3566                                          const gchar* server_account_name,
3567                                          gchar **username,
3568                                          gchar **password, 
3569                                          gboolean *cancel, 
3570                                          gboolean *remember,
3571                                          ModestMainWindow *main_window)
3572 {
3573         g_return_if_fail(server_account_name);
3574         gboolean completed = FALSE;
3575         PasswordDialogFields *fields = NULL;
3576         
3577         /* Initalize output parameters: */
3578         if (cancel)
3579                 *cancel = FALSE;
3580                 
3581         if (remember)
3582                 *remember = TRUE;
3583                 
3584 #ifndef MODEST_TOOLKIT_GTK
3585         /* Maemo uses a different (awkward) button order,
3586          * It should probably just use gtk_alternative_dialog_button_order ().
3587          */
3588         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3589                                               NULL,
3590                                               GTK_DIALOG_MODAL,
3591                                               _("mcen_bd_dialog_ok"),
3592                                               GTK_RESPONSE_ACCEPT,
3593                                               _("mcen_bd_dialog_cancel"),
3594                                               GTK_RESPONSE_REJECT,
3595                                               NULL);
3596 #else
3597         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3598                                               NULL,
3599                                               GTK_DIALOG_MODAL,
3600                                               GTK_STOCK_CANCEL,
3601                                               GTK_RESPONSE_REJECT,
3602                                               GTK_STOCK_OK,
3603                                               GTK_RESPONSE_ACCEPT,
3604                                               NULL);
3605 #endif /* !MODEST_TOOLKIT_GTK */
3606
3607         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog), NULL);
3608         
3609         gchar *server_name = modest_account_mgr_get_server_account_hostname (
3610                 modest_runtime_get_account_mgr(), server_account_name);
3611         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3612                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3613                 if (cancel)
3614                         *cancel = TRUE;
3615                 gtk_widget_destroy (dialog);
3616                 return;
3617         }
3618         
3619         /* This causes a warning because the logical ID has no %s in it, 
3620          * though the translation does, but there is not much we can do about that: */
3621         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
3622         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
3623                             FALSE, FALSE, 0);
3624         g_free (txt);
3625         g_free (server_name);
3626         server_name = NULL;
3627
3628         /* username: */
3629         gchar *initial_username = modest_account_mgr_get_server_account_username (
3630                 modest_runtime_get_account_mgr(), server_account_name);
3631         
3632         GtkWidget *entry_username = gtk_entry_new ();
3633         if (initial_username)
3634                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
3635         /* Dim this if a connection has ever succeeded with this username,
3636          * as per the UI spec: */
3637         /* const gboolean username_known =  */
3638         /*      modest_account_mgr_get_server_account_username_has_succeeded( */
3639         /*              modest_runtime_get_account_mgr(), server_account_name); */
3640         /* gtk_widget_set_sensitive (entry_username, !username_known); */
3641
3642         /* We drop the username sensitive code and disallow changing it here
3643          * as tinymail does not support really changing the username in the callback
3644          */
3645         gtk_widget_set_sensitive (entry_username, FALSE);
3646
3647 #ifndef MODEST_TOOLKIT_GTK
3648         /* Auto-capitalization is the default, so let's turn it off: */
3649         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
3650         
3651         /* Create a size group to be used by all captions.
3652          * Note that HildonCaption does not create a default size group if we do not specify one.
3653          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
3654         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3655         
3656         GtkWidget *caption = hildon_caption_new (sizegroup, 
3657                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
3658         gtk_widget_show (entry_username);
3659         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3660                 FALSE, FALSE, MODEST_MARGIN_HALF);
3661         gtk_widget_show (caption);
3662 #else 
3663         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
3664                             TRUE, FALSE, 0);
3665 #endif /* !MODEST_TOOLKIT_GTK */        
3666                             
3667         /* password: */
3668         GtkWidget *entry_password = gtk_entry_new ();
3669         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
3670         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
3671         
3672 #ifndef MODEST_TOOLKIT_GTK
3673         /* Auto-capitalization is the default, so let's turn it off: */
3674         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
3675                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
3676         
3677         caption = hildon_caption_new (sizegroup, 
3678                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
3679         gtk_widget_show (entry_password);
3680         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3681                 FALSE, FALSE, MODEST_MARGIN_HALF);
3682         gtk_widget_show (caption);
3683         g_object_unref (sizegroup);
3684 #else 
3685         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
3686                             TRUE, FALSE, 0);
3687 #endif /* !MODEST_TOOLKIT_GTK */        
3688
3689         if (initial_username != NULL)
3690                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
3691                                 
3692 /* This is not in the Maemo UI spec:
3693         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
3694         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
3695                             TRUE, FALSE, 0);
3696 */
3697
3698         fields = g_slice_new0 (PasswordDialogFields);
3699         fields->username = entry_username;
3700         fields->password = entry_password;
3701         fields->dialog = dialog;
3702
3703         g_signal_connect (entry_username, "changed", G_CALLBACK (password_dialog_check_field), fields);
3704         g_signal_connect (entry_password, "changed", G_CALLBACK (password_dialog_check_field), fields);
3705         password_dialog_check_field (NULL, fields);
3706
3707         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3708
3709         while (!completed) {
3710         
3711                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
3712                         if (username) {
3713                                 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
3714                                 
3715                                 /* Note that an empty field becomes the "" string */
3716                                 if (*username && strlen (*username) > 0) {
3717                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(), 
3718                                                                                         server_account_name, 
3719                                                                                         *username);
3720                                         completed = TRUE;
3721                                 
3722                                         const gboolean username_was_changed = 
3723                                                 (strcmp (*username, initial_username) != 0);
3724                                         if (username_was_changed) {
3725                                                 g_warning ("%s: tinymail does not yet support changing the "
3726                                                            "username in the get_password() callback.\n", __FUNCTION__);
3727                                         }
3728                                 } else {
3729                                         g_free (*username);
3730                                         *username = NULL;
3731                                         /* Show error */
3732                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL, 
3733                                                                             _("mcen_ib_username_pw_incorrect"));
3734                                         completed = FALSE;
3735                                 }
3736                         }
3737                         
3738                         if (password) {
3739                                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
3740                         
3741                                 /* We do not save the password in the configuration, 
3742                                  * because this function is only called for passwords that should 
3743                                  * not be remembered:
3744                                  modest_server_account_set_password (
3745                                  modest_runtime_get_account_mgr(), server_account_name, 
3746                                  *password);
3747                                  */
3748                         }                       
3749                         if (cancel)
3750                                 *cancel   = FALSE;                      
3751                 } else {
3752                         /* Set parent to NULL or the banner will disappear with its parent dialog */
3753                         modest_platform_information_banner(NULL, NULL, _("mail_ib_login_cancelled"));
3754                         completed = TRUE;
3755                         if (username)
3756                                 *username = NULL;                       
3757                         if (password)
3758                                 *password = NULL;                       
3759                         if (cancel)
3760                                 *cancel   = TRUE;
3761                 }
3762         }
3763
3764 /* This is not in the Maemo UI spec:
3765         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
3766                 *remember = TRUE;
3767         else
3768                 *remember = FALSE;
3769 */
3770
3771         g_free (initial_username);
3772         gtk_widget_destroy (dialog);
3773         g_slice_free (PasswordDialogFields, fields);
3774         
3775         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
3776 }
3777
3778 void
3779 modest_ui_actions_on_cut (GtkAction *action,
3780                           ModestWindow *window)
3781 {
3782         GtkWidget *focused_widget;
3783         GtkClipboard *clipboard;
3784
3785         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3786         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3787         if (GTK_IS_EDITABLE (focused_widget)) {
3788                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3789                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3790                 gtk_clipboard_store (clipboard);
3791         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3792                 GtkTextBuffer *buffer;
3793
3794                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3795                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3796                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3797                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3798                         gtk_clipboard_store (clipboard);
3799                 }
3800         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3801                 TnyList *header_list = modest_header_view_get_selected_headers (
3802                                 MODEST_HEADER_VIEW (focused_widget));
3803                 gboolean continue_download = FALSE;
3804                 gint num_of_unc_msgs;
3805
3806                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3807
3808                 if (num_of_unc_msgs) {
3809                         TnyAccount *account = get_account_from_header_list (header_list);
3810                         if (account) {
3811                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3812                                 g_object_unref (account);
3813                         }
3814                 }
3815
3816                 if (num_of_unc_msgs == 0 || continue_download) {
3817 /*                      modest_platform_information_banner (
3818                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
3819                         modest_header_view_cut_selection (
3820                                         MODEST_HEADER_VIEW (focused_widget));
3821                 }
3822
3823                 g_object_unref (header_list);
3824         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3825                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3826         }
3827 }
3828
3829 void
3830 modest_ui_actions_on_copy (GtkAction *action,
3831                            ModestWindow *window)
3832 {
3833         GtkClipboard *clipboard;
3834         GtkWidget *focused_widget;
3835         gboolean copied = TRUE;
3836
3837         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3838         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3839
3840         if (GTK_IS_LABEL (focused_widget)) {
3841                 gchar *selection;
3842                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
3843                 gtk_clipboard_set_text (clipboard, selection, -1);
3844                 g_free (selection);
3845                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3846                 gtk_clipboard_store (clipboard);
3847         } else if (GTK_IS_EDITABLE (focused_widget)) {
3848                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3849                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3850                 gtk_clipboard_store (clipboard);
3851         } else if (GTK_IS_HTML (focused_widget)) {
3852                 const gchar *sel;
3853                 int len = -1;
3854                 sel = gtk_html_get_selection_html (GTK_HTML (focused_widget), &len);
3855                 if ((sel == NULL) || (sel[0] == '\0')) {
3856                         copied = FALSE;
3857                 } else {
3858                         gtk_html_copy (GTK_HTML (focused_widget));
3859                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3860                         gtk_clipboard_store (clipboard);
3861                 }
3862         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3863                 GtkTextBuffer *buffer;
3864                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3865                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3866                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
3867                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3868                         gtk_clipboard_store (clipboard);
3869                 }
3870         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3871                 TnyList *header_list = modest_header_view_get_selected_headers (
3872                                 MODEST_HEADER_VIEW (focused_widget));
3873                 gboolean continue_download = FALSE;
3874                 gint num_of_unc_msgs;
3875
3876                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3877
3878                 if (num_of_unc_msgs) {
3879                         TnyAccount *account = get_account_from_header_list (header_list);
3880                         if (account) {
3881                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3882                                 g_object_unref (account);
3883                         }
3884                 }
3885
3886                 if (num_of_unc_msgs == 0 || continue_download) {
3887                         modest_platform_information_banner (
3888                                         NULL, NULL, _CS("mcen_ib_getting_items"));
3889                         modest_header_view_copy_selection (
3890                                         MODEST_HEADER_VIEW (focused_widget));
3891                 } else
3892                         copied = FALSE;
3893
3894                 g_object_unref (header_list);
3895
3896         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3897                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3898         }
3899
3900         /* Show information banner if there was a copy to clipboard */
3901         if(copied)
3902                 modest_platform_information_banner (
3903                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3904 }
3905
3906 void
3907 modest_ui_actions_on_undo (GtkAction *action,
3908                            ModestWindow *window)
3909 {
3910         ModestEmailClipboard *clipboard = NULL;
3911
3912         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3913                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3914         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3915                 /* Clear clipboard source */
3916                 clipboard = modest_runtime_get_email_clipboard ();
3917                 modest_email_clipboard_clear (clipboard);               
3918         }
3919         else {
3920                 g_return_if_reached ();
3921         }
3922 }
3923
3924 void
3925 modest_ui_actions_on_redo (GtkAction *action,
3926                            ModestWindow *window)
3927 {
3928         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3929                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3930         }
3931         else {
3932                 g_return_if_reached ();
3933         }
3934 }
3935
3936
3937 static void
3938 destroy_information_note (ModestMailOperation *mail_op, 
3939                           gpointer user_data)
3940 {
3941         /* destroy information note */
3942         gtk_widget_destroy (GTK_WIDGET(user_data));
3943 }
3944
3945 static void
3946 destroy_folder_information_note (ModestMailOperation *mail_op, 
3947                                  TnyFolder *new_folder,
3948                                  gpointer user_data)
3949 {
3950         /* destroy information note */
3951         gtk_widget_destroy (GTK_WIDGET(user_data));
3952 }
3953
3954
3955 static void
3956 paste_as_attachment_free (gpointer data)
3957 {
3958         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3959
3960         if (helper->banner) {
3961                 gtk_widget_destroy (helper->banner);
3962                 g_object_unref (helper->banner);
3963         }
3964         g_free (helper);
3965 }
3966
3967 static void
3968 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3969                             TnyHeader *header,
3970                             TnyMsg *msg,
3971                             gpointer userdata)
3972 {
3973         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3974         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3975
3976         if (msg == NULL)
3977                 return;
3978
3979         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3980         
3981 }
3982
3983 void
3984 modest_ui_actions_on_paste (GtkAction *action,
3985                             ModestWindow *window)
3986 {
3987         GtkWidget *focused_widget = NULL;
3988         GtkWidget *inf_note = NULL;
3989         ModestMailOperation *mail_op = NULL;
3990
3991         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3992         if (GTK_IS_EDITABLE (focused_widget)) {
3993                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3994         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3995                 ModestEmailClipboard *e_clipboard = NULL;
3996                 e_clipboard = modest_runtime_get_email_clipboard ();
3997                 if (modest_email_clipboard_cleared (e_clipboard)) {
3998                         GtkTextBuffer *buffer;
3999                         GtkClipboard *clipboard;
4000
4001                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
4002                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4003                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
4004                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
4005                         ModestMailOperation *mail_op;
4006                         TnyFolder *src_folder = NULL;
4007                         TnyList *data = NULL;
4008                         gboolean delete;
4009                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
4010                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
4011                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
4012                                                                            _CS("ckct_nw_pasting"));
4013                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
4014                         mail_op = modest_mail_operation_new (G_OBJECT (window));
4015                         if (helper->banner != NULL) {
4016                                 g_object_ref (G_OBJECT (helper->banner));
4017                                 gtk_widget_show (GTK_WIDGET (helper->banner));
4018                         }
4019
4020                         if (data != NULL) {
4021                                 modest_mail_operation_get_msgs_full (mail_op, 
4022                                                                      data,
4023                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
4024                                                                      helper,
4025                                                                      paste_as_attachment_free);
4026                         }
4027                         /* Free */
4028                         if (data) 
4029                                 g_object_unref (data);
4030                         if (src_folder) 
4031                                 g_object_unref (src_folder);
4032
4033                 }
4034         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
4035                 ModestEmailClipboard *clipboard = NULL;
4036                 TnyFolder *src_folder = NULL;
4037                 TnyFolderStore *folder_store = NULL;
4038                 TnyList *data = NULL;           
4039                 gboolean delete = FALSE;
4040                 
4041                 /* Check clipboard source */
4042                 clipboard = modest_runtime_get_email_clipboard ();
4043                 if (modest_email_clipboard_cleared (clipboard)) 
4044                         return;
4045                 
4046                 /* Get elements to paste */
4047                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
4048
4049                 /* Create a new mail operation */
4050                 mail_op = modest_mail_operation_new (G_OBJECT(window));
4051                 
4052                 /* Get destination folder */
4053                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
4054
4055                 /* transfer messages  */
4056                 if (data != NULL) {
4057                         gint response = 0;
4058
4059                         /* Ask for user confirmation */
4060                         response = 
4061                                 modest_ui_actions_msgs_move_to_confirmation (window, 
4062                                                                              TNY_FOLDER (folder_store), 
4063                                                                              delete,
4064                                                                              data);
4065                         
4066                         if (response == GTK_RESPONSE_OK) {
4067                                 /* Launch notification */
4068                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
4069                                                                              _CS("ckct_nw_pasting"));
4070                                 if (inf_note != NULL)  {
4071                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4072                                         gtk_widget_show (GTK_WIDGET(inf_note));
4073                                 }
4074
4075                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4076                                 modest_mail_operation_xfer_msgs (mail_op, 
4077                                                                  data,
4078                                                                  TNY_FOLDER (folder_store),
4079                                                                  delete,
4080                                                                  destroy_information_note,
4081                                                                  inf_note);                             
4082                         } else {
4083                                 g_object_unref (mail_op);
4084                         }
4085                         
4086                 } else if (src_folder != NULL) {                        
4087                         /* Launch notification */
4088                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
4089                                                                      _CS("ckct_nw_pasting"));
4090                         if (inf_note != NULL)  {
4091                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
4092                                 gtk_widget_show (GTK_WIDGET(inf_note));
4093                         }
4094                         
4095                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4096                         modest_mail_operation_xfer_folder (mail_op, 
4097                                                            src_folder,
4098                                                            folder_store,
4099                                                            delete,
4100                                                            destroy_folder_information_note,
4101                                                            inf_note);
4102                 }
4103
4104                 /* Free */
4105                 if (data != NULL) 
4106                         g_object_unref (data);
4107                 if (src_folder != NULL) 
4108                         g_object_unref (src_folder);
4109                 if (folder_store != NULL) 
4110                         g_object_unref (folder_store);
4111         }
4112 }
4113
4114
4115 void
4116 modest_ui_actions_on_select_all (GtkAction *action,
4117                                  ModestWindow *window)
4118 {
4119         GtkWidget *focused_widget;
4120
4121         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
4122         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
4123                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
4124         } else if (GTK_IS_LABEL (focused_widget)) {
4125                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
4126         } else if (GTK_IS_EDITABLE (focused_widget)) {
4127                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
4128         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
4129                 GtkTextBuffer *buffer;
4130                 GtkTextIter start, end;
4131
4132                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
4133                 gtk_text_buffer_get_start_iter (buffer, &start);
4134                 gtk_text_buffer_get_end_iter (buffer, &end);
4135                 gtk_text_buffer_select_range (buffer, &start, &end);
4136         } else if (GTK_IS_HTML (focused_widget)) {
4137                 gtk_html_select_all (GTK_HTML (focused_widget));
4138         } else if (MODEST_IS_MAIN_WINDOW (window)) {
4139                 GtkWidget *header_view = focused_widget;
4140                 GtkTreeSelection *selection = NULL;
4141                 
4142                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
4143                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
4144                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4145                 }
4146                                 
4147                 /* Disable window dimming management */
4148                 modest_window_disable_dimming (MODEST_WINDOW(window));
4149                 
4150                 /* Select all messages */
4151                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
4152                 gtk_tree_selection_select_all (selection);
4153
4154                 /* Set focuse on header view */
4155                 gtk_widget_grab_focus (header_view);
4156
4157                 /* Enable window dimming management */
4158                 modest_window_enable_dimming (MODEST_WINDOW(window));
4159                 modest_ui_actions_check_menu_dimming_rules (MODEST_WINDOW (window));
4160                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
4161         }
4162
4163 }
4164
4165 void
4166 modest_ui_actions_on_mark_as_read (GtkAction *action,
4167                                    ModestWindow *window)
4168 {       
4169         g_return_if_fail (MODEST_IS_WINDOW(window));
4170                 
4171         /* Mark each header as read */
4172         do_headers_action (window, headers_action_mark_as_read, NULL);
4173 }
4174
4175 void
4176 modest_ui_actions_on_mark_as_unread (GtkAction *action,
4177                                      ModestWindow *window)
4178 {       
4179         g_return_if_fail (MODEST_IS_WINDOW(window));
4180                 
4181         /* Mark each header as read */
4182         do_headers_action (window, headers_action_mark_as_unread, NULL);
4183 }
4184
4185 void
4186 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
4187                                   GtkRadioAction *selected,
4188                                   ModestWindow *window)
4189 {
4190         gint value;
4191
4192         value = gtk_radio_action_get_current_value (selected);
4193         if (MODEST_IS_WINDOW (window)) {
4194                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
4195         }
4196 }
4197
4198 void
4199 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
4200                                                GtkRadioAction *selected,
4201                                                ModestWindow *window)
4202 {
4203         TnyHeaderFlags flags;
4204         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4205
4206         flags = gtk_radio_action_get_current_value (selected);
4207         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
4208 }
4209
4210 void
4211 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
4212                                                   GtkRadioAction *selected,
4213                                                   ModestWindow *window)
4214 {
4215         gint file_format;
4216
4217         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4218
4219         file_format = gtk_radio_action_get_current_value (selected);
4220         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
4221 }
4222
4223
4224 void
4225 modest_ui_actions_on_zoom_plus (GtkAction *action,
4226                                 ModestWindow *window)
4227 {
4228         g_return_if_fail (MODEST_IS_WINDOW (window));
4229
4230         modest_window_zoom_plus (MODEST_WINDOW (window));
4231 }
4232
4233 void     
4234 modest_ui_actions_on_zoom_minus (GtkAction *action,
4235                                  ModestWindow *window)
4236 {
4237         g_return_if_fail (MODEST_IS_WINDOW (window));
4238
4239         modest_window_zoom_minus (MODEST_WINDOW (window));
4240 }
4241
4242 void     
4243 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
4244                                            ModestWindow *window)
4245 {
4246         ModestWindowMgr *mgr;
4247         gboolean fullscreen, active;
4248         g_return_if_fail (MODEST_IS_WINDOW (window));
4249
4250         mgr = modest_runtime_get_window_mgr ();
4251
4252         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
4253         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4254
4255         if (active != fullscreen) {
4256                 modest_window_mgr_set_fullscreen_mode (mgr, active);
4257 #ifndef MODEST_TOOLKIT_HILDON2
4258                 gtk_window_present (GTK_WINDOW (window));
4259 #endif
4260         }
4261 }
4262
4263 void
4264 modest_ui_actions_on_change_fullscreen (GtkAction *action,
4265                                         ModestWindow *window)
4266 {
4267         ModestWindowMgr *mgr;
4268         gboolean fullscreen;
4269
4270         g_return_if_fail (MODEST_IS_WINDOW (window));
4271
4272         mgr = modest_runtime_get_window_mgr ();
4273         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
4274         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
4275
4276 #ifndef MODEST_TOOLKIT_HILDON2
4277         gtk_window_present (GTK_WINDOW (window));
4278 #endif
4279 }
4280
4281 /* 
4282  * Used by modest_ui_actions_on_details to call do_headers_action 
4283  */
4284 static void
4285 headers_action_show_details (TnyHeader *header, 
4286                              ModestWindow *window,
4287                              gpointer user_data)
4288
4289 {
4290         modest_platform_run_header_details_dialog (GTK_WINDOW (window), header);
4291 }
4292
4293 /*
4294  * Show the header details in a ModestDetailsDialog widget
4295  */
4296 void     
4297 modest_ui_actions_on_details (GtkAction *action, 
4298                               ModestWindow *win)
4299 {
4300         TnyList * headers_list;
4301         TnyIterator *iter;
4302         TnyHeader *header;              
4303
4304         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
4305                 TnyMsg *msg;
4306
4307                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
4308                 if (!msg)
4309                         return;
4310                 g_object_unref (msg);           
4311
4312                 headers_list = get_selected_headers (win);
4313                 if (!headers_list)
4314                         return;
4315
4316                 iter = tny_list_create_iterator (headers_list);
4317
4318                 header = TNY_HEADER (tny_iterator_get_current (iter));
4319                 if (header) {
4320                         headers_action_show_details (header, win, NULL);
4321                         g_object_unref (header);
4322                 }
4323
4324                 g_object_unref (iter);
4325                 g_object_unref (headers_list);
4326
4327         } else if (MODEST_IS_MAIN_WINDOW (win)) {
4328                 GtkWidget *folder_view, *header_view;
4329
4330                 /* Check which widget has the focus */
4331                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4332                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4333                 if (gtk_widget_is_focus (folder_view)) {
4334                         TnyFolderStore *folder_store
4335                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4336                         if (!folder_store) {
4337                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
4338                                 return; 
4339                         }
4340                         /* Show only when it's a folder */
4341                         /* This function should not be called for account items, 
4342                          * because we dim the menu item for them. */
4343                         if (TNY_IS_FOLDER (folder_store)) {
4344                                 modest_platform_run_folder_details_dialog (GTK_WINDOW (win), 
4345                                                                            TNY_FOLDER (folder_store));
4346                         }
4347
4348                         g_object_unref (folder_store);
4349
4350                 } else {
4351                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4352                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4353                         /* Show details of each header */
4354                         do_headers_action (win, headers_action_show_details, header_view);
4355                 }
4356         }
4357 }
4358
4359 void     
4360 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
4361                                      ModestMsgEditWindow *window)
4362 {
4363         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4364
4365         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
4366 }
4367
4368 void     
4369 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
4370                                       ModestMsgEditWindow *window)
4371 {
4372         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4373
4374         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
4375 }
4376
4377 void
4378 modest_ui_actions_toggle_folders_view (GtkAction *action, 
4379                                        ModestMainWindow *main_window)
4380 {
4381         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
4382
4383         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
4384                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
4385         else
4386                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
4387 }
4388
4389 void 
4390 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
4391                                      ModestWindow *window)
4392 {
4393         gboolean active, fullscreen = FALSE;
4394         ModestWindowMgr *mgr;
4395
4396         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
4397
4398         /* Check if we want to toggle the toolbar view in fullscreen
4399            or normal mode */
4400         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
4401                      "ViewShowToolbarFullScreen")) {
4402                 fullscreen = TRUE;
4403         }
4404
4405         /* Toggle toolbar */
4406         mgr = modest_runtime_get_window_mgr ();
4407         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
4408 }
4409
4410 void     
4411 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
4412                                            ModestMsgEditWindow *window)
4413 {
4414         modest_msg_edit_window_select_font (window);
4415 }
4416
4417
4418 void
4419 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
4420                                                   const gchar *display_name,
4421                                                   GtkWindow *window)
4422 {
4423         /* don't update the display name if it was already set;
4424          * updating the display name apparently is expensive */
4425         const gchar* old_name = gtk_window_get_title (window);
4426
4427         if (display_name == NULL)
4428                 display_name = " ";
4429
4430         if (old_name && display_name && strcmp (old_name, display_name) == 0)
4431                 return; /* don't do anything */
4432
4433         /* This is usually used to change the title of the main window, which
4434          * is the one that holds the folder view. Note that this change can
4435          * happen even when the widget doesn't have the focus. */
4436         gtk_window_set_title (window, display_name);
4437
4438 }
4439
4440 void
4441 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4442 {
4443         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4444         modest_msg_edit_window_select_contacts (window);
4445 }
4446
4447 void
4448 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4449 {
4450         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4451         modest_msg_edit_window_check_names (window, FALSE);
4452 }
4453
4454 static void
4455 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
4456 {
4457         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
4458                                          GTK_WIDGET (user_data));
4459 }
4460
4461 /*
4462  * This function is used to track changes in the selection of the
4463  * folder view that is inside the "move to" dialog to enable/disable
4464  * the OK button because we do not want the user to select a disallowed
4465  * destination for a folder.
4466  * The user also not desired to be able to use NEW button on items where
4467  * folder creation is not possibel.
4468  */
4469 static void
4470 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4471                                             TnyFolderStore *folder_store,
4472                                             gboolean selected,
4473                                             gpointer user_data)
4474 {
4475         GtkWidget *dialog = NULL;
4476         GtkWidget *ok_button = NULL, *new_button = NULL;
4477         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4478         gboolean moving_folder = FALSE;
4479         gboolean is_local_account = TRUE;
4480         GtkWidget *folder_view = NULL;
4481         ModestTnyFolderRules rules;
4482
4483         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4484         
4485         if (!selected)
4486                 return;
4487         
4488         /* Get the OK button */
4489         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4490         if (!dialog)
4491                 return;
4492
4493         ok_button = g_object_get_data (G_OBJECT (dialog), MOVE_FOLDER_OK_BUTTON);
4494         new_button = g_object_get_data (G_OBJECT (dialog), MOVE_FOLDER_NEW_BUTTON);
4495
4496         /* check if folder_store is an remote account */
4497         if (TNY_IS_ACCOUNT (folder_store)) {
4498                 TnyAccount *local_account = NULL;
4499                 TnyAccount *mmc_account = NULL;
4500                 ModestTnyAccountStore *account_store = NULL;
4501
4502                 account_store = modest_runtime_get_account_store ();
4503                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4504                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4505
4506                 if ((gpointer) local_account != (gpointer) folder_store &&
4507                     (gpointer) mmc_account != (gpointer) folder_store) {
4508                         ModestProtocolType proto;
4509                         proto = modest_tny_account_get_protocol_type (TNY_ACCOUNT (folder_store));
4510                         if (proto == MODEST_PROTOCOL_REGISTRY_TYPE_INVALID) {
4511                                 proto = MODEST_PROTOCOLS_STORE_MAILDIR;
4512                         }
4513                         is_local_account = FALSE;
4514                         /* New button should be dimmed on remote
4515                            POP account root */
4516                         new_sensitive = (modest_protocol_registry_protocol_type_has_tag (modest_runtime_get_protocol_registry (),
4517                                                                                          proto,
4518                                                                                          MODEST_PROTOCOL_REGISTRY_STORE_HAS_FOLDERS));
4519                 }
4520                 g_object_unref (local_account);
4521
4522                 /* It could not exist */
4523                 if (mmc_account)
4524                         g_object_unref (mmc_account);
4525         }
4526
4527         /* Check the target folder rules */
4528         if (TNY_IS_FOLDER (folder_store)) {
4529                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
4530                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
4531                         ok_sensitive = FALSE;
4532                         new_sensitive = FALSE;
4533                         goto end;
4534                 }
4535         }
4536
4537         /* Check if we're moving a folder */
4538         if (MODEST_IS_MAIN_WINDOW (user_data)) {
4539                 /* Get the widgets */
4540                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
4541                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4542                 if (gtk_widget_is_focus (folder_view))
4543                         moving_folder = TRUE;
4544         }
4545
4546         if (moving_folder) {
4547                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
4548
4549                 /* Get the folder to move */
4550                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4551                 
4552                 /* Check that we're not moving to the same folder */
4553                 if (TNY_IS_FOLDER (moved_folder)) {
4554                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
4555                         if (parent == folder_store)
4556                                 ok_sensitive = FALSE;
4557                         g_object_unref (parent);
4558                 } 
4559
4560                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
4561                         /* Do not allow to move to an account unless it's the
4562                            local folders account */
4563                         if (!is_local_account)
4564                                 ok_sensitive = FALSE;
4565                 } 
4566
4567                 if (ok_sensitive && (moved_folder == folder_store)) {
4568                         /* Do not allow to move to itself */
4569                         ok_sensitive = FALSE;
4570                 }
4571                 g_object_unref (moved_folder);
4572         } else {
4573                 TnyFolder *src_folder = NULL;
4574
4575                 /* Moving a message */
4576                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
4577
4578                         TnyHeader *header = NULL;
4579                         header = modest_msg_view_window_get_header
4580                                 (MODEST_MSG_VIEW_WINDOW (user_data));
4581                         if (!TNY_IS_HEADER(header))
4582                                 g_warning ("%s: could not get source header", __FUNCTION__);
4583                         else
4584                                 src_folder = tny_header_get_folder (header);
4585
4586                         if (header)
4587                                 g_object_unref (header);
4588                 } else {
4589                         src_folder = 
4590                                 TNY_FOLDER (modest_folder_view_get_selected
4591                                             (MODEST_FOLDER_VIEW (folder_view)));
4592                 }
4593
4594                 if (TNY_IS_FOLDER(src_folder)) {
4595                         /* Do not allow to move the msg to the same folder */
4596                         /* Do not allow to move the msg to an account */
4597                         if ((gpointer) src_folder == (gpointer) folder_store ||
4598                             TNY_IS_ACCOUNT (folder_store))
4599                                 ok_sensitive = FALSE;
4600                         g_object_unref (src_folder);
4601                 } else
4602                         g_warning ("%s: could not get source folder", __FUNCTION__);
4603         }
4604
4605  end:
4606         /* Set sensitivity of the OK button */
4607         gtk_widget_set_sensitive (ok_button, ok_sensitive);
4608         /* Set sensitivity of the NEW button */
4609         gtk_widget_set_sensitive (new_button, new_sensitive);
4610 }
4611
4612
4613 #define MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
4614
4615 static GtkWidget*
4616 get_folder_view_from_move_to_dialog (GtkWidget *move_to_dialog)
4617 {
4618         return GTK_WIDGET(g_object_get_data (G_OBJECT(move_to_dialog),
4619                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4620 }
4621
4622 static GtkWidget*
4623 create_move_to_dialog (GtkWindow *win,
4624                        GtkWidget *folder_view,
4625                        GtkWidget **tree_view)
4626 {
4627         GtkWidget *dialog;
4628 #ifdef MODEST_TOOLKIT_HILDON2
4629         GtkWidget *pannable;
4630 #else
4631         GtkWidget *scroll;
4632 #endif
4633         GtkWidget *new_button, *ok_button;
4634
4635         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
4636                                               GTK_WINDOW (win),
4637                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
4638                                               NULL);
4639
4640 #ifndef MODEST_TOOLKIT_GTK
4641         ok_button = gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
4642         /* We do this manually so GTK+ does not associate a response ID for
4643          * the button. */
4644         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
4645         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
4646         gtk_widget_show (new_button);
4647 #ifndef MODEST_TOOLKIT_HILDON2
4648         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
4649 #endif
4650 #else
4651         /* We do this manually so GTK+ does not associate a response ID for
4652          * the button. */
4653         new_button = gtk_button_new_with_label (_("mcen_ti_new_folder"));
4654         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
4655         gtk_button_box_set_child_secondary (GTK_BUTTON_BOX (GTK_DIALOG (dialog)->action_area), new_button, TRUE);
4656         gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
4657         ok_button = gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
4658         gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
4659         gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 24);
4660 #endif
4661         g_object_set_data (G_OBJECT (dialog), MOVE_FOLDER_OK_BUTTON, ok_button);
4662         g_object_set_data (G_OBJECT (dialog), MOVE_FOLDER_NEW_BUTTON, new_button);
4663
4664         /* Create scrolled window */
4665 #ifdef MODEST_TOOLKIT_HILDON2
4666         pannable = hildon_pannable_area_new ();
4667 #else
4668         scroll = gtk_scrolled_window_new (NULL, NULL);
4669         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
4670                                          GTK_POLICY_AUTOMATIC,
4671                                          GTK_POLICY_AUTOMATIC);
4672 #endif
4673
4674 #ifdef MODEST_TOOLKIT_GTK
4675         gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_IN);
4676 #endif
4677
4678         /* Create folder view */
4679         *tree_view = modest_platform_create_folder_view (NULL);
4680
4681         /* Track changes in the selection to
4682          * disable the OK button whenever "Move to" is not possible
4683          * disbale NEW button whenever New is not possible */
4684         g_signal_connect (*tree_view,
4685                           "folder_selection_changed",
4686                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
4687                           win);
4688
4689         /* Listen to clicks on New button */
4690         g_signal_connect (G_OBJECT (new_button), 
4691                           "clicked", 
4692                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
4693                           *tree_view);
4694
4695         /* It could happen that we're trying to move a message from a
4696            window (msg window for example) after the main window was
4697            closed, so we can not just get the model of the folder
4698            view */
4699         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
4700                 const gchar *visible_id = NULL;
4701
4702                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4703                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4704                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
4705                                                MODEST_FOLDER_VIEW(*tree_view));
4706
4707                 visible_id = 
4708                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
4709
4710                 /* Show the same account than the one that is shown in the main window */
4711                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
4712                                                                              visible_id);
4713         } else {
4714                 const gchar *active_account_name = NULL;
4715                 ModestAccountMgr *mgr = NULL;
4716                 ModestAccountSettings *settings = NULL;
4717                 ModestServerAccountSettings *store_settings = NULL;
4718
4719                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4720                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4721                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
4722                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
4723
4724                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
4725                 mgr = modest_runtime_get_account_mgr ();
4726                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
4727
4728                 if (settings) {
4729                         const gchar *store_account_name;
4730                         store_settings = modest_account_settings_get_store_settings (settings);
4731                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
4732
4733                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
4734                                                                                      store_account_name);
4735                         g_object_unref (store_settings);
4736                         g_object_unref (settings);
4737                 }
4738         }
4739
4740         /* we keep a pointer to the embedded folder view, so we can retrieve it with
4741          *   get_folder_view_from_move_to_dialog 
4742          * (see above) later (needed for focus handling) 
4743          */
4744         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, *tree_view);
4745
4746         
4747         /* Hide special folders */
4748         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
4749
4750 #ifdef MODEST_TOOLKIT_HILDON2
4751         gtk_container_add (GTK_CONTAINER (pannable), *tree_view);
4752         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
4753                             pannable, TRUE, TRUE, 0);
4754 #else
4755         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
4756         /* Add scroll to dialog */
4757         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
4758                             scroll, TRUE, TRUE, 0);
4759 #endif
4760
4761
4762         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4763 #ifndef MODEST_TOOLKIT_GTK
4764         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
4765 #else
4766         gtk_window_set_default_size (GTK_WINDOW (dialog), 600, 400);
4767 #endif
4768
4769         return dialog;
4770 }
4771
4772
4773
4774 /*
4775  * Shows a confirmation dialog to the user when we're moving messages
4776  * from a remote server to the local storage. Returns the dialog
4777  * response. If it's other kind of movement then it always returns
4778  * GTK_RESPONSE_OK
4779  *
4780  * This one is used by the next functions:
4781  *      modest_ui_actions_on_paste                      - commented out
4782  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4783  */
4784 gint
4785 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4786                                              TnyFolder *dest_folder,
4787                                              gboolean delete,
4788                                              TnyList *headers)
4789 {
4790         gint response = GTK_RESPONSE_OK;
4791         TnyAccount *account = NULL;
4792         TnyFolder *src_folder = NULL;
4793         TnyIterator *iter = NULL;
4794         TnyHeader *header = NULL;
4795
4796         /* return with OK if the destination is a remote folder */
4797         if (modest_tny_folder_is_remote_folder (dest_folder))
4798                 return GTK_RESPONSE_OK;
4799
4800         /* Get source folder */
4801         iter = tny_list_create_iterator (headers);
4802         header = TNY_HEADER (tny_iterator_get_current (iter));
4803         if (header) {
4804                 src_folder = tny_header_get_folder (header);
4805                 g_object_unref (header);
4806         }
4807         g_object_unref (iter);
4808
4809         /* if no src_folder, message may be an attahcment */
4810         if (src_folder == NULL) 
4811                 return GTK_RESPONSE_CANCEL;
4812
4813         /* If the source is a local or MMC folder */
4814         if (!modest_tny_folder_is_remote_folder (src_folder)) {
4815                 g_object_unref (src_folder);
4816                 return GTK_RESPONSE_OK;
4817         }
4818
4819         /* Get the account */
4820         account = tny_folder_get_account (src_folder);
4821
4822         /* now if offline we ask the user */
4823         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4824                 response = GTK_RESPONSE_OK;
4825         else
4826                 response = GTK_RESPONSE_CANCEL;
4827
4828         /* Frees */
4829         g_object_unref (src_folder);
4830         g_object_unref (account);
4831
4832         return response;
4833 }
4834
4835 static void
4836 move_to_helper_destroyer (gpointer user_data)
4837 {
4838         MoveToHelper *helper = (MoveToHelper *) user_data;
4839
4840         /* Close the "Pasting" information banner */
4841         if (helper->banner) {
4842                 gtk_widget_destroy (GTK_WIDGET (helper->banner));
4843                 g_object_unref (helper->banner);
4844         }
4845         if (gtk_tree_row_reference_valid (helper->reference)) {
4846                 gtk_tree_row_reference_free (helper->reference);
4847                 helper->reference = NULL;
4848         }
4849         g_free (helper);
4850 }
4851
4852 static void
4853 move_to_cb (ModestMailOperation *mail_op, 
4854             gpointer user_data)
4855 {
4856         MoveToHelper *helper = (MoveToHelper *) user_data;
4857
4858         /* Note that the operation could have failed, in that case do
4859            nothing */
4860         if (modest_mail_operation_get_status (mail_op) == 
4861             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4862
4863                 GObject *object = modest_mail_operation_get_source (mail_op);
4864                 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4865                         ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4866
4867                         if (!modest_msg_view_window_select_next_message (self) &&
4868                             !modest_msg_view_window_select_previous_message (self)) {
4869                                 /* No more messages to view, so close this window */
4870                                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4871                         }
4872                 } else if (MODEST_IS_MAIN_WINDOW (object) && 
4873                            gtk_tree_row_reference_valid (helper->reference)) {
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         if (subject)
6157                 g_free (subject);
6158         if (msg == NULL) {
6159                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
6160         }
6161
6162         /* Frees */
6163         g_object_unref (account);
6164         g_object_unref (folder);
6165         g_object_unref (header);
6166
6167         return msg;
6168 }
6169
6170 gboolean
6171 modest_ui_actions_on_delete_account (GtkWindow *parent_window,
6172                                      const gchar *account_name,
6173                                      const gchar *account_title)
6174 {
6175         ModestAccountMgr *account_mgr;
6176         gchar *txt = NULL;
6177         gint response;
6178         ModestProtocol *protocol;
6179         gboolean removed = FALSE;
6180
6181         g_return_val_if_fail (account_name, FALSE);
6182         g_return_val_if_fail (account_title, FALSE);
6183
6184         account_mgr = modest_runtime_get_account_mgr();
6185
6186         /* The warning text depends on the account type: */
6187         protocol = modest_protocol_registry_get_protocol_by_type (modest_runtime_get_protocol_registry (),
6188                                                                   modest_account_mgr_get_store_protocol (account_mgr,
6189                                                                                                          account_name));
6190         txt = modest_protocol_get_translation (protocol,
6191                                                MODEST_PROTOCOL_TRANSLATION_DELETE_MAILBOX,
6192                                                account_title);
6193         if (txt == NULL)
6194                 txt = g_strdup_printf (_("emev_nc_delete_mailbox"), account_title);
6195
6196         response = modest_platform_run_confirmation_dialog (parent_window, txt);
6197         g_free (txt);
6198         txt = NULL;
6199
6200         if (response == GTK_RESPONSE_OK) {
6201                 /* Remove account. If it succeeds then it also removes
6202                    the account from the ModestAccountView: */
6203                 gboolean is_default = FALSE;
6204                 gchar *default_account_name = modest_account_mgr_get_default_account (account_mgr);
6205                 if (default_account_name && (strcmp (default_account_name, account_name) == 0))
6206                         is_default = TRUE;
6207                 g_free (default_account_name);
6208
6209                 removed = modest_account_mgr_remove_account (account_mgr, account_name);
6210                 if (!removed)
6211                         g_warning ("%s: modest_account_mgr_remove_account() failed.\n", __FUNCTION__);
6212         }
6213         return removed;
6214 }