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