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