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