* Fixes NB#81525, added proper error messages when device memory is full in some...
[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_disk_operations_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_disk_operations_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_disk_operations_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         /* Set draft is there was no error */
2334         if (!modest_mail_operation_get_error (mail_op))
2335                 modest_msg_edit_window_set_draft (edit_window, saved_draft);
2336
2337         g_object_unref(edit_window);
2338 }
2339
2340 gboolean
2341 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2342 {
2343         TnyTransportAccount *transport_account;
2344         ModestMailOperation *mail_operation;
2345         MsgData *data;
2346         gchar *account_name, *from;
2347         ModestAccountMgr *account_mgr;
2348 /*      char *info_text; */
2349         gboolean had_error = FALSE;
2350         guint64 available_disk, expected_size;
2351         gint parts_count;
2352         guint64 parts_size;
2353         ModestMainWindow *win;
2354
2355         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), FALSE);
2356         
2357         data = modest_msg_edit_window_get_msg_data (edit_window);
2358
2359         /* Check size */
2360         available_disk = modest_folder_available_space (NULL);
2361         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2362         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2363                                                  data->html_body,
2364                                                  parts_count,
2365                                                  parts_size);
2366
2367         if ((available_disk != -1) && expected_size > available_disk) {
2368                 modest_msg_edit_window_free_msg_data (edit_window, data);
2369
2370                 modest_platform_information_banner (NULL, NULL, dgettext("ke-recv", "cerm_device_memory_full"));
2371                 return FALSE;
2372         }
2373
2374         account_name = g_strdup (data->account_name);
2375         account_mgr = modest_runtime_get_account_mgr();
2376         if (!account_name)
2377                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2378         if (!account_name) 
2379                 account_name = modest_account_mgr_get_default_account (account_mgr);
2380         if (!account_name) {
2381                 g_printerr ("modest: no account found\n");
2382                 modest_msg_edit_window_free_msg_data (edit_window, data);
2383                 return FALSE;
2384         }
2385
2386         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
2387                 account_name = g_strdup (data->account_name);
2388         }
2389
2390         transport_account =
2391                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2392                                       (modest_runtime_get_account_store(),
2393                                        account_name,
2394                                        TNY_ACCOUNT_TYPE_TRANSPORT));
2395         if (!transport_account) {
2396                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
2397                 g_free (account_name);
2398                 modest_msg_edit_window_free_msg_data (edit_window, data);
2399                 return FALSE;
2400         }
2401         from = modest_account_mgr_get_from_string (account_mgr, account_name);
2402
2403         /* Create the mail operation */         
2404         mail_operation = modest_mail_operation_new_with_error_handling (NULL, modest_ui_actions_disk_operations_error_handler,
2405                                                                         NULL, NULL);
2406         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2407
2408         modest_mail_operation_save_to_drafts (mail_operation,
2409                                               transport_account,
2410                                               data->draft_msg,
2411                                               from,
2412                                               data->to, 
2413                                               data->cc, 
2414                                               data->bcc,
2415                                               data->subject, 
2416                                               data->plain_body, 
2417                                               data->html_body,
2418                                               data->attachments,
2419                                               data->images,
2420                                               data->priority_flags,
2421                                               on_save_to_drafts_cb,
2422                                               g_object_ref(edit_window));
2423
2424         /* Use the main window as the parent of the banner, if the
2425            main window does not exist it won't be shown, if the parent
2426            window exists then it's properly shown. We don't use the
2427            editor window because it could be closed (save to drafts
2428            could happen after closing the window */
2429         win = (ModestMainWindow *)
2430                 modest_window_mgr_get_main_window( modest_runtime_get_window_mgr(), FALSE);
2431         if (win) {
2432                 gchar *text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
2433                 modest_platform_information_banner (GTK_WIDGET (win), NULL, text);
2434                 g_free (text);
2435         }
2436         modest_msg_edit_window_set_modified (edit_window, FALSE);
2437
2438         /* Frees */
2439         g_free (from);
2440         g_free (account_name);
2441         g_object_unref (G_OBJECT (transport_account));
2442         g_object_unref (G_OBJECT (mail_operation));
2443
2444         modest_msg_edit_window_free_msg_data (edit_window, data);
2445
2446         /* ** FIXME **
2447          * If the drafts folder is selected then make the header view
2448          * insensitive while the message is being saved to drafts
2449          * (it'll be sensitive again in on_save_to_drafts_cb()). This
2450          * is not very clean but it avoids letting the drafts folder
2451          * in an inconsistent state: the user could edit the message
2452          * being saved and undesirable things would happen.
2453          * In the average case the user won't notice anything at
2454          * all. In the worst case (the user is editing a really big
2455          * file from Drafts) the header view will be insensitive
2456          * during the saving process (10 or 20 seconds, depending on
2457          * the message). Anyway this is just a quick workaround: once
2458          * we find a better solution it should be removed
2459          * See NB#65125 (commend #18) for details.
2460          */
2461         if (!had_error && win != NULL) {
2462                 ModestFolderView *view = MODEST_FOLDER_VIEW(modest_main_window_get_child_widget(
2463                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW));
2464                 if (view != NULL) {
2465                         TnyFolder *folder = TNY_FOLDER(modest_folder_view_get_selected(view));
2466                         if (folder) {
2467                                 if (modest_tny_folder_is_local_folder(folder)) {
2468                                         TnyFolderType folder_type;
2469                                         folder_type = modest_tny_folder_get_local_or_mmc_folder_type(folder);
2470                                         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
2471                                                 GtkWidget *hdrview = modest_main_window_get_child_widget(
2472                                                         win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2473                                                 if (hdrview) gtk_widget_set_sensitive(hdrview, FALSE);
2474                                         }
2475                                 }
2476                         }
2477                         if (folder != NULL) g_object_unref(folder);
2478                 }
2479         }
2480
2481         return !had_error;
2482 }
2483
2484 /* For instance, when clicking the Send toolbar button when editing a message: */
2485 gboolean
2486 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
2487 {
2488         TnyTransportAccount *transport_account = NULL;
2489         gboolean had_error = FALSE;
2490         guint64 available_disk, expected_size;
2491         gint parts_count;
2492         guint64 parts_size;
2493
2494         g_return_val_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window), TRUE);
2495
2496         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
2497                 return TRUE;
2498         
2499         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
2500
2501         /* Check size */
2502         available_disk = modest_folder_available_space (NULL);
2503         modest_msg_edit_window_get_parts_size (edit_window, &parts_count, &parts_size);
2504         expected_size = modest_tny_msg_estimate_size (data->plain_body,
2505                                                  data->html_body,
2506                                                  parts_count,
2507                                                  parts_size);
2508
2509         if ((available_disk != -1) && expected_size > available_disk) {
2510                 modest_msg_edit_window_free_msg_data (edit_window, data);
2511
2512                 modest_platform_information_banner (NULL, NULL, dgettext("ke-recv", "cerm_device_memory_full"));
2513                 return FALSE;
2514         }
2515
2516         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
2517         gchar *account_name = g_strdup (data->account_name);
2518         if (!account_name)
2519                 account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
2520
2521         if (!account_name) 
2522                 account_name = modest_account_mgr_get_default_account (account_mgr);
2523                 
2524         if (!account_name) {
2525                 modest_msg_edit_window_free_msg_data (edit_window, data);
2526                 /* Run account setup wizard */
2527                 if (!modest_ui_actions_run_account_setup_wizard (MODEST_WINDOW(edit_window))) {
2528                         return TRUE;
2529                 }
2530         }
2531         
2532         /* Get the currently-active transport account for this modest account: */
2533         if (strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID) != 0) {
2534                 transport_account = TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
2535                                                           (modest_runtime_get_account_store(),
2536                                                            account_name, TNY_ACCOUNT_TYPE_TRANSPORT));
2537         }
2538         
2539         if (!transport_account) {
2540                 modest_msg_edit_window_free_msg_data (edit_window, data);
2541                 /* Run account setup wizard */
2542                 if (!modest_ui_actions_run_account_setup_wizard(MODEST_WINDOW(edit_window)))
2543                         return TRUE;
2544         }
2545         
2546         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
2547
2548         /* Create the mail operation */
2549         ModestMailOperation *mail_operation = modest_mail_operation_new (NULL);
2550         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2551
2552         modest_mail_operation_send_new_mail (mail_operation,
2553                                              transport_account,
2554                                              data->draft_msg,
2555                                              from,
2556                                              data->to, 
2557                                              data->cc, 
2558                                              data->bcc,
2559                                              data->subject, 
2560                                              data->plain_body, 
2561                                              data->html_body,
2562                                              data->attachments,
2563                                              data->images,
2564                                              data->priority_flags);
2565
2566         if (modest_mail_operation_get_status (mail_operation) == MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
2567                 modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
2568
2569
2570         if (modest_mail_operation_get_error (mail_operation) != NULL) {
2571                 const GError *error = modest_mail_operation_get_error (mail_operation);
2572                 if (error->code == MODEST_MAIL_OPERATION_ERROR_INSTANCE_CREATION_FAILED) {
2573                         g_warning ("%s failed: %s\n", __FUNCTION__, (modest_mail_operation_get_error (mail_operation))->message);
2574                         modest_platform_information_banner (NULL, NULL, _CS("sfil_ni_not_enough_memory"));
2575                         had_error = TRUE;
2576                 }
2577         }
2578                                              
2579         /* Free data: */
2580         g_free (from);
2581         g_free (account_name);
2582         g_object_unref (G_OBJECT (transport_account));
2583         g_object_unref (G_OBJECT (mail_operation));
2584
2585         modest_msg_edit_window_free_msg_data (edit_window, data);
2586
2587         if (!had_error) {
2588                 modest_msg_edit_window_set_sent (edit_window, TRUE);
2589
2590                 /* Save settings and close the window: */
2591                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2592         }
2593
2594         return !had_error;
2595 }
2596
2597 void 
2598 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2599                                   ModestMsgEditWindow *window)
2600 {
2601         ModestMsgEditFormatState *format_state = NULL;
2602
2603         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2604         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2605
2606         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2607                 return;
2608
2609         format_state = modest_msg_edit_window_get_format_state (window);
2610         g_return_if_fail (format_state != NULL);
2611
2612         format_state->bold = gtk_toggle_action_get_active (action);
2613         modest_msg_edit_window_set_format_state (window, format_state);
2614         g_free (format_state);
2615         
2616 }
2617
2618 void 
2619 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2620                                      ModestMsgEditWindow *window)
2621 {
2622         ModestMsgEditFormatState *format_state = NULL;
2623
2624         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2625         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2626
2627         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2628                 return;
2629
2630         format_state = modest_msg_edit_window_get_format_state (window);
2631         g_return_if_fail (format_state != NULL);
2632
2633         format_state->italics = gtk_toggle_action_get_active (action);
2634         modest_msg_edit_window_set_format_state (window, format_state);
2635         g_free (format_state);
2636         
2637 }
2638
2639 void 
2640 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2641                                      ModestMsgEditWindow *window)
2642 {
2643         ModestMsgEditFormatState *format_state = NULL;
2644
2645         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2646         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2647
2648         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2649                 return;
2650
2651         format_state = modest_msg_edit_window_get_format_state (window);
2652         g_return_if_fail (format_state != NULL);
2653
2654         format_state->bullet = gtk_toggle_action_get_active (action);
2655         modest_msg_edit_window_set_format_state (window, format_state);
2656         g_free (format_state);
2657         
2658 }
2659
2660 void 
2661 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2662                                      GtkRadioAction *selected,
2663                                      ModestMsgEditWindow *window)
2664 {
2665         ModestMsgEditFormatState *format_state = NULL;
2666         GtkJustification value;
2667
2668         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2669
2670         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2671                 return;
2672
2673         value = gtk_radio_action_get_current_value (selected);
2674
2675         format_state = modest_msg_edit_window_get_format_state (window);
2676         g_return_if_fail (format_state != NULL);
2677
2678         format_state->justification = value;
2679         modest_msg_edit_window_set_format_state (window, format_state);
2680         g_free (format_state);
2681 }
2682
2683 void 
2684 modest_ui_actions_on_select_editor_color (GtkAction *action,
2685                                           ModestMsgEditWindow *window)
2686 {
2687         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2688         g_return_if_fail (GTK_IS_ACTION (action));
2689
2690         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2691                 return;
2692
2693         modest_msg_edit_window_select_color (window);
2694 }
2695
2696 void 
2697 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2698                                                      ModestMsgEditWindow *window)
2699 {
2700         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2701         g_return_if_fail (GTK_IS_ACTION (action));
2702
2703         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2704                 return;
2705
2706         modest_msg_edit_window_select_background_color (window);
2707 }
2708
2709 void 
2710 modest_ui_actions_on_insert_image (GtkAction *action,
2711                                    ModestMsgEditWindow *window)
2712 {
2713         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2714         g_return_if_fail (GTK_IS_ACTION (action));
2715
2716         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2717                 return;
2718
2719         modest_msg_edit_window_insert_image (window);
2720 }
2721
2722 void 
2723 modest_ui_actions_on_attach_file (GtkAction *action,
2724                                   ModestMsgEditWindow *window)
2725 {
2726         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2727         g_return_if_fail (GTK_IS_ACTION (action));
2728
2729         modest_msg_edit_window_offer_attach_file (window);
2730 }
2731
2732 void 
2733 modest_ui_actions_on_remove_attachments (GtkAction *action,
2734                                          ModestMsgEditWindow *window)
2735 {
2736         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2737         g_return_if_fail (GTK_IS_ACTION (action));
2738
2739         modest_msg_edit_window_remove_attachments (window, NULL);
2740 }
2741
2742 static void
2743 do_create_folder_cb (ModestMailOperation *mail_op,
2744                      TnyFolderStore *parent_folder, 
2745                      TnyFolder *new_folder,
2746                      gpointer user_data)
2747 {
2748         gchar *suggested_name = (gchar *) user_data;
2749         GtkWindow *source_win = (GtkWindow *) modest_mail_operation_get_source (mail_op);
2750
2751         if (modest_mail_operation_get_error (mail_op)) {
2752
2753                 /* Show an error. If there was some problem writing to
2754                    disk, show it, otherwise show the generic folder
2755                    create error. We do it here and not in an error
2756                    handler because the call to do_create_folder will
2757                    stop the main loop in a gtk_dialog_run and then,
2758                    the message won't be shown until that dialog is
2759                    closed */
2760                 modest_ui_actions_disk_operations_error_handler (mail_op,
2761                                                                  _("mail_in_ui_folder_create_error"));
2762
2763                 /* Try again. Do *NOT* show any error because the mail
2764                    operations system will do it for us because we
2765                    created the mail_op with new_with_error_handler */
2766                 do_create_folder (source_win, parent_folder, (const gchar *) suggested_name);
2767         } else {
2768                 /* the 'source_win' is either the ModestMainWindow, or the 'Move to folder'-dialog
2769                  * FIXME: any other? */         
2770                 GtkWidget *folder_view;
2771
2772                 if (MODEST_IS_MAIN_WINDOW(source_win)) 
2773                         folder_view = 
2774                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (source_win),
2775                                                                      MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2776                 else
2777                         folder_view =
2778                                 get_folder_view_from_move_to_dialog (GTK_WIDGET(source_win));
2779                 
2780                 /* Select the newly created folder */
2781                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view),
2782                                                   new_folder, FALSE);
2783                 g_object_unref (new_folder);
2784         }
2785         /* Free. Note that the first time it'll be NULL so noop */
2786         g_free (suggested_name);
2787         g_object_unref (source_win);
2788 }
2789
2790 static void
2791 do_create_folder (GtkWindow *parent_window, 
2792                   TnyFolderStore *parent_folder, 
2793                   const gchar *suggested_name)
2794 {
2795         gint result;
2796         gchar *folder_name = NULL;
2797
2798         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2799                                                         parent_folder,
2800                                                         (gchar *) suggested_name,
2801                                                         &folder_name);
2802         
2803         if (result == GTK_RESPONSE_ACCEPT) {
2804                 ModestMailOperation *mail_op;
2805                 
2806                 mail_op  = modest_mail_operation_new (NULL);                    
2807                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2808                                                  mail_op);
2809                 modest_mail_operation_create_folder (mail_op,
2810                                                      parent_folder,
2811                                                      (const gchar *) folder_name,
2812                                                      do_create_folder_cb,
2813                                                      folder_name);
2814                 g_object_unref (mail_op);
2815         }
2816 }
2817
2818 static void
2819 create_folder_performer (gboolean canceled, 
2820                          GError *err,
2821                          GtkWindow *parent_window, 
2822                          TnyAccount *account, 
2823                          gpointer user_data)
2824 {
2825         TnyFolderStore *parent_folder = TNY_FOLDER_STORE (user_data);
2826
2827         if (canceled || err) {
2828                 goto frees;
2829         }
2830
2831         /* Run the new folder dialog */
2832         do_create_folder (GTK_WINDOW (parent_window), parent_folder, NULL);
2833
2834  frees:
2835         g_object_unref (parent_folder);
2836 }
2837
2838 static void
2839 modest_ui_actions_create_folder(GtkWidget *parent_window,
2840                                 GtkWidget *folder_view)
2841 {
2842         TnyFolderStore *parent_folder;
2843
2844         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2845         
2846         if (parent_folder) {
2847                 /* The parent folder will be freed in the callback */
2848                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (parent_window), 
2849                                                                TRUE,
2850                                                                parent_folder,
2851                                                                create_folder_performer, 
2852                                                                parent_folder);
2853         }
2854 }
2855
2856 void 
2857 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2858 {
2859         GtkWidget *folder_view;
2860         
2861         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2862
2863         folder_view = modest_main_window_get_child_widget (main_window,
2864                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2865         if (!folder_view)
2866                 return;
2867
2868         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2869 }
2870
2871 static void
2872 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2873                                                gpointer user_data)
2874 {
2875         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2876         const GError *error = NULL;
2877         const gchar *message = NULL;
2878         
2879         /* Get error message */
2880         error = modest_mail_operation_get_error (mail_op);
2881         if (!error)
2882                 g_return_if_reached ();
2883
2884         switch (error->code) {
2885         case MODEST_MAIL_OPERATION_ERROR_FOLDER_EXISTS:
2886                 message = _CS("ckdg_ib_folder_already_exists");
2887                 break;
2888         default:
2889                 g_warning ("%s: BUG: unexpected error:[%d]: %s", __FUNCTION__,
2890                            error->code, error->message);
2891                 return;
2892         }
2893
2894         modest_platform_information_banner (GTK_WIDGET (window), NULL, message);
2895 }
2896
2897 typedef struct {
2898         TnyFolderStore *folder;
2899         gchar *new_name;
2900 } RenameFolderInfo;
2901
2902 static void
2903 on_rename_folder_cb (ModestMailOperation *mail_op, 
2904                      TnyFolder *new_folder,
2905                      gpointer user_data)
2906 {
2907         /* Select now */
2908         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (user_data),
2909                                           new_folder, FALSE);
2910 }
2911
2912 static void
2913 on_rename_folder_performer (gboolean canceled, 
2914                             GError *err, 
2915                             GtkWindow *parent_window, 
2916                             TnyAccount *account, 
2917                             gpointer user_data)
2918 {
2919         ModestMailOperation *mail_op = NULL;
2920         GtkTreeSelection *sel = NULL;
2921         GtkWidget *folder_view = NULL;
2922         RenameFolderInfo *data = (RenameFolderInfo*)user_data;
2923
2924         if (!canceled && (err == NULL) && MODEST_IS_MAIN_WINDOW(parent_window)) {
2925
2926                 folder_view = modest_main_window_get_child_widget (
2927                                 MODEST_MAIN_WINDOW (parent_window),
2928                                 MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2929
2930                 mail_op = 
2931                         modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
2932                                         modest_ui_actions_rename_folder_error_handler,
2933                                         parent_window, NULL);
2934
2935                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2936                                 mail_op);
2937
2938                 /* Clear the headers view */
2939                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
2940                 gtk_tree_selection_unselect_all (sel);
2941
2942                 /* Actually rename the folder */
2943                 modest_mail_operation_rename_folder (mail_op,
2944                                                      TNY_FOLDER (data->folder),
2945                                                      (const gchar *) (data->new_name),
2946                                                      on_rename_folder_cb,
2947                                                      folder_view);
2948         }
2949
2950         g_object_unref (mail_op);
2951         g_free (data->new_name);
2952         g_free (data);
2953 }
2954
2955 void 
2956 modest_ui_actions_on_rename_folder (GtkAction *action,
2957                                      ModestMainWindow *main_window)
2958 {
2959         TnyFolderStore *folder;
2960         GtkWidget *folder_view;
2961         GtkWidget *header_view; 
2962
2963         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2964
2965         folder_view = modest_main_window_get_child_widget (main_window,
2966                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
2967         if (!folder_view)
2968                 return;
2969
2970         header_view = modest_main_window_get_child_widget (main_window,
2971                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
2972         
2973         if (!header_view)
2974                 return;
2975
2976         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2977
2978         if (!folder)
2979                 return;
2980
2981         if (TNY_IS_FOLDER (folder)) {
2982                 gchar *folder_name;
2983                 gint response;
2984                 const gchar *current_name;
2985                 TnyFolderStore *parent;
2986                 gboolean do_rename = TRUE;
2987
2988                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2989                 parent = tny_folder_get_folder_store (TNY_FOLDER (folder));
2990                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), 
2991                                                                      parent, current_name, 
2992                                                                      &folder_name);
2993                 g_object_unref (parent);
2994
2995                 if (response != GTK_RESPONSE_ACCEPT || strlen (folder_name) == 0) {
2996                         do_rename = FALSE;
2997                 } else {
2998                         RenameFolderInfo *rename_folder_data = g_new0 (RenameFolderInfo, 1);
2999                         rename_folder_data->folder = folder;
3000                         rename_folder_data->new_name = folder_name;
3001                         modest_platform_connect_if_remote_and_perform (GTK_WINDOW(main_window), TRUE,
3002                                         folder, on_rename_folder_performer, rename_folder_data);
3003                 }
3004         }
3005         g_object_unref (folder);
3006 }
3007
3008 static void
3009 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
3010                                                gpointer user_data)
3011 {
3012         GObject *win = modest_mail_operation_get_source (mail_op);
3013
3014         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
3015                                                 _("mail_in_ui_folder_delete_error"));
3016         g_object_unref (win);
3017 }
3018
3019 typedef struct {
3020         TnyFolderStore *folder;
3021         gboolean move_to_trash;
3022 } DeleteFolderInfo;
3023
3024 static void
3025 on_delete_folder_cb (gboolean canceled, 
3026                   GError *err,
3027                   GtkWindow *parent_window, 
3028                   TnyAccount *account, 
3029                   gpointer user_data)
3030 {
3031         DeleteFolderInfo *info = (DeleteFolderInfo*) user_data;
3032         GtkWidget *folder_view;
3033         ModestMailOperation *mail_op;
3034         GtkTreeSelection *sel;
3035         
3036         if (!MODEST_IS_MAIN_WINDOW(parent_window) || canceled || (err!=NULL)) {
3037                 g_object_unref (G_OBJECT (info->folder));
3038                 g_free (info);
3039                 return;
3040         }
3041         
3042         folder_view = modest_main_window_get_child_widget (
3043                         MODEST_MAIN_WINDOW (parent_window),
3044                         MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3045
3046         /* Unselect the folder before deleting it to free the headers */
3047         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
3048         gtk_tree_selection_unselect_all (sel);
3049
3050         /* Create the mail operation */
3051         mail_op =
3052                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
3053                                 modest_ui_actions_delete_folder_error_handler,
3054                                 NULL, NULL);
3055
3056         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
3057                         mail_op);
3058         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (info->folder), info->move_to_trash);
3059         
3060         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (folder_view));
3061
3062         g_object_unref (G_OBJECT (mail_op));
3063         g_object_unref (G_OBJECT (info->folder));
3064         g_free (info);
3065 }
3066
3067 static void
3068 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash)
3069 {
3070         TnyFolderStore *folder;
3071         GtkWidget *folder_view;
3072         gint response;
3073         gchar *message;
3074         
3075         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3076
3077         folder_view = modest_main_window_get_child_widget (main_window,
3078                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3079         if (!folder_view)
3080                 return;
3081
3082         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3083
3084         /* Show an error if it's an account */
3085         if (!TNY_IS_FOLDER (folder)) {
3086                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
3087                                                         _("mail_in_ui_folder_delete_error"));
3088                 g_object_unref (G_OBJECT (folder));
3089                 return;
3090         }
3091
3092         /* Ask the user */      
3093         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
3094                                     tny_folder_get_name (TNY_FOLDER (folder)));
3095         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
3096                                                             (const gchar *) message);
3097         g_free (message);
3098
3099         if (response == GTK_RESPONSE_OK) {
3100                 DeleteFolderInfo *info;
3101                 info = g_new0(DeleteFolderInfo, 1);
3102                 info->folder = folder;
3103                 info->move_to_trash = move_to_trash;
3104                 g_object_ref (G_OBJECT (info->folder));
3105                 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder));
3106                 modest_platform_connect_if_remote_and_perform (GTK_WINDOW (main_window), 
3107                                                                TRUE,
3108                                                                TNY_FOLDER_STORE (account), 
3109                                                                on_delete_folder_cb, info);
3110                 g_object_unref (account);
3111         }
3112         g_object_unref (G_OBJECT (folder));
3113 }
3114
3115 void 
3116 modest_ui_actions_on_delete_folder (GtkAction *action,
3117                                      ModestMainWindow *main_window)
3118 {
3119         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3120         
3121         delete_folder (main_window, FALSE);
3122 }
3123
3124 void 
3125 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
3126 {
3127         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3128         
3129         delete_folder (main_window, TRUE);
3130 }
3131
3132
3133 void
3134 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
3135                                          const gchar* server_account_name,
3136                                          gchar **username,
3137                                          gchar **password, 
3138                                          gboolean *cancel, 
3139                                          gboolean *remember,
3140                                          ModestMainWindow *main_window)
3141 {
3142         g_return_if_fail(server_account_name);
3143         gboolean completed = FALSE;
3144         
3145         /* Initalize output parameters: */
3146         if (cancel)
3147                 *cancel = FALSE;
3148                 
3149         if (remember)
3150                 *remember = TRUE;
3151                 
3152 #ifdef MODEST_PLATFORM_MAEMO
3153         /* Maemo uses a different (awkward) button order,
3154          * It should probably just use gtk_alternative_dialog_button_order ().
3155          */
3156         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3157                                               NULL,
3158                                               GTK_DIALOG_MODAL,
3159                                               _("mcen_bd_dialog_ok"),
3160                                               GTK_RESPONSE_ACCEPT,
3161                                               _("mcen_bd_dialog_cancel"),
3162                                               GTK_RESPONSE_REJECT,
3163                                               NULL);
3164 #else
3165         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
3166                                               NULL,
3167                                               GTK_DIALOG_MODAL,
3168                                               GTK_STOCK_CANCEL,
3169                                               GTK_RESPONSE_REJECT,
3170                                               GTK_STOCK_OK,
3171                                               GTK_RESPONSE_ACCEPT,
3172                                               NULL);
3173 #endif /* MODEST_PLATFORM_MAEMO */
3174
3175         modest_window_mgr_set_modal (modest_runtime_get_window_mgr(), GTK_WINDOW (dialog));
3176         
3177         gchar *server_name = modest_account_mgr_get_server_account_hostname (
3178                 modest_runtime_get_account_mgr(), server_account_name);
3179         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
3180                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
3181                 if (cancel)
3182                         *cancel = TRUE;
3183                 return;
3184         }
3185         
3186         /* This causes a warning because the logical ID has no %s in it, 
3187          * though the translation does, but there is not much we can do about that: */
3188         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
3189         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
3190                             FALSE, FALSE, 0);
3191         g_free (txt);
3192         g_free (server_name);
3193         server_name = NULL;
3194
3195         /* username: */
3196         gchar *initial_username = modest_account_mgr_get_server_account_username (
3197                 modest_runtime_get_account_mgr(), server_account_name);
3198         
3199         GtkWidget *entry_username = gtk_entry_new ();
3200         if (initial_username)
3201                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
3202         /* Dim this if a connection has ever succeeded with this username,
3203          * as per the UI spec: */
3204         const gboolean username_known = 
3205                 modest_account_mgr_get_server_account_username_has_succeeded(
3206                         modest_runtime_get_account_mgr(), server_account_name);
3207         gtk_widget_set_sensitive (entry_username, !username_known);
3208         
3209 #ifdef MODEST_PLATFORM_MAEMO
3210         /* Auto-capitalization is the default, so let's turn it off: */
3211         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
3212         
3213         /* Create a size group to be used by all captions.
3214          * Note that HildonCaption does not create a default size group if we do not specify one.
3215          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
3216         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
3217         
3218         GtkWidget *caption = hildon_caption_new (sizegroup, 
3219                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
3220         gtk_widget_show (entry_username);
3221         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3222                 FALSE, FALSE, MODEST_MARGIN_HALF);
3223         gtk_widget_show (caption);
3224 #else 
3225         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
3226                             TRUE, FALSE, 0);
3227 #endif /* MODEST_PLATFORM_MAEMO */      
3228                             
3229         /* password: */
3230         GtkWidget *entry_password = gtk_entry_new ();
3231         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
3232         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
3233         
3234 #ifdef MODEST_PLATFORM_MAEMO
3235         /* Auto-capitalization is the default, so let's turn it off: */
3236         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
3237                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
3238         
3239         caption = hildon_caption_new (sizegroup, 
3240                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
3241         gtk_widget_show (entry_password);
3242         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
3243                 FALSE, FALSE, MODEST_MARGIN_HALF);
3244         gtk_widget_show (caption);
3245         g_object_unref (sizegroup);
3246 #else 
3247         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
3248                             TRUE, FALSE, 0);
3249 #endif /* MODEST_PLATFORM_MAEMO */      
3250
3251         if (initial_username != NULL)
3252                 gtk_widget_grab_focus (GTK_WIDGET (entry_password));
3253                                 
3254 /* This is not in the Maemo UI spec:
3255         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
3256         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
3257                             TRUE, FALSE, 0);
3258 */
3259
3260         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3261
3262         while (!completed) {
3263         
3264                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
3265                         if (username) {
3266                                 *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
3267                                 
3268                                 /* Note that an empty field becomes the "" string */
3269                                 if (*username && strlen (*username) > 0) {
3270                                         modest_account_mgr_set_server_account_username (modest_runtime_get_account_mgr(), 
3271                                                                                         server_account_name, 
3272                                                                                         *username);
3273                                         completed = TRUE;
3274                                 
3275                                         const gboolean username_was_changed = 
3276                                                 (strcmp (*username, initial_username) != 0);
3277                                         if (username_was_changed) {
3278                                                 g_warning ("%s: tinymail does not yet support changing the "
3279                                                            "username in the get_password() callback.\n", __FUNCTION__);
3280                                         }
3281                                 } else {
3282                                         /* Show error */
3283                                         modest_platform_information_banner (GTK_WIDGET (dialog), NULL, 
3284                                                                             _("mcen_ib_username_pw_incorrect"));
3285                                         completed = FALSE;
3286                                 }
3287                         }
3288                         
3289                         if (password) {
3290                                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
3291                         
3292                                 /* We do not save the password in the configuration, 
3293                                  * because this function is only called for passwords that should 
3294                                  * not be remembered:
3295                                  modest_server_account_set_password (
3296                                  modest_runtime_get_account_mgr(), server_account_name, 
3297                                  *password);
3298                                  */
3299                         }                       
3300                         if (cancel)
3301                                 *cancel   = FALSE;                      
3302                 } else {
3303                         modest_platform_information_banner(GTK_WIDGET (dialog), 
3304                                                            NULL, _("mail_ib_login_cancelled"));
3305                         completed = TRUE;
3306                         if (username)
3307                                 *username = NULL;                       
3308                         if (password)
3309                                 *password = NULL;                       
3310                         if (cancel)
3311                                 *cancel   = TRUE;
3312                 }
3313         }
3314
3315 /* This is not in the Maemo UI spec:
3316         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
3317                 *remember = TRUE;
3318         else
3319                 *remember = FALSE;
3320 */
3321
3322         gtk_widget_destroy (dialog);
3323         
3324         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
3325 }
3326
3327 void
3328 modest_ui_actions_on_cut (GtkAction *action,
3329                           ModestWindow *window)
3330 {
3331         GtkWidget *focused_widget;
3332         GtkClipboard *clipboard;
3333
3334         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3335         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3336         if (GTK_IS_EDITABLE (focused_widget)) {
3337                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
3338                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3339                 gtk_clipboard_store (clipboard);
3340         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3341                 GtkTextBuffer *buffer;
3342
3343                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3344                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3345                         gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
3346                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3347                         gtk_clipboard_store (clipboard);
3348                 }
3349         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3350                 TnyList *header_list = modest_header_view_get_selected_headers (
3351                                 MODEST_HEADER_VIEW (focused_widget));
3352                 gboolean continue_download = FALSE;
3353                 gint num_of_unc_msgs;
3354
3355                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3356
3357                 if (num_of_unc_msgs) {
3358                         TnyAccount *account = get_account_from_header_list (header_list);
3359                         if (account) {
3360                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3361                                 g_object_unref (account);
3362                         }
3363                 }
3364
3365                 if (num_of_unc_msgs == 0 || continue_download) {
3366 /*                      modest_platform_information_banner (
3367                                         NULL, NULL, _CS("mcen_ib_getting_items"));*/
3368                         modest_header_view_cut_selection (
3369                                         MODEST_HEADER_VIEW (focused_widget));
3370                 }
3371
3372                 g_object_unref (header_list);
3373         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3374                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
3375         }
3376 }
3377
3378 void
3379 modest_ui_actions_on_copy (GtkAction *action,
3380                            ModestWindow *window)
3381 {
3382         GtkClipboard *clipboard;
3383         GtkWidget *focused_widget;
3384         gboolean copied = TRUE;
3385
3386         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3387         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3388
3389         if (GTK_IS_LABEL (focused_widget)) {
3390                 gchar *selection;
3391                 selection = modest_text_utils_label_get_selection (GTK_LABEL (focused_widget));
3392                 gtk_clipboard_set_text (clipboard, selection, -1);
3393                 g_free (selection);
3394                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3395                 gtk_clipboard_store (clipboard);
3396         } else if (GTK_IS_EDITABLE (focused_widget)) {
3397                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
3398                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3399                 gtk_clipboard_store (clipboard);
3400         } else if (GTK_IS_HTML (focused_widget)) {
3401                 gtk_html_copy (GTK_HTML (focused_widget));
3402                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
3403                 gtk_clipboard_store (clipboard);
3404         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3405                 GtkTextBuffer *buffer;
3406                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3407                 if (modest_text_utils_buffer_selection_is_valid (buffer)) {
3408                         gtk_text_buffer_copy_clipboard (buffer, clipboard);
3409                         gtk_clipboard_set_can_store (clipboard, NULL, 0);
3410                         gtk_clipboard_store (clipboard);
3411                 }
3412         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
3413                 TnyList *header_list = modest_header_view_get_selected_headers (
3414                                 MODEST_HEADER_VIEW (focused_widget));
3415                 gboolean continue_download = FALSE;
3416                 gint num_of_unc_msgs;
3417
3418                 num_of_unc_msgs = header_list_count_uncached_msgs(header_list);
3419
3420                 if (num_of_unc_msgs) {
3421                         TnyAccount *account = get_account_from_header_list (header_list);
3422                         if (account) {
3423                                 continue_download = connect_to_get_msg (window, num_of_unc_msgs, account);
3424                                 g_object_unref (account);
3425                         }
3426                 }
3427
3428                 if (num_of_unc_msgs == 0 || continue_download) {
3429                         modest_platform_information_banner (
3430                                         NULL, NULL, _CS("mcen_ib_getting_items"));
3431                         modest_header_view_copy_selection (
3432                                         MODEST_HEADER_VIEW (focused_widget));
3433                 } else
3434                         copied = FALSE;
3435
3436                 g_object_unref (header_list);
3437
3438         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3439                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
3440         }
3441
3442         /* Show information banner if there was a copy to clipboard */
3443         if(copied)
3444                 modest_platform_information_banner (
3445                                 NULL, NULL, _CS("ecoc_ib_edwin_copied"));
3446 }
3447
3448 void
3449 modest_ui_actions_on_undo (GtkAction *action,
3450                            ModestWindow *window)
3451 {
3452         ModestEmailClipboard *clipboard = NULL;
3453
3454         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3455                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
3456         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3457                 /* Clear clipboard source */
3458                 clipboard = modest_runtime_get_email_clipboard ();
3459                 modest_email_clipboard_clear (clipboard);               
3460         }
3461         else {
3462                 g_return_if_reached ();
3463         }
3464 }
3465
3466 void
3467 modest_ui_actions_on_redo (GtkAction *action,
3468                            ModestWindow *window)
3469 {
3470         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3471                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
3472         }
3473         else {
3474                 g_return_if_reached ();
3475         }
3476 }
3477
3478
3479 static void
3480 destroy_information_note (ModestMailOperation *mail_op, 
3481                           gpointer user_data)
3482 {
3483         /* destroy information note */
3484         gtk_widget_destroy (GTK_WIDGET(user_data));
3485 }
3486
3487 static void
3488 destroy_folder_information_note (ModestMailOperation *mail_op, 
3489                                  TnyFolder *new_folder,
3490                                  gpointer user_data)
3491 {
3492         /* destroy information note */
3493         gtk_widget_destroy (GTK_WIDGET(user_data));
3494 }
3495
3496
3497 static void
3498 paste_as_attachment_free (gpointer data)
3499 {
3500         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
3501
3502         gtk_widget_destroy (helper->banner);
3503         g_object_unref (helper->banner);
3504         g_free (helper);
3505 }
3506
3507 static void
3508 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
3509                             TnyHeader *header,
3510                             TnyMsg *msg,
3511                             gpointer userdata)
3512 {
3513         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
3514         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
3515
3516         if (msg == NULL)
3517                 return;
3518
3519         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
3520         
3521 }
3522
3523 void
3524 modest_ui_actions_on_paste (GtkAction *action,
3525                             ModestWindow *window)
3526 {
3527         GtkWidget *focused_widget = NULL;
3528         GtkWidget *inf_note = NULL;
3529         ModestMailOperation *mail_op = NULL;
3530
3531         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3532         if (GTK_IS_EDITABLE (focused_widget)) {
3533                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
3534         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3535                 ModestEmailClipboard *e_clipboard = NULL;
3536                 e_clipboard = modest_runtime_get_email_clipboard ();
3537                 if (modest_email_clipboard_cleared (e_clipboard)) {
3538                         GtkTextBuffer *buffer;
3539                         GtkClipboard *clipboard;
3540
3541                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
3542                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3543                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
3544                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
3545                         ModestMailOperation *mail_op;
3546                         TnyFolder *src_folder;
3547                         TnyList *data;
3548                         gboolean delete;
3549                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
3550                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
3551                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
3552                                                                            _CS("ckct_nw_pasting"));
3553                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
3554                         mail_op = modest_mail_operation_new (G_OBJECT (window));
3555                         if (helper->banner != NULL) {
3556                                 g_object_ref (G_OBJECT (helper->banner));
3557                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
3558                                 gtk_widget_show (GTK_WIDGET (helper->banner));
3559                         }
3560
3561                         if (data != NULL) {
3562                                 modest_mail_operation_get_msgs_full (mail_op, 
3563                                                                      data,
3564                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
3565                                                                      helper,
3566                                                                      paste_as_attachment_free);
3567                         }
3568                 }
3569         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
3570                 ModestEmailClipboard *clipboard = NULL;
3571                 TnyFolder *src_folder = NULL;
3572                 TnyFolderStore *folder_store = NULL;
3573                 TnyList *data = NULL;           
3574                 gboolean delete = FALSE;
3575                 
3576                 /* Check clipboard source */
3577                 clipboard = modest_runtime_get_email_clipboard ();
3578                 if (modest_email_clipboard_cleared (clipboard)) 
3579                         return;
3580                 
3581                 /* Get elements to paste */
3582                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
3583
3584                 /* Create a new mail operation */
3585                 mail_op = modest_mail_operation_new (G_OBJECT(window));
3586                 
3587                 /* Get destination folder */
3588                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
3589
3590                 /* transfer messages  */
3591                 if (data != NULL) {
3592                         gint response = 0;
3593
3594                         /* Ask for user confirmation */
3595                         response = 
3596                                 modest_ui_actions_msgs_move_to_confirmation (window, 
3597                                                                              TNY_FOLDER (folder_store), 
3598                                                                              delete,
3599                                                                              data);
3600                         
3601                         if (response == GTK_RESPONSE_OK) {
3602                                 /* Launch notification */
3603                                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3604                                                                              _CS("ckct_nw_pasting"));
3605                                 if (inf_note != NULL)  {
3606                                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3607                                         gtk_widget_show (GTK_WIDGET(inf_note));
3608                                 }
3609
3610                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3611                                 modest_mail_operation_xfer_msgs (mail_op, 
3612                                                                  data,
3613                                                                  TNY_FOLDER (folder_store),
3614                                                                  delete,
3615                                                                  destroy_information_note,
3616                                                                  inf_note);                             
3617                         } else {
3618                                 g_object_unref (mail_op);
3619                         }
3620                         
3621                 } else if (src_folder != NULL) {                        
3622                         /* Launch notification */
3623                         inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
3624                                                                      _CS("ckct_nw_pasting"));
3625                         if (inf_note != NULL)  {
3626                                 gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
3627                                 gtk_widget_show (GTK_WIDGET(inf_note));
3628                         }
3629                         
3630                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3631                         modest_mail_operation_xfer_folder (mail_op, 
3632                                                            src_folder,
3633                                                            folder_store,
3634                                                            delete,
3635                                                            destroy_folder_information_note,
3636                                                            inf_note);
3637                 }
3638
3639                 /* Free */
3640                 if (data != NULL) 
3641                         g_object_unref (data);
3642                 if (src_folder != NULL) 
3643                         g_object_unref (src_folder);
3644                 if (folder_store != NULL) 
3645                         g_object_unref (folder_store);
3646         }
3647 }
3648
3649
3650 void
3651 modest_ui_actions_on_select_all (GtkAction *action,
3652                                  ModestWindow *window)
3653 {
3654         GtkWidget *focused_widget;
3655
3656         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
3657         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
3658                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
3659         } else if (GTK_IS_LABEL (focused_widget)) {
3660                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
3661         } else if (GTK_IS_EDITABLE (focused_widget)) {
3662                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
3663         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
3664                 GtkTextBuffer *buffer;
3665                 GtkTextIter start, end;
3666
3667                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
3668                 gtk_text_buffer_get_start_iter (buffer, &start);
3669                 gtk_text_buffer_get_end_iter (buffer, &end);
3670                 gtk_text_buffer_select_range (buffer, &start, &end);
3671         } else if (GTK_IS_HTML (focused_widget)) {
3672                 gtk_html_select_all (GTK_HTML (focused_widget));
3673         } else if (MODEST_IS_MAIN_WINDOW (window)) {
3674                 GtkWidget *header_view = focused_widget;
3675                 GtkTreeSelection *selection = NULL;
3676                 
3677                 if (!(MODEST_IS_HEADER_VIEW (focused_widget))) {
3678                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
3679                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3680                 }
3681                                 
3682                 /* Disable window dimming management */
3683                 modest_window_disable_dimming (MODEST_WINDOW(window));
3684                 
3685                 /* Select all messages */
3686                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
3687                 gtk_tree_selection_select_all (selection);
3688
3689                 /* Set focuse on header view */
3690                 gtk_widget_grab_focus (header_view);
3691
3692
3693                 /* Enable window dimming management */
3694                 modest_window_enable_dimming (MODEST_WINDOW(window));
3695                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (window));
3696         }
3697
3698 }
3699
3700 void
3701 modest_ui_actions_on_mark_as_read (GtkAction *action,
3702                                    ModestWindow *window)
3703 {       
3704         g_return_if_fail (MODEST_IS_WINDOW(window));
3705                 
3706         /* Mark each header as read */
3707         do_headers_action (window, headers_action_mark_as_read, NULL);
3708 }
3709
3710 void
3711 modest_ui_actions_on_mark_as_unread (GtkAction *action,
3712                                      ModestWindow *window)
3713 {       
3714         g_return_if_fail (MODEST_IS_WINDOW(window));
3715                 
3716         /* Mark each header as read */
3717         do_headers_action (window, headers_action_mark_as_unread, NULL);
3718 }
3719
3720 void
3721 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
3722                                   GtkRadioAction *selected,
3723                                   ModestWindow *window)
3724 {
3725         gint value;
3726
3727         value = gtk_radio_action_get_current_value (selected);
3728         if (MODEST_IS_WINDOW (window)) {
3729                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
3730         }
3731 }
3732
3733 void
3734 modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
3735                                                GtkRadioAction *selected,
3736                                                ModestWindow *window)
3737 {
3738         TnyHeaderFlags flags;
3739         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3740
3741         flags = gtk_radio_action_get_current_value (selected);
3742         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
3743 }
3744
3745 void
3746 modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
3747                                                   GtkRadioAction *selected,
3748                                                   ModestWindow *window)
3749 {
3750         gint file_format;
3751
3752         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3753
3754         file_format = gtk_radio_action_get_current_value (selected);
3755         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
3756 }
3757
3758
3759 void
3760 modest_ui_actions_on_zoom_plus (GtkAction *action,
3761                                 ModestWindow *window)
3762 {
3763         g_return_if_fail (MODEST_IS_WINDOW (window));
3764
3765         modest_window_zoom_plus (MODEST_WINDOW (window));
3766 }
3767
3768 void     
3769 modest_ui_actions_on_zoom_minus (GtkAction *action,
3770                                  ModestWindow *window)
3771 {
3772         g_return_if_fail (MODEST_IS_WINDOW (window));
3773
3774         modest_window_zoom_minus (MODEST_WINDOW (window));
3775 }
3776
3777 void     
3778 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3779                                            ModestWindow *window)
3780 {
3781         ModestWindowMgr *mgr;
3782         gboolean fullscreen, active;
3783         g_return_if_fail (MODEST_IS_WINDOW (window));
3784
3785         mgr = modest_runtime_get_window_mgr ();
3786
3787         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3788         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3789
3790         if (active != fullscreen) {
3791                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3792                 gtk_window_present (GTK_WINDOW (window));
3793         }
3794 }
3795
3796 void
3797 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3798                                         ModestWindow *window)
3799 {
3800         ModestWindowMgr *mgr;
3801         gboolean fullscreen;
3802
3803         g_return_if_fail (MODEST_IS_WINDOW (window));
3804
3805         mgr = modest_runtime_get_window_mgr ();
3806         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3807         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3808
3809         gtk_window_present (GTK_WINDOW (window));
3810 }
3811
3812 /* 
3813  * Used by modest_ui_actions_on_details to call do_headers_action 
3814  */
3815 static void
3816 headers_action_show_details (TnyHeader *header, 
3817                              ModestWindow *window,
3818                              gpointer user_data)
3819
3820 {
3821         GtkWidget *dialog;
3822         
3823         /* Create dialog */
3824         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3825
3826         /* Run dialog */
3827         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3828         gtk_widget_show_all (dialog);
3829         gtk_dialog_run (GTK_DIALOG (dialog));
3830
3831         gtk_widget_destroy (dialog);
3832 }
3833
3834 /*
3835  * Show the folder details in a ModestDetailsDialog widget
3836  */
3837 static void
3838 show_folder_details (TnyFolder *folder, 
3839                      GtkWindow *window)
3840 {
3841         GtkWidget *dialog;
3842         
3843         /* Create dialog */
3844         dialog = modest_details_dialog_new_with_folder (window, folder);
3845
3846         /* Run dialog */
3847         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
3848         gtk_widget_show_all (dialog);
3849         gtk_dialog_run (GTK_DIALOG (dialog));
3850
3851         gtk_widget_destroy (dialog);
3852 }
3853
3854 /*
3855  * Show the header details in a ModestDetailsDialog widget
3856  */
3857 void     
3858 modest_ui_actions_on_details (GtkAction *action, 
3859                               ModestWindow *win)
3860 {
3861         TnyList * headers_list;
3862         TnyIterator *iter;
3863         TnyHeader *header;              
3864
3865         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3866                 TnyMsg *msg;
3867
3868                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3869                 if (!msg)
3870                         return;
3871                 g_object_unref (msg);           
3872
3873                 headers_list = get_selected_headers (win);
3874                 if (!headers_list)
3875                         return;
3876
3877                 iter = tny_list_create_iterator (headers_list);
3878
3879                 header = TNY_HEADER (tny_iterator_get_current (iter));
3880                 if (header) {
3881                         headers_action_show_details (header, win, NULL);
3882                         g_object_unref (header);
3883                 }
3884
3885                 g_object_unref (iter);
3886                 g_object_unref (headers_list);
3887
3888         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3889                 GtkWidget *folder_view, *header_view;
3890
3891                 /* Check which widget has the focus */
3892                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3893                                                                     MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
3894                 if (gtk_widget_is_focus (folder_view)) {
3895                         TnyFolderStore *folder_store
3896                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3897                         if (!folder_store) {
3898                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3899                                 return; 
3900                         }
3901                         /* Show only when it's a folder */
3902                         /* This function should not be called for account items, 
3903                          * because we dim the menu item for them. */
3904                         if (TNY_IS_FOLDER (folder_store)) {
3905                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3906                         }
3907
3908                         g_object_unref (folder_store);
3909
3910                 } else {
3911                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3912                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
3913                         /* Show details of each header */
3914                         do_headers_action (win, headers_action_show_details, header_view);
3915                 }
3916         }
3917 }
3918
3919 void     
3920 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3921                                      ModestMsgEditWindow *window)
3922 {
3923         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3924
3925         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3926 }
3927
3928 void     
3929 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3930                                       ModestMsgEditWindow *window)
3931 {
3932         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3933
3934         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3935 }
3936
3937 void
3938 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3939                                        ModestMainWindow *main_window)
3940 {
3941         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3942
3943         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3944                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3945         else
3946                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3947 }
3948
3949 void 
3950 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3951                                      ModestWindow *window)
3952 {
3953         gboolean active, fullscreen = FALSE;
3954         ModestWindowMgr *mgr;
3955
3956         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3957
3958         /* Check if we want to toggle the toolbar vuew in fullscreen
3959            or normal mode */
3960         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3961                      "ViewShowToolbarFullScreen")) {
3962                 fullscreen = TRUE;
3963         }
3964
3965         /* Toggle toolbar */
3966         mgr = modest_runtime_get_window_mgr ();
3967         modest_window_mgr_show_toolbars (mgr, G_TYPE_FROM_INSTANCE (window), active, fullscreen);
3968 }
3969
3970 void     
3971 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3972                                            ModestMsgEditWindow *window)
3973 {
3974         modest_msg_edit_window_select_font (window);
3975 }
3976
3977
3978 void
3979 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3980                                                   const gchar *display_name,
3981                                                   GtkWindow *window)
3982 {
3983         /* don't update the display name if it was already set;
3984          * updating the display name apparently is expensive */
3985         const gchar* old_name = gtk_window_get_title (window);
3986
3987         if (display_name == NULL)
3988                 display_name = " ";
3989
3990         if (old_name && display_name && strcmp (old_name, display_name) == 0)
3991                 return; /* don't do anything */
3992
3993         /* This is usually used to change the title of the main window, which
3994          * is the one that holds the folder view. Note that this change can
3995          * happen even when the widget doesn't have the focus. */
3996         gtk_window_set_title (window, display_name);
3997
3998 }
3999
4000 void
4001 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
4002 {
4003         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4004         modest_msg_edit_window_select_contacts (window);
4005 }
4006
4007 void
4008 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
4009 {
4010         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4011         modest_msg_edit_window_check_names (window, FALSE);
4012 }
4013
4014 static void
4015 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
4016 {
4017         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
4018                                          GTK_WIDGET (user_data));
4019 }
4020
4021 /*
4022  * This function is used to track changes in the selection of the
4023  * folder view that is inside the "move to" dialog to enable/disable
4024  * the OK button because we do not want the user to select a disallowed
4025  * destination for a folder.
4026  * The user also not desired to be able to use NEW button on items where
4027  * folder creation is not possibel.
4028  */
4029 static void
4030 on_move_to_dialog_folder_selection_changed (ModestFolderView* self,
4031                                             TnyFolderStore *folder_store,
4032                                             gboolean selected,
4033                                             gpointer user_data)
4034 {
4035         GtkWidget *dialog = NULL;
4036         GtkWidget *ok_button = NULL, *new_button = NULL;
4037         GList *children = NULL;
4038         gboolean ok_sensitive = TRUE, new_sensitive = TRUE;
4039         gboolean moving_folder = FALSE;
4040         gboolean is_local_account = TRUE;
4041         GtkWidget *folder_view = NULL;
4042         ModestTnyFolderRules rules;
4043
4044         g_return_if_fail (MODEST_IS_FOLDER_VIEW(self));
4045         
4046         if (!selected)
4047                 return;
4048         
4049         /* Get the OK button */
4050         dialog = gtk_widget_get_ancestor (GTK_WIDGET (self), GTK_TYPE_DIALOG);
4051         if (!dialog)
4052                 return;
4053
4054         children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
4055         ok_button = GTK_WIDGET (children->next->next->data);
4056         new_button = GTK_WIDGET (children->next->data);
4057         g_list_free (children);
4058
4059         /* check if folder_store is an remote account */
4060         if (TNY_IS_ACCOUNT (folder_store)) {
4061                 TnyAccount *local_account = NULL;
4062                 TnyAccount *mmc_account = NULL;
4063                 ModestTnyAccountStore *account_store = NULL;
4064
4065                 account_store = modest_runtime_get_account_store ();
4066                 local_account = modest_tny_account_store_get_local_folders_account (account_store);
4067                 mmc_account = modest_tny_account_store_get_mmc_folders_account (account_store);
4068
4069                 if ((gpointer) local_account != (gpointer) folder_store &&
4070                     (gpointer) mmc_account != (gpointer) folder_store) {
4071                         const char *proto_name = tny_account_get_proto (TNY_ACCOUNT (folder_store));
4072                         ModestTransportStoreProtocol proto = MODEST_PROTOCOL_STORE_MAILDIR;
4073                         if (proto_name != NULL) {
4074                                 proto = modest_protocol_info_get_transport_store_protocol (proto_name);
4075                         }
4076                         is_local_account = FALSE;
4077                         /* New button should be dimmed on remote
4078                            POP account root */
4079                         new_sensitive = (proto != MODEST_PROTOCOL_STORE_POP);
4080                 }
4081                 g_object_unref (local_account);
4082                 g_object_unref (mmc_account);
4083         }
4084
4085         /* Check the target folder rules */
4086         if (TNY_IS_FOLDER (folder_store)) {
4087                 rules = modest_tny_folder_get_rules (TNY_FOLDER (folder_store));
4088                 if (rules & MODEST_FOLDER_RULES_FOLDER_NON_WRITEABLE) {
4089                         ok_sensitive = FALSE;
4090                         new_sensitive = FALSE;
4091                         goto end;
4092                 }
4093         }
4094
4095         /* Check if we're moving a folder */
4096         if (MODEST_IS_MAIN_WINDOW (user_data)) {
4097                 /* Get the widgets */
4098                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (user_data),
4099                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4100                 if (gtk_widget_is_focus (folder_view))
4101                         moving_folder = TRUE;
4102         }
4103
4104         if (moving_folder) {
4105                 TnyFolderStore *moved_folder = NULL, *parent = NULL;
4106
4107                 /* Get the folder to move */
4108                 moved_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4109                 
4110                 /* Check that we're not moving to the same folder */
4111                 if (TNY_IS_FOLDER (moved_folder)) {
4112                         parent = tny_folder_get_folder_store (TNY_FOLDER (moved_folder));
4113                         if (parent == folder_store)
4114                                 ok_sensitive = FALSE;
4115                         g_object_unref (parent);
4116                 } 
4117
4118                 if (ok_sensitive && TNY_IS_ACCOUNT (folder_store)) {
4119                         /* Do not allow to move to an account unless it's the
4120                            local folders account */
4121                         if (!is_local_account)
4122                                 ok_sensitive = FALSE;
4123                 } 
4124
4125                 if (ok_sensitive && (moved_folder == folder_store)) {
4126                         /* Do not allow to move to itself */
4127                         ok_sensitive = FALSE;
4128                 }
4129                 g_object_unref (moved_folder);
4130         } else {
4131                 TnyFolder *src_folder = NULL;
4132
4133                 /* Moving a message */
4134                 if (MODEST_IS_MSG_VIEW_WINDOW (user_data)) {
4135
4136                         TnyHeader *header = NULL;
4137                         header = modest_msg_view_window_get_header
4138                                 (MODEST_MSG_VIEW_WINDOW (user_data));
4139                         if (!TNY_IS_HEADER(header))
4140                                 g_warning ("%s: could not get source header", __FUNCTION__);
4141                         else
4142                                 src_folder = tny_header_get_folder (header);
4143
4144                         if (header)
4145                                 g_object_unref (header);
4146                 } else {
4147                         src_folder = 
4148                                 TNY_FOLDER (modest_folder_view_get_selected
4149                                             (MODEST_FOLDER_VIEW (folder_view)));
4150                 }
4151
4152                 if (TNY_IS_FOLDER(src_folder)) {
4153                         /* Do not allow to move the msg to the same folder */
4154                         /* Do not allow to move the msg to an account */
4155                         if ((gpointer) src_folder == (gpointer) folder_store ||
4156                             TNY_IS_ACCOUNT (folder_store))
4157                                 ok_sensitive = FALSE;
4158                         g_object_unref (src_folder);
4159                 } else
4160                         g_warning ("%s: could not get source folder", __FUNCTION__);
4161         }
4162
4163  end:
4164         /* Set sensitivity of the OK button */
4165         gtk_widget_set_sensitive (ok_button, ok_sensitive);
4166         /* Set sensitivity of the NEW button */
4167         gtk_widget_set_sensitive (new_button, new_sensitive);
4168 }
4169
4170
4171 #define MODEST_MOVE_TO_DIALOG_FOLDER_VIEW "move-to-dialog-folder-view"
4172
4173 static GtkWidget*
4174 get_folder_view_from_move_to_dialog (GtkWidget *move_to_dialog)
4175 {
4176         return GTK_WIDGET(g_object_get_data (G_OBJECT(move_to_dialog),
4177                                              MODEST_MOVE_TO_DIALOG_FOLDER_VIEW));
4178 }
4179
4180 static GtkWidget*
4181 create_move_to_dialog (GtkWindow *win,
4182                        GtkWidget *folder_view,
4183                        GtkWidget **tree_view)
4184 {
4185         GtkWidget *dialog, *scroll;
4186         GtkWidget *new_button;
4187
4188         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
4189                                               GTK_WINDOW (win),
4190                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
4191                                               NULL);
4192
4193         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_ok"), GTK_RESPONSE_ACCEPT);
4194         /* We do this manually so GTK+ does not associate a response ID for
4195          * the button. */
4196         new_button = gtk_button_new_from_stock (_("mcen_bd_new"));
4197         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
4198         gtk_dialog_add_button (GTK_DIALOG (dialog), _("mcen_bd_dialog_cancel"), GTK_RESPONSE_REJECT);
4199
4200         /* Create scrolled window */
4201         scroll = gtk_scrolled_window_new (NULL, NULL);
4202         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
4203                                          GTK_POLICY_AUTOMATIC,
4204                                          GTK_POLICY_AUTOMATIC);
4205
4206         /* Create folder view */
4207         *tree_view = modest_platform_create_folder_view (NULL);
4208
4209         /* Track changes in the selection to
4210          * disable the OK button whenever "Move to" is not possible
4211          * disbale NEW button whenever New is not possible */
4212         g_signal_connect (*tree_view,
4213                           "folder_selection_changed",
4214                           G_CALLBACK (on_move_to_dialog_folder_selection_changed),
4215                           win);
4216
4217         /* Listen to clicks on New button */
4218         g_signal_connect (G_OBJECT (new_button), 
4219                           "clicked", 
4220                           G_CALLBACK(create_move_to_dialog_on_new_folder), 
4221                           *tree_view);
4222
4223         /* It could happen that we're trying to move a message from a
4224            window (msg window for example) after the main window was
4225            closed, so we can not just get the model of the folder
4226            view */
4227         if (MODEST_IS_FOLDER_VIEW (folder_view)) {
4228                 const gchar *visible_id = NULL;
4229
4230                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4231                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4232                 modest_folder_view_copy_model (MODEST_FOLDER_VIEW(folder_view), 
4233                                                MODEST_FOLDER_VIEW(*tree_view));
4234
4235                 visible_id = 
4236                         modest_folder_view_get_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(folder_view));
4237
4238                 /* Show the same account than the one that is shown in the main window */
4239                 modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW(*tree_view), 
4240                                                                              visible_id);
4241         } else {
4242                 const gchar *active_account_name = NULL;
4243                 ModestAccountMgr *mgr = NULL;
4244                 ModestAccountSettings *settings = NULL;
4245                 ModestServerAccountSettings *store_settings = NULL;
4246
4247                 modest_folder_view_set_style (MODEST_FOLDER_VIEW (*tree_view),
4248                                               MODEST_FOLDER_VIEW_STYLE_SHOW_ALL);
4249                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
4250                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
4251
4252                 active_account_name = modest_window_get_active_account (MODEST_WINDOW (win));
4253                 mgr = modest_runtime_get_account_mgr ();
4254                 settings = modest_account_mgr_load_account_settings (mgr, active_account_name);
4255
4256                 if (settings) {
4257                         const gchar *store_account_name;
4258                         store_settings = modest_account_settings_get_store_settings (settings);
4259                         store_account_name = modest_server_account_settings_get_account_name (store_settings);
4260
4261                         modest_folder_view_set_account_id_of_visible_server_account (MODEST_FOLDER_VIEW (*tree_view),
4262                                                                                      store_account_name);
4263                         g_object_unref (store_settings);
4264                         g_object_unref (settings);
4265                 }
4266         }
4267
4268         /* we keep a pointer to the embedded folder view, so we can retrieve it with
4269          *   get_folder_view_from_move_to_dialog 
4270          * (see above) later (needed for focus handling) 
4271          */
4272         g_object_set_data (G_OBJECT(dialog), MODEST_MOVE_TO_DIALOG_FOLDER_VIEW, *tree_view);
4273
4274         
4275         /* Hide special folders */
4276         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
4277
4278         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
4279
4280         /* Add scroll to dialog */
4281         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
4282                             scroll, TRUE, TRUE, 0);
4283
4284         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
4285         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
4286
4287         return dialog;
4288 }
4289
4290 /*
4291  * Returns TRUE if at least one of the headers of the list belongs to
4292  * a message that has been fully retrieved.
4293  */
4294 #if 0 /* no longer in use. delete in 2007.10 */
4295 static gboolean
4296 has_retrieved_msgs (TnyList *list)
4297 {
4298         TnyIterator *iter;
4299         gboolean found = FALSE;
4300
4301         iter = tny_list_create_iterator (list);
4302         while (!tny_iterator_is_done (iter) && !found) {
4303                 TnyHeader *header;
4304                 TnyHeaderFlags flags = 0;
4305
4306                 header = TNY_HEADER (tny_iterator_get_current (iter));
4307                 if (header) {
4308                         flags = tny_header_get_flags (header);
4309                         if (flags & TNY_HEADER_FLAG_CACHED)
4310 /*                      if (!(flags & TNY_HEADER_FLAG_PARTIAL)) */
4311                                 found = TRUE;
4312
4313                         g_object_unref (header);
4314                 }
4315
4316                 if (!found)
4317                         tny_iterator_next (iter);
4318         }
4319         g_object_unref (iter);
4320
4321         return found;
4322 }
4323 #endif /* 0 */
4324
4325
4326 /*
4327  * Shows a confirmation dialog to the user when we're moving messages
4328  * from a remote server to the local storage. Returns the dialog
4329  * response. If it's other kind of movement then it always returns
4330  * GTK_RESPONSE_OK
4331  *
4332  * This one is used by the next functions:
4333  *      modest_ui_actions_on_paste                      - commented out
4334  *      drag_and_drop_from_header_view (for d&d in modest_folder_view.c)
4335  */
4336 gint
4337 modest_ui_actions_msgs_move_to_confirmation (ModestWindow *win,
4338                                              TnyFolder *dest_folder,
4339                                              gboolean delete,
4340                                              TnyList *headers)
4341 {
4342         gint response = GTK_RESPONSE_OK;
4343         TnyAccount *account = NULL;
4344         TnyFolder *src_folder = NULL;
4345         TnyIterator *iter = NULL;
4346         TnyHeader *header = NULL;
4347
4348         /* return with OK if the destination is a remote folder */
4349         if (modest_tny_folder_is_remote_folder (dest_folder))
4350                 return GTK_RESPONSE_OK;
4351
4352         /* Get source folder */
4353         iter = tny_list_create_iterator (headers);
4354         header = TNY_HEADER (tny_iterator_get_current (iter));
4355         if (header) {
4356                 src_folder = tny_header_get_folder (header);
4357                 g_object_unref (header);
4358         }
4359         g_object_unref (iter);
4360
4361         /* if no src_folder, message may be an attahcment */
4362         if (src_folder == NULL) 
4363                 return GTK_RESPONSE_CANCEL;
4364
4365         /* If the source is a local or MMC folder */
4366         if (!modest_tny_folder_is_remote_folder (src_folder)) {
4367                 g_object_unref (src_folder);
4368                 return GTK_RESPONSE_OK;
4369         }
4370
4371         /* Get the account */
4372         account = tny_folder_get_account (src_folder);
4373
4374         /* now if offline we ask the user */
4375         if(connect_to_get_msg (win, tny_list_get_length (headers), account))
4376                 response = GTK_RESPONSE_OK;
4377         else
4378                 response = GTK_RESPONSE_CANCEL;
4379
4380         /* Frees */
4381         g_object_unref (src_folder);
4382         g_object_unref (account);
4383
4384         return response;
4385 }
4386
4387 static void
4388 move_to_cb (ModestMailOperation *mail_op, 
4389             gpointer user_data)
4390 {
4391         MoveToHelper *helper = (MoveToHelper *) user_data;
4392
4393         /* Note that the operation could have failed, in that case do
4394            nothing */
4395         if (modest_mail_operation_get_status (mail_op) == 
4396             MODEST_MAIL_OPERATION_STATUS_SUCCESS) {
4397
4398                 GObject *object = modest_mail_operation_get_source (mail_op);
4399                 if (MODEST_IS_MSG_VIEW_WINDOW (object)) {
4400                         ModestMsgViewWindow *self = MODEST_MSG_VIEW_WINDOW (object);
4401
4402                         if (!modest_msg_view_window_select_next_message (self) &&
4403                             !modest_msg_view_window_select_previous_message (self)) {
4404                                 /* No more messages to view, so close this window */
4405                                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
4406                         }
4407                 } else if (MODEST_IS_MAIN_WINDOW (object) && helper->reference != NULL) {
4408                         GtkWidget *header_view;
4409                         GtkTreePath *path;
4410                         GtkTreeSelection *sel;
4411
4412                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4413                                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4414                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
4415                         path = gtk_tree_row_reference_get_path (helper->reference);
4416                         gtk_tree_selection_select_path (sel, path);
4417                         gtk_tree_path_free (path);
4418                 }
4419                 g_object_unref (object);
4420         }
4421
4422         /* Close the "Pasting" information banner */
4423         gtk_widget_destroy (GTK_WIDGET(helper->banner));
4424         if (helper->reference != NULL)
4425                 gtk_tree_row_reference_free (helper->reference);
4426         g_free (helper);
4427 }
4428
4429 static void
4430 folder_move_to_cb (ModestMailOperation *mail_op, 
4431                    TnyFolder *new_folder,
4432                    gpointer user_data)
4433 {
4434         GtkWidget *folder_view;
4435         GObject *object;
4436
4437         object = modest_mail_operation_get_source (mail_op);
4438         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(object),
4439                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
4440         g_object_ref (folder_view);
4441         g_object_unref (object);
4442         move_to_cb (mail_op, user_data);
4443         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), new_folder, FALSE);
4444         g_object_unref (folder_view);
4445 }
4446
4447 static void
4448 msgs_move_to_cb (ModestMailOperation *mail_op, 
4449                  gpointer user_data)
4450 {
4451         move_to_cb (mail_op, user_data);
4452 }
4453
4454 void
4455 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
4456                                              gpointer user_data)
4457 {
4458         ModestWindow *main_window = NULL;
4459         GObject *win = NULL;
4460         
4461         /* Disable next automatic folder selection */
4462         main_window = modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
4463                                                          FALSE); /* don't create */
4464         if (main_window) {
4465                 GtkWidget *folder_view = NULL;
4466         
4467                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (main_window),
4468                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW); 
4469                 modest_folder_view_disable_next_folder_selection (MODEST_FOLDER_VIEW(folder_view));
4470                 
4471                 if (user_data && TNY_IS_FOLDER (user_data)) {
4472                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW (folder_view), 
4473                                                           TNY_FOLDER (user_data), FALSE);
4474                 }
4475         }
4476
4477         /* Show notification dialog */
4478         win = modest_mail_operation_get_source (mail_op);
4479         modest_platform_run_information_dialog ((GtkWindow *) win, _("mail_in_ui_folder_move_target_error"));
4480         if (win)
4481                 g_object_unref (win);
4482 }
4483
4484 void
4485 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
4486                                               gpointer user_data)
4487 {
4488         GObject *win = modest_mail_operation_get_source (mail_op);
4489         const GError *error = modest_mail_operation_get_error (mail_op);
4490
4491         g_return_if_fail (error != NULL);
4492         if (error->message != NULL)             
4493                 g_printerr ("modest: %s\n", error->message);
4494         else
4495                 g_printerr ("modest: unkonw error on send&receive operation");
4496
4497         /* Show error message */
4498 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
4499 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4500 /*                                                      _CS("sfil_ib_unable_to_receive")); */
4501 /*      else  */
4502 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
4503 /*                                                      _CS("sfil_ib_unable_to_send")); */
4504         g_object_unref (win);
4505 }
4506
4507 static void
4508 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
4509                        TnyHeader *header, 
4510                        gboolean canceled,
4511                        TnyMsg *msg, 
4512                        GError *err,
4513                        gpointer user_data)
4514 {
4515         TnyList *parts;
4516         TnyIterator *iter;
4517         gint pending_purges = 0;
4518         gboolean some_purged = FALSE;
4519         ModestWindow *win = MODEST_WINDOW (user_data);
4520         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
4521
4522         /* If there was any error */
4523         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
4524                 modest_window_mgr_unregister_header (mgr, header);
4525                 return;
4526         }
4527
4528         /* Once the message has been retrieved for purging, we check if
4529          * it's all ok for purging */
4530
4531         parts = tny_simple_list_new ();
4532         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
4533         iter = tny_list_create_iterator (parts);
4534
4535         while (!tny_iterator_is_done (iter)) {
4536                 TnyMimePart *part;
4537                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4538                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
4539                         if (tny_mime_part_is_purged (part))
4540                                 some_purged = TRUE;
4541                         else
4542                                 pending_purges++;
4543                 }
4544
4545                 if (part)
4546                         g_object_unref (part);
4547
4548                 tny_iterator_next (iter);
4549         }
4550         g_object_unref (iter);
4551         
4552
4553         if (pending_purges>0) {
4554                 gint response;
4555                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
4556
4557                 if (response == GTK_RESPONSE_OK) {
4558                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
4559                         iter = tny_list_create_iterator (parts);
4560                         while (!tny_iterator_is_done (iter)) {
4561                                 TnyMimePart *part;
4562                                 
4563                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
4564                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
4565                                         tny_mime_part_set_purged (part);
4566
4567                                 if (part)
4568                                         g_object_unref (part);
4569
4570                                 tny_iterator_next (iter);
4571                         }
4572                         g_object_unref (iter);
4573                         
4574                         tny_msg_rewrite_cache (msg);
4575                 }
4576      /* } else { */
4577                 /* This string no longer exists, refer to NB#75415 for more info */
4578                 /* modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged")); */
4579         }
4580
4581         modest_window_mgr_unregister_header (mgr, header);
4582
4583         g_object_unref (parts);
4584 }
4585
4586 static void
4587 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
4588                                                      ModestMainWindow *win)
4589 {
4590         GtkWidget *header_view;
4591         TnyList *header_list;
4592         TnyHeader *header;
4593         TnyHeaderFlags flags;
4594         ModestWindow *msg_view_window =  NULL;
4595         gboolean found;
4596
4597         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4598
4599         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
4600                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4601
4602         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
4603         if (!header_list) {
4604                 g_warning ("%s: no header selected", __FUNCTION__);
4605                 return;
4606         }
4607         
4608         if (tny_list_get_length (header_list) == 1) {
4609                 TnyIterator *iter = tny_list_create_iterator (header_list);
4610                 header = TNY_HEADER (tny_iterator_get_current (iter));
4611                 g_object_unref (iter);
4612         } else
4613                 return;
4614         
4615         if (!header || !TNY_IS_HEADER(header)) {
4616                 g_warning ("%s: header is not valid", __FUNCTION__);
4617                 return;
4618         }
4619         
4620         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
4621                                                           header, &msg_view_window);
4622         flags = tny_header_get_flags (header);
4623         if (!(flags & TNY_HEADER_FLAG_CACHED))
4624                 return;
4625         if (found) {
4626                 if (msg_view_window != NULL) 
4627                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
4628                 else {
4629                         /* do nothing; uid was registered before, so window is probably on it's way */
4630                         g_warning ("debug: header %p has already been registered", header);
4631                 }
4632         } else {
4633                 ModestMailOperation *mail_op = NULL;
4634                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header, NULL);
4635                 mail_op = modest_mail_operation_new_with_error_handling (G_OBJECT (win),
4636                                                                          modest_ui_actions_disk_operations_error_handler,
4637                                                                          NULL, NULL);
4638                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
4639                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
4640                 
4641                 g_object_unref (mail_op);
4642         }
4643         if (header)
4644                 g_object_unref (header);
4645         if (header_list)
4646                 g_object_unref (header_list);
4647 }
4648
4649 /*
4650  * Checks if we need a connection to do the transfer and if the user
4651  * wants to connect to complete it
4652  */
4653 void
4654 modest_ui_actions_xfer_messages_check (GtkWindow *parent_window,
4655                                        TnyFolderStore *src_folder,
4656                                        TnyList *headers,
4657                                        TnyFolder *dst_folder,
4658                                        gboolean delete_originals,
4659                                        gboolean *need_connection,
4660                                        gboolean *do_xfer)
4661 {
4662         TnyAccount *src_account;
4663         gint uncached_msgs = 0;
4664
4665         uncached_msgs = header_list_count_uncached_msgs (headers);
4666
4667         /* We don't need any further check if
4668          *
4669          * 1- the source folder is local OR
4670          * 2- the device is already online
4671          */
4672         if (!modest_tny_folder_store_is_remote (src_folder) ||
4673             tny_device_is_online (modest_runtime_get_device())) {
4674                 *need_connection = FALSE;
4675                 *do_xfer = TRUE;
4676                 return;
4677         }
4678
4679         /* We must ask for a connection when
4680          *
4681          *   - the message(s) is not already cached   OR 
4682          *   - the message(s) is cached but the leave_on_server setting
4683          * is FALSE (because we need to sync the source folder to
4684          * delete the message from the server (for IMAP we could do it
4685          * offline, it'll take place the next time we get a
4686          * connection)
4687          */
4688         src_account = get_account_from_folder_store (src_folder);
4689         if (uncached_msgs > 0) {
4690                 guint num_headers;
4691                 const gchar *msg;
4692
4693                 *need_connection = TRUE;
4694                 num_headers = tny_list_get_length (headers);
4695                 msg = ngettext ("mcen_nc_get_msg", "mcen_nc_get_msgs", num_headers);
4696
4697                 if (modest_platform_run_confirmation_dialog (parent_window, msg) ==
4698                     GTK_RESPONSE_CANCEL) {
4699                         *do_xfer = FALSE;
4700                 } else {
4701                         *do_xfer = TRUE;
4702                 }
4703         } else {
4704                 /* The transfer is possible and the user wants to */
4705                 *do_xfer = TRUE;
4706
4707                 if (remote_folder_is_pop (src_folder) && delete_originals) {
4708                         const gchar *account_name;
4709                         gboolean leave_on_server;
4710                         
4711                         account_name = modest_tny_account_get_parent_modest_account_name_for_server_account (src_account);
4712                         leave_on_server = modest_account_mgr_get_leave_on_server (modest_runtime_get_account_mgr (),
4713                                                                                   account_name);
4714                         
4715                         if (leave_on_server == TRUE) {
4716                                 *need_connection = FALSE;
4717                         } else {
4718                                 *need_connection = TRUE;
4719                         }
4720                 } else {
4721                         *need_connection = FALSE;
4722                 }
4723         }
4724
4725         /* Frees */
4726         g_object_unref (src_account);
4727 }
4728
4729
4730 /**
4731  * Utility function that transfer messages from both the main window
4732  * and the msg view window when using the "Move to" dialog
4733  */
4734 static void
4735 xfer_messages_performer  (gboolean canceled, 
4736                           GError *err,
4737                           GtkWindow *parent_window, 
4738                           TnyAccount *account, 
4739                           gpointer user_data)
4740 {
4741         TnyFolderStore *dst_folder = TNY_FOLDER_STORE (user_data);
4742         ModestWindow *win = MODEST_WINDOW (parent_window);
4743         TnyList *headers = NULL;
4744         TnyAccount *dst_account = NULL;
4745         const gchar *proto_str = NULL;
4746         gboolean dst_is_pop = FALSE;
4747
4748         if (canceled || err) {
4749                 /* Show the proper error message */
4750                 modest_ui_actions_on_account_connection_error (parent_window, account);
4751                 g_object_unref (dst_folder);
4752                 return;
4753         }
4754
4755         dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4756         proto_str = tny_account_get_proto (dst_account);
4757
4758         /* tinymail will return NULL for local folders it seems */
4759         dst_is_pop = proto_str &&
4760                 (modest_protocol_info_get_transport_store_protocol (proto_str) == 
4761                  MODEST_PROTOCOL_STORE_POP);
4762
4763         g_object_unref (dst_account);
4764
4765         /* Get selected headers */
4766         headers = get_selected_headers (MODEST_WINDOW (win));
4767         if (!headers) {
4768                 g_warning ("%s: no headers selected", __FUNCTION__);
4769                 return;
4770         }
4771
4772
4773         if (dst_is_pop) {
4774                 modest_platform_information_banner (GTK_WIDGET (win),
4775                                                     NULL,
4776                                                     ngettext("mail_in_ui_folder_move_target_error",
4777                                                              "mail_in_ui_folder_move_targets_error",
4778                                                              tny_list_get_length (headers)));
4779                 g_object_unref (headers);
4780                 return;
4781         }
4782
4783         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4784         helper->banner = modest_platform_animation_banner (GTK_WIDGET (win), NULL,
4785                                                            _CS("ckct_nw_pasting"));
4786         if (helper->banner != NULL)  {
4787                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4788                 gtk_widget_show (GTK_WIDGET(helper->banner));
4789         }
4790
4791         if (MODEST_IS_MAIN_WINDOW (win)) {
4792                 GtkWidget *header_view = 
4793                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
4794                                                              MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
4795                 helper->reference = get_next_after_selected_headers (MODEST_HEADER_VIEW (header_view));
4796         }
4797
4798         ModestMailOperation *mail_op = 
4799                 modest_mail_operation_new_with_error_handling (G_OBJECT(win),
4800                                                                modest_ui_actions_move_folder_error_handler,
4801                                                                NULL, NULL);
4802         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
4803                                          mail_op);
4804
4805         modest_mail_operation_xfer_msgs (mail_op, 
4806                                          headers,
4807                                          TNY_FOLDER (dst_folder),
4808                                          TRUE,
4809                                          msgs_move_to_cb,
4810                                          helper);
4811
4812         g_object_unref (G_OBJECT (mail_op));
4813         g_object_unref (headers);
4814         g_object_unref (dst_folder);
4815 }
4816
4817 typedef struct {
4818         TnyFolder *src_folder;
4819         TnyFolderStore *dst_folder;
4820         gboolean delete_original;
4821         GtkWidget *folder_view;
4822 } MoveFolderInfo;
4823
4824 static void
4825 on_move_folder_cb (gboolean canceled, GError *err, GtkWindow *parent_window, 
4826                 TnyAccount *account, gpointer user_data)
4827 {
4828         MoveFolderInfo *info = (MoveFolderInfo*)user_data;
4829         GtkTreeSelection *sel;
4830         ModestMailOperation *mail_op = NULL;
4831         
4832         if (canceled || err || !MODEST_IS_MAIN_WINDOW (parent_window)) {
4833                 g_object_unref (G_OBJECT (info->src_folder));
4834                 g_object_unref (G_OBJECT (info->dst_folder));
4835                 g_free (info);
4836                 return;
4837         }
4838         
4839         MoveToHelper *helper = g_new0 (MoveToHelper, 1);
4840         helper->banner = modest_platform_animation_banner (GTK_WIDGET (parent_window), NULL,
4841                         _CS("ckct_nw_pasting"));
4842         if (helper->banner != NULL)  {
4843                 gtk_window_set_modal (GTK_WINDOW(helper->banner), FALSE);
4844                 gtk_widget_show (GTK_WIDGET(helper->banner));
4845         }
4846         /* Clean folder on header view before moving it */
4847         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (info->folder_view));
4848         gtk_tree_selection_unselect_all (sel);
4849
4850         /* Let gtk events run. We need that the folder
4851            view frees its reference to the source
4852            folder *before* issuing the mail operation
4853            so we need the signal handler of selection
4854            changed to happen before the mail
4855            operation 
4856         while (gtk_events_pending ())
4857                 gtk_main_iteration ();   */
4858
4859         mail_op =
4860                 modest_mail_operation_new_with_error_handling (G_OBJECT(parent_window),
4861                                 modest_ui_actions_move_folder_error_handler,
4862                                 info->src_folder, NULL);
4863         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
4864                         mail_op);
4865
4866         /* Select *after* the changes */
4867         /* TODO: this function hangs UI after transfer */ 
4868         /*                      modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), */
4869         /*                                                        TNY_FOLDER (src_folder), TRUE); */
4870
4871         modest_mail_operation_xfer_folder (mail_op,
4872                         TNY_FOLDER (info->src_folder),
4873                         info->dst_folder,
4874                         info->delete_original, 
4875                         folder_move_to_cb, 
4876                         helper);
4877
4878         if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_SUCCESS) {       
4879                 modest_folder_view_select_folder (MODEST_FOLDER_VIEW(info->folder_view),
4880                                                   TNY_FOLDER (info->dst_folder), TRUE);
4881         }
4882         
4883         /* Unref mail operation */
4884         g_object_unref (G_OBJECT (mail_op));
4885         g_object_unref (G_OBJECT (info->src_folder));
4886         g_object_unref (G_OBJECT (info->dst_folder));
4887         g_free (user_data);
4888 }
4889
4890 static TnyAccount *
4891 get_account_from_folder_store (TnyFolderStore *folder_store) 
4892 {
4893         if (TNY_IS_ACCOUNT (folder_store))
4894                 return g_object_ref (folder_store);
4895         else
4896                 return tny_folder_get_account (TNY_FOLDER (folder_store));
4897 }
4898
4899 /*
4900  * UI handler for the "Move to" action when invoked from the
4901  * ModestMainWindow
4902  */
4903 static void 
4904 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
4905                                           GtkWidget *folder_view,
4906                                           TnyFolderStore *dst_folder,
4907                                           ModestMainWindow *win)
4908 {
4909         ModestHeaderView *header_view = NULL;
4910         TnyFolderStore *src_folder = NULL;
4911
4912         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
4913
4914         /* Get the source folder */
4915         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
4916
4917         /* Get header view */
4918         header_view = MODEST_HEADER_VIEW(modest_main_window_get_child_widget (win, MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW));
4919
4920         /* Get folder or messages to transfer */
4921         if (gtk_widget_is_focus (folder_view)) {
4922                 gboolean do_xfer = TRUE;
4923
4924                 /* Allow only to transfer folders to the local root folder */
4925                 if (TNY_IS_ACCOUNT (dst_folder) && 
4926                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder) &&
4927                     !modest_tny_account_is_memory_card_account (TNY_ACCOUNT (dst_folder))) {
4928                         do_xfer = FALSE;
4929                 } else if (!TNY_IS_FOLDER (src_folder)) {
4930                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);
4931                         do_xfer = FALSE;
4932                 }
4933
4934                 if (do_xfer) {                  
4935                         MoveFolderInfo *info = g_new0 (MoveFolderInfo, 1);
4936                         DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
4937
4938                         info->src_folder = g_object_ref (src_folder);
4939                         info->dst_folder = g_object_ref (dst_folder);
4940                         info->delete_original = TRUE;
4941                         info->folder_view = folder_view;
4942
4943                         connect_info->callback = on_move_folder_cb;
4944                         connect_info->dst_account = get_account_from_folder_store (TNY_FOLDER_STORE (dst_folder));
4945                         connect_info->data = info;
4946
4947                         modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
4948                                                                    TNY_FOLDER_STORE (src_folder), 
4949                                                                    connect_info);
4950                 }
4951         } else if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
4952                 TnyList *headers;
4953
4954                 headers = modest_header_view_get_selected_headers(header_view);
4955
4956                 /* Transfer the messages */
4957                 transfer_messages_helper (GTK_WINDOW (win), TNY_FOLDER (src_folder), 
4958                                           headers, TNY_FOLDER (dst_folder));
4959
4960                 g_object_unref (headers);
4961         }
4962
4963         /* Frees */
4964         g_object_unref (src_folder);
4965 }
4966
4967
4968 static void
4969 transfer_messages_helper (GtkWindow *win,
4970                           TnyFolder *src_folder,
4971                           TnyList *headers,
4972                           TnyFolder *dst_folder)
4973 {
4974         gboolean need_connection = TRUE;
4975         gboolean do_xfer = TRUE;
4976         
4977         modest_ui_actions_xfer_messages_check (win, TNY_FOLDER_STORE (src_folder), 
4978                                                headers, TNY_FOLDER (dst_folder),
4979                                                TRUE, &need_connection, 
4980                                                &do_xfer);
4981
4982         /* If we don't want to transfer just return */
4983         if (!do_xfer)
4984                 return;
4985
4986         if (need_connection) {
4987                 DoubleConnectionInfo *connect_info = g_slice_new (DoubleConnectionInfo);
4988                 connect_info->callback = xfer_messages_performer;
4989                 connect_info->dst_account = tny_folder_get_account (TNY_FOLDER (dst_folder));
4990                 connect_info->data = g_object_ref (dst_folder);
4991                 
4992                 modest_platform_double_connect_and_perform(GTK_WINDOW (win), TRUE,
4993                                                            TNY_FOLDER_STORE (src_folder), 
4994                                                            connect_info);
4995         } else {
4996                 TnyAccount *src_account = get_account_from_folder_store (TNY_FOLDER_STORE (src_folder));
4997                 xfer_messages_performer (FALSE, NULL, GTK_WINDOW (win),
4998                                          src_account, 
4999                                          g_object_ref (dst_folder));
5000                 g_object_unref (src_account);
5001         }
5002 }
5003
5004 /*
5005  * UI handler for the "Move to" action when invoked from the
5006  * ModestMsgViewWindow
5007  */
5008 static void 
5009 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
5010                                               TnyFolderStore *dst_folder,
5011                                               ModestMsgViewWindow *win)
5012 {
5013         TnyList *headers = NULL;
5014         TnyHeader *header = NULL;
5015         TnyFolder *src_folder = NULL;
5016
5017         g_return_if_fail (TNY_IS_FOLDER (dst_folder));
5018
5019         /* Create header list */
5020         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5021         src_folder = TNY_FOLDER (tny_header_get_folder(header));
5022         headers = tny_simple_list_new ();
5023         tny_list_append (headers, G_OBJECT (header));
5024
5025         /* Transfer the messages */
5026         transfer_messages_helper (GTK_WINDOW (win), src_folder, headers, 
5027                                   TNY_FOLDER (dst_folder));
5028
5029         /* Frees */
5030         g_object_unref (header);
5031         g_object_unref (headers);
5032 }
5033
5034 void 
5035 modest_ui_actions_on_move_to (GtkAction *action, 
5036                               ModestWindow *win)
5037 {
5038         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
5039         gint result = 0;
5040         TnyFolderStore *dst_folder = NULL;
5041         ModestMainWindow *main_window;
5042
5043         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
5044                           MODEST_IS_MSG_VIEW_WINDOW (win));
5045
5046         /* Get the main window if exists */
5047         if (MODEST_IS_MAIN_WINDOW (win))
5048                 main_window = MODEST_MAIN_WINDOW (win);
5049         else
5050                 main_window = 
5051                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr (),
5052                                                                                FALSE)); /* don't create */
5053
5054         /* Get the folder view widget if exists */
5055         if (main_window)
5056                 folder_view = modest_main_window_get_child_widget (main_window,
5057                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5058         else
5059                 folder_view = NULL;
5060
5061         /* Create and run the dialog */
5062         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
5063         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
5064         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5065         result = gtk_dialog_run (GTK_DIALOG(dialog));
5066         g_object_ref (tree_view);
5067         gtk_widget_destroy (dialog);
5068
5069         if (result != GTK_RESPONSE_ACCEPT)
5070                 return;
5071
5072         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
5073         /* Do window specific stuff */
5074         if (MODEST_IS_MAIN_WINDOW (win)) {
5075                 modest_ui_actions_on_main_window_move_to (action,
5076                                 folder_view,
5077                                 dst_folder,
5078                                 MODEST_MAIN_WINDOW (win));
5079         } else {
5080                 modest_ui_actions_on_msg_view_window_move_to (action,
5081                                 dst_folder,
5082                                 MODEST_MSG_VIEW_WINDOW (win));
5083         }
5084
5085         if (dst_folder)
5086                 g_object_unref (dst_folder);
5087 }
5088
5089 /*
5090  * Calls #HeadersFunc for each header already selected in the main
5091  * window or the message currently being shown in the msg view window
5092  */
5093 static void
5094 do_headers_action (ModestWindow *win, 
5095                    HeadersFunc func,
5096                    gpointer user_data)
5097 {
5098         TnyList *headers_list = NULL;
5099         TnyIterator *iter = NULL;
5100         TnyHeader *header = NULL;
5101         TnyFolder *folder = NULL;
5102
5103         /* Get headers */
5104         headers_list = get_selected_headers (win);
5105         if (!headers_list)
5106                 return;
5107
5108         /* Get the folder */
5109         iter = tny_list_create_iterator (headers_list);
5110         header = TNY_HEADER (tny_iterator_get_current (iter));
5111         if (header) {
5112                 folder = tny_header_get_folder (header);
5113                 g_object_unref (header);
5114         }
5115
5116         /* Call the function for each header */
5117         while (!tny_iterator_is_done (iter)) {
5118                 header = TNY_HEADER (tny_iterator_get_current (iter));
5119                 func (header, win, user_data);
5120                 g_object_unref (header);
5121                 tny_iterator_next (iter);
5122         }
5123
5124         /* Trick: do a poke status in order to speed up the signaling
5125            of observers */
5126         tny_folder_poke_status (folder);
5127
5128         /* Frees */
5129         g_object_unref (folder);
5130         g_object_unref (iter);
5131         g_object_unref (headers_list);
5132 }
5133
5134 void 
5135 modest_ui_actions_view_attachment (GtkAction *action,
5136                                    ModestWindow *window)
5137 {
5138         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5139                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
5140         } else {
5141                 /* not supported window for this action */
5142                 g_return_if_reached ();
5143         }
5144 }
5145
5146 void
5147 modest_ui_actions_save_attachments (GtkAction *action,
5148                                     ModestWindow *window)
5149 {
5150         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5151                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
5152         } else {
5153                 /* not supported window for this action */
5154                 g_return_if_reached ();
5155         }
5156 }
5157
5158 void
5159 modest_ui_actions_remove_attachments (GtkAction *action,
5160                                       ModestWindow *window)
5161 {
5162         if (MODEST_IS_MAIN_WINDOW (window)) {
5163                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
5164         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
5165                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
5166         } else {
5167                 /* not supported window for this action */
5168                 g_return_if_reached ();
5169         }
5170 }
5171
5172 void 
5173 modest_ui_actions_on_settings (GtkAction *action, 
5174                                ModestWindow *win)
5175 {
5176         GtkWidget *dialog;
5177
5178         dialog = modest_platform_get_global_settings_dialog ();
5179         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
5180         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
5181         gtk_widget_show_all (dialog);
5182
5183         gtk_dialog_run (GTK_DIALOG (dialog));
5184
5185         gtk_widget_destroy (dialog);
5186 }
5187
5188 void 
5189 modest_ui_actions_on_help (GtkAction *action, 
5190                            GtkWindow *win)
5191 {
5192         const gchar *help_id;
5193
5194         g_return_if_fail (action);
5195         g_return_if_fail (win && GTK_IS_WINDOW(win));
5196         
5197         help_id = modest_window_mgr_get_help_id (modest_runtime_get_window_mgr(), win);
5198         
5199         if (help_id)
5200                 modest_platform_show_help (GTK_WINDOW (win), help_id);
5201         else
5202                 g_warning ("%s: no help for window %p", __FUNCTION__, win);
5203 }
5204
5205 static void
5206 retrieve_msg_contents_performer (gboolean canceled, 
5207                                  GError *err,
5208                                  GtkWindow *parent_window, 
5209                                  TnyAccount *account, 
5210                                  gpointer user_data)
5211 {
5212         ModestMailOperation *mail_op;
5213         TnyList *headers = TNY_LIST (user_data);
5214
5215         if (err || canceled) {
5216                 goto out;
5217         }
5218
5219         /* Create mail operation */
5220         mail_op = modest_mail_operation_new_with_error_handling ((GObject *) parent_window,
5221                                                                  modest_ui_actions_disk_operations_error_handler, 
5222                                                                  NULL, NULL);
5223         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
5224         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
5225
5226         /* Frees */
5227         g_object_unref (mail_op);
5228  out:
5229         g_object_unref (headers);
5230         g_object_unref (account);
5231 }
5232
5233 void 
5234 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
5235                                             ModestWindow *window)
5236 {
5237         TnyList *headers = NULL;
5238         TnyAccount *account = NULL;
5239         TnyIterator *iter = NULL;
5240         TnyHeader *header = NULL;
5241         TnyFolder *folder = NULL;
5242
5243         /* Get headers */
5244         headers = get_selected_headers (window);
5245         if (!headers)
5246                 return;
5247
5248         /* Pick the account */
5249         iter = tny_list_create_iterator (headers);
5250         header = TNY_HEADER (tny_iterator_get_current (iter));
5251         folder = tny_header_get_folder (header);
5252         account = tny_folder_get_account (folder);
5253         g_object_unref (folder);
5254         g_object_unref (header);
5255         g_object_unref (iter);
5256
5257         /* Connect and perform the message retrieval */
5258         modest_platform_connect_and_perform ((GtkWindow *) window, TRUE,
5259                                              g_object_ref (account), 
5260                                              retrieve_msg_contents_performer, 
5261                                              g_object_ref (headers));
5262
5263         /* Frees */
5264         g_object_unref (account);
5265         g_object_unref (headers);
5266 }
5267
5268 void
5269 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
5270 {
5271         g_return_if_fail (MODEST_IS_WINDOW (window));
5272
5273         /* Update dimmed */
5274         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_TOOLBAR);
5275 }
5276
5277 void
5278 modest_ui_actions_check_menu_dimming_rules (ModestWindow *window)
5279 {
5280         g_return_if_fail (MODEST_IS_WINDOW (window));
5281
5282         /* Update dimmed */
5283         modest_window_check_dimming_rules_group (window, MODEST_DIMMING_RULES_MENU);
5284 }
5285
5286 void
5287 modest_ui_actions_on_email_menu_activated (GtkAction *action,
5288                                           ModestWindow *window)
5289 {
5290         g_return_if_fail (MODEST_IS_WINDOW (window));
5291         
5292         /* Update dimmed */
5293         modest_ui_actions_check_menu_dimming_rules (window);
5294 }
5295
5296 void
5297 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
5298                                           ModestWindow *window)
5299 {
5300         g_return_if_fail (MODEST_IS_WINDOW (window));
5301
5302         /* Update dimmed */
5303         modest_ui_actions_check_menu_dimming_rules (window);
5304 }
5305
5306 void
5307 modest_ui_actions_on_view_menu_activated (GtkAction *action,
5308                                           ModestWindow *window)
5309 {
5310         g_return_if_fail (MODEST_IS_WINDOW (window));
5311
5312         /* Update dimmed */
5313         modest_ui_actions_check_menu_dimming_rules (window);
5314 }
5315
5316 void
5317 modest_ui_actions_on_format_menu_activated (GtkAction *action,
5318                                             ModestWindow *window)
5319 {
5320         g_return_if_fail (MODEST_IS_WINDOW (window));
5321
5322         /* Update dimmed */
5323         modest_ui_actions_check_menu_dimming_rules (window);
5324 }
5325
5326 void
5327 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
5328                                           ModestWindow *window)
5329 {
5330         g_return_if_fail (MODEST_IS_WINDOW (window));
5331
5332         /* Update dimmed */
5333         modest_ui_actions_check_menu_dimming_rules (window);
5334 }
5335
5336 void
5337 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
5338                                           ModestWindow *window)
5339 {
5340         g_return_if_fail (MODEST_IS_WINDOW (window));
5341
5342         /* Update dimmed */
5343         modest_ui_actions_check_menu_dimming_rules (window);
5344 }
5345
5346 void
5347 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
5348                                                  ModestWindow *window)
5349 {
5350         g_return_if_fail (MODEST_IS_WINDOW (window));
5351
5352         /* Update dimmed */
5353         modest_ui_actions_check_menu_dimming_rules (window);
5354 }
5355
5356 void
5357 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
5358                                                      ModestWindow *window)
5359 {
5360         g_return_if_fail (MODEST_IS_WINDOW (window));
5361
5362         /* Update dimmed */
5363         modest_ui_actions_check_menu_dimming_rules (window);
5364 }
5365
5366 void
5367 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
5368                                                      ModestWindow *window)
5369 {
5370         g_return_if_fail (MODEST_IS_WINDOW (window));
5371
5372         /* Update dimmed */
5373         modest_ui_actions_check_menu_dimming_rules (window);
5374 }
5375
5376 void
5377 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
5378 {
5379         g_return_if_fail (MODEST_IS_WINDOW (window));
5380
5381         modest_platform_show_search_messages (GTK_WINDOW (window));
5382 }
5383
5384 void     
5385 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
5386 {
5387         g_return_if_fail (MODEST_IS_WINDOW (win));
5388         modest_platform_show_addressbook (GTK_WINDOW (win));
5389 }
5390
5391
5392 void
5393 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
5394                                           ModestWindow *window)
5395 {
5396         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
5397
5398         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
5399 }
5400
5401 static void 
5402 on_send_receive_finished (ModestMailOperation  *mail_op, 
5403                            gpointer user_data)
5404 {
5405         GtkWidget *header_view, *folder_view;
5406         TnyFolderStore *folder_store;
5407         ModestMainWindow *main_win = MODEST_MAIN_WINDOW (user_data);
5408
5409         /* Set send/receive operation finished */       
5410         modest_main_window_notify_send_receive_completed (main_win);
5411
5412         /* Don't refresh the current folder if there were any errors */
5413         if (modest_mail_operation_get_status (mail_op) !=
5414             MODEST_MAIL_OPERATION_STATUS_SUCCESS)
5415                 return;
5416         
5417         /* Refresh the current folder if we're viewing a window. We do
5418            this because the user won't be able to see the new mails in
5419            the selected folder after a Send&Receive because it only
5420            performs a poke_status, i.e, only the number of read/unread
5421            messages is updated, but the new headers are not
5422            downloaded */
5423         folder_view = modest_main_window_get_child_widget (main_win, 
5424                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5425         if (!folder_view)
5426                 return;
5427
5428         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5429         
5430         /* Do not need to refresh INBOX again because the
5431            update_account does it always automatically */
5432         if (folder_store && TNY_IS_FOLDER (folder_store) && 
5433             tny_folder_get_folder_type (TNY_FOLDER (folder_store)) != TNY_FOLDER_TYPE_INBOX) {
5434                 ModestMailOperation *refresh_op;
5435
5436                 header_view = modest_main_window_get_child_widget (main_win,
5437                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5438                 
5439                 /* We do not need to set the contents style
5440                    because it hasn't changed. We also do not
5441                    need to save the widget status. Just force
5442                    a refresh */
5443                 refresh_op = modest_mail_operation_new (G_OBJECT (main_win));
5444                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), refresh_op);
5445                 modest_mail_operation_refresh_folder (refresh_op, TNY_FOLDER (folder_store),
5446                                                       folder_refreshed_cb, main_win);
5447                 g_object_unref (refresh_op);
5448         }
5449         
5450         if (folder_store)
5451                 g_object_unref (folder_store);
5452 }
5453
5454
5455 void 
5456 modest_ui_actions_on_send_queue_error_happened (TnySendQueue *self, 
5457                                                 TnyHeader *header, 
5458                                                 TnyMsg *msg, 
5459                                                 GError *err, 
5460                                                 gpointer user_data)
5461 {
5462         const gchar* server_name = NULL;
5463         TnyTransportAccount *server_account;
5464         gchar *message = NULL;
5465
5466         /* Don't show anything if the user cancelled something */
5467         if (err->code == TNY_SYSTEM_ERROR_CANCEL)
5468                 return;
5469
5470         /* Get the server name: */
5471         server_account = 
5472                 TNY_TRANSPORT_ACCOUNT (tny_camel_send_queue_get_transport_account (TNY_CAMEL_SEND_QUEUE (self)));
5473         if (server_account) {
5474                 server_name = tny_account_get_hostname (TNY_ACCOUNT (server_account));
5475                         
5476                 g_object_unref (server_account);
5477                 server_account = NULL;
5478         }
5479         
5480         g_return_if_fail (server_name);
5481
5482         /* Show the appropriate message text for the GError: */
5483         switch (err->code) {
5484         case TNY_SERVICE_ERROR_CONNECT:
5485                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5486                 break;
5487         case TNY_SERVICE_ERROR_AUTHENTICATE:
5488                 message = g_strdup_printf (_("emev_ni_ui_smtp_authentication_fail_error"), server_name);
5489                 break;
5490         case TNY_SERVICE_ERROR_SEND:
5491                 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
5492                 break;
5493         case TNY_SERVICE_ERROR_UNAVAILABLE:
5494                 message = g_strdup_printf (_("emev_ib_ui_smtp_server_invalid"), server_name);
5495                 break;
5496         default:
5497                 g_warning ("%s: unexpected ERROR %d",
5498                            __FUNCTION__, err->code);
5499                 message = g_strdup (_("emev_ib_ui_smtp_send_error"));
5500                 break;  
5501         }
5502         
5503         /* TODO if the username or the password where not defined we
5504            should show the Accounts Settings dialog or the Connection
5505            specific SMTP server window */
5506
5507         modest_platform_run_information_dialog (NULL, message);
5508         g_free (message);
5509 }
5510
5511 void
5512 modest_ui_actions_on_send_queue_status_changed (ModestTnySendQueue *send_queue,
5513                                                 gchar *msg_id, 
5514                                                 guint status,
5515                                                 gpointer user_data)
5516 {
5517         ModestMainWindow *main_window = NULL;
5518         ModestWindowMgr *mgr = NULL;
5519         GtkWidget *folder_view = NULL, *header_view = NULL;
5520         TnyFolderStore *selected_folder = NULL;
5521         TnyFolderType folder_type;
5522
5523         mgr = modest_runtime_get_window_mgr ();
5524         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (mgr,
5525                                                                              FALSE));/* don't create */
5526         if (!main_window)
5527                 return;
5528
5529         /* Check if selected folder is OUTBOX */
5530         folder_view = modest_main_window_get_child_widget (main_window,
5531                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_FOLDER_VIEW);
5532         header_view = modest_main_window_get_child_widget (main_window,
5533                                                            MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5534
5535         selected_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
5536         if (!TNY_IS_FOLDER (selected_folder)) 
5537                 goto frees;
5538
5539         /* gtk_tree_view_column_queue_resize is only available in GTK+ 2.8 */
5540 #if GTK_CHECK_VERSION(2, 8, 0) 
5541         folder_type = modest_tny_folder_guess_folder_type (TNY_FOLDER (selected_folder)); 
5542         if (folder_type ==  TNY_FOLDER_TYPE_OUTBOX) {           
5543                 GtkTreeViewColumn *tree_column;
5544
5545                 tree_column = gtk_tree_view_get_column (GTK_TREE_VIEW (header_view), 
5546                                                         TNY_GTK_HEADER_LIST_MODEL_FROM_COLUMN);
5547                 gtk_tree_view_column_queue_resize (tree_column);
5548         }
5549 #else
5550         gtk_widget_queue_draw (header_view);
5551 #endif          
5552
5553         /* Rerun dimming rules, because the message could become deletable for example */
5554         modest_window_check_dimming_rules_group (MODEST_WINDOW (main_window), 
5555                                                  MODEST_DIMMING_RULES_TOOLBAR);
5556         
5557         /* Free */
5558  frees:
5559         if (selected_folder != NULL)
5560                 g_object_unref (selected_folder);
5561 }
5562
5563 void 
5564 modest_ui_actions_on_account_connection_error (GtkWindow *parent_window,
5565                                                TnyAccount *account)
5566 {
5567         ModestTransportStoreProtocol proto;
5568         const gchar *proto_name;
5569         gchar *error_note = NULL;
5570         
5571         proto_name = tny_account_get_proto (account);
5572         proto = modest_protocol_info_get_transport_store_protocol (proto_name);
5573         
5574         switch (proto) {
5575         case MODEST_PROTOCOL_STORE_POP:
5576                 error_note = g_strdup_printf (_("emev_ni_ui_pop3_msg_connect_error"), 
5577                                               tny_account_get_hostname (account));
5578                 break;
5579         case MODEST_PROTOCOL_STORE_IMAP:
5580                 error_note = g_strdup_printf (_("emev_ni_ui_imap_connect_server_error"), 
5581                                               tny_account_get_hostname (account));
5582                 break;
5583         case MODEST_PROTOCOL_STORE_MAILDIR:
5584         case MODEST_PROTOCOL_STORE_MBOX:
5585                 error_note = g_strdup (_("emev_nc_mailbox_notavailable"));
5586                 break;
5587         default:
5588                 g_warning ("%s: This should not be reached", __FUNCTION__);
5589         }
5590
5591         if (error_note) {
5592                 modest_platform_run_information_dialog (parent_window, error_note);
5593                 g_free (error_note);
5594         }
5595 }
5596
5597 gchar *
5598 modest_ui_actions_get_msg_already_deleted_error_msg (ModestWindow *win)
5599 {
5600         gchar *msg = NULL;
5601         TnyFolderStore *folder = NULL;
5602         TnyAccount *account = NULL;
5603         ModestTransportStoreProtocol proto;
5604         TnyHeader *header = NULL;
5605
5606         if (MODEST_IS_MAIN_WINDOW (win)) {
5607                 GtkWidget *header_view;
5608                 TnyList* headers = NULL;
5609                 TnyIterator *iter;
5610                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
5611                                                                    MODEST_MAIN_WINDOW_WIDGET_TYPE_HEADER_VIEW);
5612                 headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
5613                 if (!headers || tny_list_get_length (headers) == 0) {
5614                         if (headers)
5615                                 g_object_unref (headers);
5616                         return NULL;
5617                 }
5618                 iter = tny_list_create_iterator (headers);
5619                 header = TNY_HEADER (tny_iterator_get_current (iter));
5620                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
5621                 g_object_unref (iter);
5622                 g_object_unref (headers);
5623         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
5624                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
5625                 folder = TNY_FOLDER_STORE (tny_header_get_folder (header));
5626         }
5627
5628         /* Get the account type */
5629         account = tny_folder_get_account (TNY_FOLDER (folder));
5630         proto = modest_protocol_info_get_transport_store_protocol (tny_account_get_proto (account));
5631         if (proto == MODEST_PROTOCOL_STORE_POP) {
5632                 msg = g_strdup (_("emev_ni_ui_pop3_msg_recv_error"));
5633         } else if (proto == MODEST_PROTOCOL_STORE_IMAP) {
5634                 msg = g_strdup_printf (_("emev_ni_ui_imap_message_not_available_in_server"), 
5635                                        tny_header_get_subject (header));
5636         } else {
5637                 msg = g_strdup_printf (_("mail_ni_ui_folder_get_msg_folder_error"));
5638         }
5639
5640         /* Frees */
5641         g_object_unref (account);
5642         g_object_unref (folder);
5643         g_object_unref (header);
5644
5645         return msg;
5646 }