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