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