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