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