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