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