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