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