1b6ed49c720141828b825bfcdfd571a46cac7c37
[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
45 #include "modest-tny-platform-factory.h"
46 #include "modest-platform.h"
47
48 #ifdef MODEST_PLATFORM_MAEMO
49 #include "maemo/modest-osso-state-saving.h"
50 #endif /* MODEST_PLATFORM_MAEMO */
51
52 #include "widgets/modest-ui-constants.h"
53 #include <widgets/modest-main-window.h>
54 #include <widgets/modest-msg-view-window.h>
55 #include <widgets/modest-account-view-window.h>
56 #include <widgets/modest-details-dialog.h>
57 #include <widgets/modest-attachments-view.h>
58 #include "widgets/modest-global-settings-dialog.h"
59 #include "modest-connection-specific-smtp-window.h"
60 #include "modest-account-mgr-helpers.h"
61 #include "modest-mail-operation.h"
62 #include "modest-text-utils.h"
63
64 #ifdef MODEST_HAVE_EASYSETUP
65 #include "easysetup/modest-easysetup-wizard.h"
66 #endif /* MODEST_HAVE_EASYSETUP */
67
68 #include <modest-widget-memory.h>
69 #include <tny-error.h>
70 #include <tny-simple-list.h>
71 #include <tny-msg-view.h>
72 #include <tny-device.h>
73 #include <tny-merge-folder.h>
74
75 typedef struct _GetMsgAsyncHelper {     
76         ModestWindow *window;
77         ModestMailOperation *mail_op;
78         TnyIterator *iter;
79         guint num_ops;
80         GFunc func;     
81         gpointer user_data;
82 } GetMsgAsyncHelper;
83
84 typedef enum _ReplyForwardAction {
85         ACTION_REPLY,
86         ACTION_REPLY_TO_ALL,
87         ACTION_FORWARD
88 } ReplyForwardAction;
89
90 typedef struct _ReplyForwardHelper {
91         guint reply_forward_type;
92         ReplyForwardAction action;
93         gchar *account_name;
94         GtkWidget *parent_window;
95 } ReplyForwardHelper;
96
97 /*
98  * The do_headers_action uses this kind of functions to perform some
99  * action to each member of a list of headers
100  */
101 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
102
103 static void
104 do_headers_action (ModestWindow *win, 
105                    HeadersFunc func,
106                    gpointer user_data);
107
108
109 static void     open_msg_cb            (ModestMailOperation *mail_op, 
110                                         TnyHeader *header, 
111                                         TnyMsg *msg,
112                                         gpointer user_data);
113
114 static void     reply_forward_cb       (ModestMailOperation *mail_op, 
115                                         TnyHeader *header, 
116                                         TnyMsg *msg,
117                                         gpointer user_data);
118
119 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
120
121 static gchar*   ask_for_folder_name    (GtkWindow *parent_window, const gchar *title);
122
123 void   
124 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
125 {
126         GtkWidget *about;
127         const gchar *authors[] = {
128                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
129                 NULL
130         };
131         about = gtk_about_dialog_new ();
132         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
133         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
134         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
135                                         _("Copyright (c) 2006, Nokia Corporation\n"
136                                           "All rights reserved."));
137         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
138                                        _("a modest e-mail client\n\n"
139                                          "design and implementation: Dirk-Jan C. Binnema\n"
140                                          "contributions from the fine people at KC and Ig\n"
141                                          "uses the tinymail email framework written by Philip van Hoof"));
142         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
143         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
144         
145         gtk_dialog_run (GTK_DIALOG (about));
146         gtk_widget_destroy(about);
147 }
148
149 /*
150  * Gets the list of currently selected messages. If the win is the
151  * main window, then it returns a newly allocated list of the headers
152  * selected in the header view. If win is the msg view window, then
153  * the value returned is a list with just a single header.
154  *
155  * The caller of this funcion must free the list.
156  */
157 static TnyList *
158 get_selected_headers (ModestWindow *win)
159 {
160         if (MODEST_IS_MAIN_WINDOW(win)) {
161                 GtkWidget *header_view;         
162                 
163                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
164                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
165                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
166                 
167         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
168                 /* for MsgViewWindows, we simply return a list with one element */
169                 TnyHeader *header;
170                 TnyList *list = NULL;
171                 
172                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
173                 if (header != NULL) {
174                         list = tny_simple_list_new ();
175                         tny_list_prepend (list, G_OBJECT(header));
176                         g_object_unref (G_OBJECT(header));
177                 }
178
179                 return list;
180
181         } else
182                 return NULL;
183 }
184
185 static void
186 headers_action_mark_as_read (TnyHeader *header,
187                              ModestWindow *win,
188                              gpointer user_data)
189 {
190         TnyHeaderFlags flags;
191
192         g_return_if_fail (TNY_IS_HEADER(header));
193
194         flags = tny_header_get_flags (header);
195         if (flags & TNY_HEADER_FLAG_SEEN) return;
196         tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
197 }
198
199 static void
200 headers_action_mark_as_unread (TnyHeader *header,
201                                ModestWindow *win,
202                                gpointer user_data)
203 {
204         TnyHeaderFlags flags;
205
206         g_return_if_fail (TNY_IS_HEADER(header));
207
208         flags = tny_header_get_flags (header);
209         if (flags & TNY_HEADER_FLAG_SEEN)  {
210                 tny_header_unset_flags (header, TNY_HEADER_FLAG_SEEN);
211         }
212 }
213
214
215 static void
216 headers_action_delete (TnyHeader *header,
217                        ModestWindow *win,
218                        gpointer user_data)
219 {
220         ModestMailOperation *mail_op = NULL;
221
222         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_DELETE, G_OBJECT(win));
223         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
224                                          mail_op);
225         
226         /* Always delete. TODO: Move to trash still not supported */
227         modest_mail_operation_remove_msg (mail_op, header, FALSE);
228         g_object_unref (G_OBJECT (mail_op));
229 }
230
231 void
232 modest_ui_actions_on_delete (GtkAction *action, ModestWindow *win)
233 {
234         TnyList *header_list = NULL;
235         TnyIterator *iter = NULL;
236         TnyHeader *header = NULL;
237         gchar *message = NULL;
238         gchar *desc = NULL;
239         gint response;
240         gboolean found;
241         ModestWindowMgr *mgr;
242
243         g_return_if_fail (MODEST_IS_WINDOW(win));
244
245         header_list = get_selected_headers (win);
246         if (!header_list) return;
247
248         /* Check if any of the headers is already opened */
249         iter = tny_list_create_iterator (header_list);
250         found = FALSE;
251         mgr = modest_runtime_get_window_mgr ();
252         while (!tny_iterator_is_done (iter) && !found) {
253                 header = TNY_HEADER (tny_iterator_get_current (iter));
254                 if (modest_window_mgr_find_window_by_header (mgr, header))
255                         found = TRUE;
256                 g_object_unref (header);
257                 tny_iterator_next (iter);
258         }
259         g_object_unref (iter);
260
261         if (found) {
262                 gchar *num, *msg;
263
264                 num = g_strdup_printf ("%d", tny_list_get_length (header_list));
265                 msg = g_strdup_printf (_("mcen_nc_unable_to_delete_n_messages"), num);
266
267                 modest_platform_run_information_dialog (GTK_WINDOW (win), (const gchar *) msg);
268
269                 g_free (msg);
270                 g_free (num);
271                 g_object_unref (header_list);
272                 return;
273         }
274
275         /* Select message */
276         if (tny_list_get_length(header_list) > 1)
277                 message = g_strdup(_("emev_nc_delete_messages"));
278         else {
279                 iter = tny_list_create_iterator (header_list);
280                 header = TNY_HEADER (tny_iterator_get_current (iter));
281                 desc = g_strdup_printf ("%s", tny_header_get_subject (header)); 
282                 message = g_strdup_printf(_("emev_nc_delete_message"), desc);
283                 g_object_unref (header);
284                 g_object_unref (iter);
285         }
286
287         /* Confirmation dialog */               
288         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
289                                                             message);
290         
291
292         if (response == GTK_RESPONSE_OK) {
293                 if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
294                         gboolean ret_value;
295                         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
296                         return;
297                 }
298                 
299                 /* Remove each header */
300                 do_headers_action (win, headers_action_delete, NULL);
301
302                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
303                         gtk_widget_destroy (GTK_WIDGET(win));
304                 } 
305         }
306
307         /* free */
308         g_free(message);
309         g_free(desc);
310         g_object_unref (header_list);
311 }
312
313
314 void
315 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
316 {
317         #ifdef MODEST_PLATFORM_MAEMO
318         modest_osso_save_state();
319         #endif /* MODEST_PLATFORM_MAEMO */
320         
321         gtk_main_quit ();
322 }
323
324 void
325 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
326 {
327         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
328                 gtk_widget_destroy (GTK_WIDGET (win));
329         } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
330                 gboolean ret_value;
331                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
332         } else if (MODEST_IS_WINDOW (win)) {
333                 gtk_widget_destroy (GTK_WIDGET (win));
334         } else {
335                 g_return_if_reached ();
336         }
337 }
338
339 void
340 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
341 {
342         GtkClipboard *clipboard = NULL;
343         gchar *selection = NULL;
344
345         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
346         selection = gtk_clipboard_wait_for_text (clipboard);
347
348         /* Question: why is the clipboard being used here? 
349          * It doesn't really make a lot of sense. */
350
351         if (selection)
352         {
353                 modest_address_book_add_address (selection);
354                 g_free (selection);
355         }
356 }
357
358 void
359 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
360 {
361         /* This is currently only implemented for Maemo,
362          * because it requires a providers preset file which is not publically available.
363          */
364 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
365         GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
366                                 TRUE /* enabled accounts only */);
367         gboolean accounts_exist = account_names != NULL;
368         g_slist_free (account_names);
369         
370         if (!accounts_exist) {
371                 /* If there are no accounts yet, just show the easy-setup wizard, as per the UI spec: */
372                 ModestEasysetupWizardDialog *wizard = modest_easysetup_wizard_dialog_new ();
373                 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
374                 gtk_dialog_run (GTK_DIALOG (wizard));
375                 gtk_widget_destroy (GTK_WIDGET (wizard));
376         } else  {
377                 /* Show the list of accounts: */
378                 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
379                 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW(win));
380                 gtk_dialog_run (account_win);
381                 gtk_widget_destroy (GTK_WIDGET(account_win));
382         }
383 #else
384         GtkWidget *dialog, *label;
385         
386         /* Create the widgets */
387         
388         dialog = gtk_dialog_new_with_buttons ("Message",
389                                               GTK_WINDOW(win),
390                                               GTK_DIALOG_DESTROY_WITH_PARENT,
391                                               GTK_STOCK_OK,
392                                               GTK_RESPONSE_NONE,
393                                               NULL);
394         label = gtk_label_new ("Hello World!");
395         
396         /* Ensure that the dialog box is destroyed when the user responds. */
397         
398         g_signal_connect_swapped (dialog, "response", 
399                                   G_CALLBACK (gtk_widget_destroy),
400                                   dialog);
401         
402         /* Add the label, and show everything we've added to the dialog. */
403         
404         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
405                            label);
406         gtk_widget_show_all (dialog);
407 #endif /* MODEST_PLATFORM_MAEMO */
408 }
409
410 static void
411 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
412 {
413         ModestWindow *main_window = MODEST_WINDOW (user_data);
414         
415         /* Save any changes. */
416         modest_connection_specific_smtp_window_save_server_accounts (
417                         MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window), 
418                         modest_window_get_active_account (main_window));
419         gtk_widget_destroy (GTK_WIDGET (window));
420 }
421
422 void
423 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
424 {
425         /* This is currently only implemented for Maemo,
426          * because it requires an API (libconic) to detect different connection 
427          * possiblities.
428          */
429 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
430         
431         /* Create the window if necessary: */
432         const gchar *active_account_name = modest_window_get_active_account (win);
433         
434         /* TODO: Dim the menu item (not in the UI spec)? or show a warning,
435          * or show the default account?
436          * If we show the default account then the account name should be shown in 
437          * the window when we show it. */
438         if (!active_account_name) {
439                 g_warning ("%s: No account is active.", __FUNCTION__);
440                 return;
441         }
442                 
443         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
444         modest_connection_specific_smtp_window_fill_with_connections (
445                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), 
446                 modest_runtime_get_account_mgr(), 
447                 active_account_name);
448
449         /* Show the window: */  
450         gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
451         gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
452     gtk_widget_show (specific_window);
453     
454     /* Save changes when the window is hidden: */
455         g_signal_connect (specific_window, "hide", 
456                 G_CALLBACK (on_smtp_servers_window_hide), win);
457 #endif /* MODEST_PLATFORM_MAEMO */
458 }
459
460 void
461 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
462 {
463         ModestWindow *msg_win;
464         TnyMsg *msg = NULL;
465         TnyFolder *folder = NULL;
466         gchar *account_name = NULL;
467         gchar *from_str = NULL;
468 /*      GError *err = NULL; */
469         TnyAccount *account = NULL;
470         ModestWindowMgr *mgr;
471         gchar *signature = NULL;
472         
473         account_name = g_strdup(modest_window_get_active_account (win));
474         if (!account_name)
475                 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
476         if (!account_name) {
477                 g_printerr ("modest: no account found\n");
478                 goto cleanup;
479         }
480         
481         account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
482                                                                        account_name,
483                                                                        TNY_ACCOUNT_TYPE_STORE);
484         if (!account) {
485                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
486                 goto cleanup;
487         }
488
489         from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
490         if (!from_str) {
491                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
492                 goto cleanup;
493         }
494
495         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr (), account_name,
496                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
497                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), account_name,
498                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
499         } else {
500                 signature = g_strdup ("");
501         }
502
503         msg = modest_tny_msg_new ("", from_str, "", "", "", signature, NULL);
504         if (!msg) {
505                 g_printerr ("modest: failed to create new msg\n");
506                 goto cleanup;
507         }
508         
509         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
510         if (!folder) {
511                 g_printerr ("modest: failed to find Drafts folder\n");
512                 goto cleanup;
513         }
514         
515 /*      tny_folder_add_msg (folder, msg, &err); */
516 /*      if (err) { */
517 /*              g_printerr ("modest: error adding msg to Drafts folder: %s", */
518 /*                          err->message); */
519 /*              g_error_free (err); */
520 /*              goto cleanup; */
521 /*      } */
522
523         /* Create and register edit window */
524         /* This is destroyed by TOOD. */
525         msg_win = modest_msg_edit_window_new (msg, account_name);
526         mgr = modest_runtime_get_window_mgr ();
527         modest_window_mgr_register_window (mgr, msg_win);
528
529         if (win)
530                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
531                                               GTK_WINDOW (win));        
532         gtk_widget_show_all (GTK_WIDGET (msg_win));
533
534 cleanup:
535         g_free (account_name);
536         g_free (from_str);
537         g_free (signature);
538         if (account)
539                 g_object_unref (G_OBJECT(account));
540         if (msg)
541                 g_object_unref (G_OBJECT(msg));
542         if (folder)
543                 g_object_unref (G_OBJECT(folder));
544 }
545
546 static void
547 open_msg_cb (ModestMailOperation *mail_op, 
548              TnyHeader *header, 
549              TnyMsg *msg, 
550              gpointer user_data)
551 {
552         ModestWindowMgr *mgr = NULL;
553         ModestWindow *parent_win = NULL;
554         ModestWindow *win = NULL;
555         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
556         gchar *account = NULL;
557         TnyFolder *folder;
558         
559         /* TODO: Show an error? (review the specs) */
560         if (!msg)
561                 return;
562
563         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
564         folder = tny_header_get_folder (header);
565
566         /* Mark header as read */
567         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
568
569         /* Get account */
570         account =  g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
571         if (!account)
572                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
573         
574         /* Gets folder type (OUTBOX headers will be opened in edit window */
575         if (modest_tny_folder_is_local_folder (folder))
576                 folder_type = modest_tny_folder_get_local_folder_type (folder);
577
578         /* If the header is in the drafts folder then open the editor,
579            else the message view window */
580         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
581                 win = modest_msg_edit_window_new (msg, account);
582         } else {
583                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
584
585                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
586                         GtkWidget *header_view;
587                         GtkTreeSelection *sel;
588                         GList *sel_list = NULL;
589                         GtkTreeModel *model;
590                 
591                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
592                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
593
594                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
595                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
596
597                         if (sel_list != NULL) {
598                                 GtkTreeRowReference *row_reference;
599
600                                 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
601                                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
602                                 g_list_free (sel_list);
603                                 
604                                 win = modest_msg_view_window_new_with_header_model (msg, 
605                                                                                     account,
606                                                                                     (const gchar*) uid,
607                                                                                     model, 
608                                                                                     row_reference);
609                                 gtk_tree_row_reference_free (row_reference);
610                         } else {
611                                 win = modest_msg_view_window_new (msg, account, (const gchar*) uid);
612                         }
613                 } else {
614                         win = modest_msg_view_window_new (msg, account, (const gchar*) uid);
615                 }
616                 g_free (uid);
617         }
618         
619         /* Register and show new window */
620         if (win != NULL) {
621                 mgr = modest_runtime_get_window_mgr ();
622                 modest_window_mgr_register_window (mgr, win);
623                 gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent_win));
624                 gtk_widget_show_all (GTK_WIDGET(win));
625         }
626
627         /* Free */
628         g_free(account);
629         g_object_unref (msg);
630         g_object_unref (folder);
631         g_object_unref (header);
632 }
633
634 /*
635  * This function is the error handler of the
636  * modest_mail_operation_get_msgs_full operation
637  */
638 static void
639 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
640                                                gpointer user_data)
641 {
642         const GError *error;
643
644         error = modest_mail_operation_get_error (mail_op);
645         if (error->code == MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT) {
646                 GObject *win = modest_mail_operation_get_source (mail_op);
647
648                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
649                                                         error->message);
650         }
651 }
652
653 /*
654  * This function is used by both modest_ui_actions_on_open and
655  * modest_ui_actions_on_header_activated. This way we always do the
656  * same when trying to open messages.
657  */
658 static void
659 _modest_ui_actions_open (TnyList *headers, ModestWindow *win)
660 {
661         ModestWindowMgr *mgr;
662         TnyIterator *iter;
663         ModestMailOperation *mail_op;
664
665         /* Look if we already have a message view for each header. If
666            true, then remove the header from the list of headers to
667            open */
668         mgr = modest_runtime_get_window_mgr ();
669         iter = tny_list_create_iterator (headers);
670         while (!tny_iterator_is_done (iter)) {
671                 ModestWindow *window;
672                 TnyHeader *header;
673
674                 header = TNY_HEADER (tny_iterator_get_current (iter));
675                 window = modest_window_mgr_find_window_by_header (mgr, header);
676                 if (window) {
677                         /* Do not open again the message and present
678                            the window to the user */
679                         tny_list_remove (headers, G_OBJECT (header));
680                         gtk_window_present (GTK_WINDOW (window));
681                 }
682
683                 g_object_unref (header);
684                 tny_iterator_next (iter);
685         }
686
687         /* Open each message */
688         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
689                                                                  G_OBJECT (win), 
690                                                                  modest_ui_actions_get_msgs_full_error_handler, 
691                                                                  NULL);
692         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
693         modest_mail_operation_get_msgs_full (mail_op, 
694                                              headers, 
695                                              open_msg_cb, 
696                                              NULL, 
697                                              NULL);
698
699         /* Clean */
700         g_object_unref(mail_op);
701 }
702
703 void
704 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
705 {
706         TnyList *headers;
707
708         /* Get headers */
709         headers = get_selected_headers (win);
710         if (!headers)
711                 return;
712
713         /* Open them */
714         _modest_ui_actions_open (headers, win);
715
716         g_object_unref(headers);
717 }
718
719
720 static void
721 free_reply_forward_helper (gpointer data)
722 {
723         ReplyForwardHelper *helper;
724
725         helper = (ReplyForwardHelper *) data;
726         g_free (helper->account_name);
727         g_slice_free (ReplyForwardHelper, helper);
728 }
729
730 static void
731 reply_forward_cb (ModestMailOperation *mail_op, 
732                   TnyHeader *header, 
733                   TnyMsg *msg,
734                   gpointer user_data)
735 {
736         TnyMsg *new_msg;
737         ReplyForwardHelper *rf_helper;
738         ModestWindow *msg_win;
739         ModestEditType edit_type;
740         gchar *from;
741         GError *err = NULL;
742         TnyFolder *folder = NULL;
743         TnyAccount *account = NULL;
744         ModestWindowMgr *mgr;
745         gchar *signature = NULL;
746                         
747         g_return_if_fail (user_data != NULL);
748         rf_helper = (ReplyForwardHelper *) user_data;
749
750         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
751                                                    rf_helper->account_name);
752         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
753                                          rf_helper->account_name,
754                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
755                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
756                                                            rf_helper->account_name,
757                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
758         }
759
760         /* Create reply mail */
761         switch (rf_helper->action) {
762         case ACTION_REPLY:
763                 new_msg = 
764                         modest_tny_msg_create_reply_msg (msg,  from, signature,
765                                                          rf_helper->reply_forward_type,
766                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
767                 break;
768         case ACTION_REPLY_TO_ALL:
769                 new_msg = 
770                         modest_tny_msg_create_reply_msg (msg, from, signature, rf_helper->reply_forward_type,
771                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
772                 edit_type = MODEST_EDIT_TYPE_REPLY;
773                 break;
774         case ACTION_FORWARD:
775                 new_msg = 
776                         modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
777                 edit_type = MODEST_EDIT_TYPE_FORWARD;
778                 break;
779         default:
780                 g_return_if_reached ();
781                 return;
782         }
783
784         g_free (signature);
785
786         if (!new_msg) {
787                 g_printerr ("modest: failed to create message\n");
788                 goto cleanup;
789         }
790
791         account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
792                                                                        rf_helper->account_name,
793                                                                        TNY_ACCOUNT_TYPE_STORE);
794         if (!account) {
795                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
796                 goto cleanup;
797         }
798
799         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
800         if (!folder) {
801                 g_printerr ("modest: failed to find Drafts folder\n");
802                 goto cleanup;
803         }
804         
805         tny_folder_add_msg (folder, msg, &err);
806         if (err) {
807                 g_printerr ("modest: error adding msg to Drafts folder: %s",
808                             err->message);
809                 g_error_free (err);
810                 goto cleanup;
811         }       
812
813         /* Create and register the windows */
814         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
815         mgr = modest_runtime_get_window_mgr ();
816         modest_window_mgr_register_window (mgr, msg_win);
817
818         if (rf_helper->parent_window != NULL) {
819                 gdouble parent_zoom;
820
821                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
822                 modest_window_set_zoom (msg_win, parent_zoom);
823         }
824
825         /* Show edit window */
826         gtk_widget_show_all (GTK_WIDGET (msg_win));
827
828 cleanup:
829         if (new_msg)
830                 g_object_unref (G_OBJECT (new_msg));
831         if (folder)
832                 g_object_unref (G_OBJECT (folder));
833         if (account)
834                 g_object_unref (G_OBJECT (account));
835         g_object_unref (msg);
836         g_object_unref (header);
837 }
838
839 /*
840  * Checks a list of headers. If any of them are not currently
841  * downloaded (CACHED) then it asks the user for permission to
842  * download them.
843  *
844  * Returns FALSE if the user does not want to download the
845  * messages. Returns TRUE if the user allowed the download or if all
846  * of them are currently downloaded
847  */
848 static gboolean
849 download_uncached_messages (TnyList *header_list, GtkWindow *win)
850 {
851         TnyIterator *iter;
852         gboolean found, retval;
853
854         iter = tny_list_create_iterator (header_list);
855         found = FALSE;
856         while (!tny_iterator_is_done (iter) && !found) {
857                 TnyHeader *header;
858                 TnyHeaderFlags flags;
859
860                 header = TNY_HEADER (tny_iterator_get_current (iter));
861                 flags = tny_header_get_flags (header);
862                 /* TODO: is this the right flag?, it seems that some
863                    headers that have been previously downloaded do not
864                    come with it */
865                 found = !(flags & TNY_HEADER_FLAG_CACHED);
866                 g_object_unref (header);
867                 tny_iterator_next (iter);
868         }
869         g_object_unref (iter);
870
871         /* Ask for user permission to download the messages */
872         retval = TRUE;
873         if (found) {
874                 GtkResponseType response;
875                 response = 
876                         modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
877                                                                  _("mcen_nc_get_multi_msg_txt"));
878                 if (response == GTK_RESPONSE_CANCEL)
879                         retval = FALSE;
880         }
881         return retval;
882 }
883
884
885 /*
886  * Common code for the reply and forward actions
887  */
888 static void
889 reply_forward (ReplyForwardAction action, ModestWindow *win)
890 {
891         ModestMailOperation *mail_op = NULL;
892         TnyList *header_list = NULL;
893         ReplyForwardHelper *rf_helper = NULL;
894         guint reply_forward_type;
895         gboolean continue_download;
896         
897         g_return_if_fail (MODEST_IS_WINDOW(win));
898
899         header_list = get_selected_headers (win);
900         if (!header_list)
901                 return;
902
903         /* Check that the messages have been previously downloaded */
904         continue_download = download_uncached_messages (header_list, GTK_WINDOW (win));
905         if (!continue_download) {
906                 g_object_unref (header_list);
907                 return;
908         }
909         
910         reply_forward_type = 
911                 modest_conf_get_int (modest_runtime_get_conf (),
912                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
913                                      NULL);
914         /* We assume that we can only select messages of the
915            same folder and that we reply all of them from the
916            same account. In fact the interface currently only
917            allows single selection */
918         
919         /* Fill helpers */
920         rf_helper = g_slice_new0 (ReplyForwardHelper);
921         rf_helper->reply_forward_type = reply_forward_type;
922         rf_helper->action = action;
923         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
924         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
925                 rf_helper->parent_window = GTK_WIDGET (win);
926         if (!rf_helper->account_name)
927                 rf_helper->account_name =
928                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
929
930         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
931                 TnyMsg *msg;
932                 TnyHeader *header;
933                 /* Get header and message. Do not free them here, the
934                    reply_forward_cb must do it */
935                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
936                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
937                 if (!msg || !header) {
938                         if (msg)
939                                 g_object_unref (msg);
940                         if (header)
941                                 g_object_unref (header);
942                         g_printerr ("modest: no message found\n");
943                         return;
944                 } else
945                         reply_forward_cb (NULL, header, msg, rf_helper);
946         } else {
947                 /* Retrieve messages */
948                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
949                                                                          G_OBJECT(win),
950                                                                          modest_ui_actions_get_msgs_full_error_handler, 
951                                                                          NULL);
952                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
953                 modest_mail_operation_get_msgs_full (mail_op, 
954                                                      header_list, 
955                                                      reply_forward_cb, 
956                                                      rf_helper, 
957                                                      free_reply_forward_helper);
958
959                 /* Clean */
960                 g_object_unref(mail_op);
961         }
962
963         /* Free */
964         g_object_unref (header_list);
965 }
966
967 void
968 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
969 {
970         g_return_if_fail (MODEST_IS_WINDOW(win));
971
972         reply_forward (ACTION_REPLY, win);
973 }
974
975 void
976 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
977 {
978         g_return_if_fail (MODEST_IS_WINDOW(win));
979
980         reply_forward (ACTION_FORWARD, win);
981 }
982
983 void
984 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
985 {
986         g_return_if_fail (MODEST_IS_WINDOW(win));
987
988         reply_forward (ACTION_REPLY_TO_ALL, win);
989 }
990
991 void 
992 modest_ui_actions_on_next (GtkAction *action, 
993                            ModestWindow *window)
994 {
995         if (MODEST_IS_MAIN_WINDOW (window)) {
996                 GtkWidget *header_view;
997
998                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
999                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1000                 if (!header_view)
1001                         return;
1002         
1003                 modest_header_view_select_next (MODEST_HEADER_VIEW(header_view)); 
1004         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1005                 modest_msg_view_window_select_next_message (MODEST_MSG_VIEW_WINDOW (window));
1006         } else {
1007                 g_return_if_reached ();
1008         }
1009 }
1010
1011 void 
1012 modest_ui_actions_on_prev (GtkAction *action, 
1013                            ModestWindow *window)
1014 {
1015         g_return_if_fail (MODEST_IS_WINDOW(window));
1016
1017         if (MODEST_IS_MAIN_WINDOW (window)) {
1018                 GtkWidget *header_view;
1019                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1020                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1021                 if (!header_view)
1022                         return;
1023                 
1024                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1025         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1026                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1027         } else {
1028                 g_return_if_reached ();
1029         }
1030 }
1031
1032 void 
1033 modest_ui_actions_on_sort (GtkAction *action, 
1034                            ModestWindow *window)
1035 {
1036         g_return_if_fail (MODEST_IS_WINDOW(window));
1037
1038         if (MODEST_IS_MAIN_WINDOW (window)) {
1039                 GtkWidget *header_view;
1040                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1041                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1042                 if (!header_view)
1043                         return;
1044
1045                 /* Show sorting dialog */
1046                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1047         }
1048 }
1049
1050 /*
1051  * This function performs the send & receive required actions. The
1052  * window is used to create the mail operation. Typically it should
1053  * always be the main window, but we pass it as argument in order to
1054  * be more flexible.
1055  */
1056 void
1057 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
1058 {
1059         gchar *acc_name = NULL;
1060         ModestMailOperation *mail_op;
1061
1062         /* If no account name was provided then get the current account, and if
1063            there is no current account then pick the default one: */
1064         if (!account_name) {
1065                 acc_name = g_strdup (modest_window_get_active_account(win));
1066                 if (!acc_name)
1067                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1068                 if (!acc_name) {
1069                         g_printerr ("modest: cannot get default account\n");
1070                         return;
1071                 }
1072         } else {
1073                 acc_name = g_strdup (account_name);
1074         }
1075
1076         /* Send & receive. */
1077         /* TODO: The spec wants us to first do any pending deletions, before receiving. */
1078         /* Receive and then send. The operation is tagged initially as
1079            a receive operation because the account update performs a
1080            receive and then a send. The operation changes its type
1081            internally, so the progress objects will receive the proper
1082            progress information */
1083         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
1084         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1085         modest_mail_operation_update_account (mail_op, acc_name);
1086         g_object_unref (G_OBJECT (mail_op));
1087         
1088         /* Free */
1089         g_free (acc_name);
1090 }
1091
1092 /*
1093  * Refreshes all accounts. This function will be used by automatic
1094  * updates
1095  */
1096 void
1097 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1098 {
1099         GSList *account_names, *iter;
1100
1101         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1102                                                           TRUE);
1103
1104         iter = account_names;
1105         while (iter) {                  
1106                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1107                 iter = g_slist_next (iter);
1108         }
1109         
1110         g_slist_foreach (account_names, (GFunc) g_free, NULL);
1111         g_slist_free (account_names);
1112 }
1113
1114 /*
1115  * Handler of the click on Send&Receive button in the main toolbar
1116  */
1117 void
1118 modest_ui_actions_on_send_receive (GtkAction *action,  ModestWindow *win)
1119 {
1120         /* Check that at least one account exists: */
1121         GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
1122                                 TRUE /* enabled accounts only */);
1123         gboolean accounts_exist = account_names != NULL;
1124         g_slist_free (account_names);
1125         
1126         /* If not, allow the user to create an account before trying to send/receive. */
1127         if (!accounts_exist)
1128                 modest_ui_actions_on_accounts (NULL, win);
1129         
1130         /* Refresh the active account */
1131         modest_ui_actions_do_send_receive (NULL, win);
1132 }
1133
1134
1135 void
1136 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1137 {
1138         ModestConf *conf;
1139         GtkWidget *header_view;
1140         
1141         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1142
1143         header_view = modest_main_window_get_child_widget (main_window,
1144                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1145         if (!header_view)
1146                 return;
1147
1148         conf = modest_runtime_get_conf ();
1149         
1150         /* what is saved/restored is depending on the style; thus; we save with
1151          * old style, then update the style, and restore for this new style
1152          */
1153         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1154         
1155         if (modest_header_view_get_style
1156             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1157                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1158                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1159         else
1160                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1161                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1162
1163         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1164                                       MODEST_CONF_HEADER_VIEW_KEY);
1165 }
1166
1167
1168 void 
1169 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1170                                       TnyHeader *header,
1171                                       ModestMainWindow *main_window)
1172 {
1173         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1174
1175         /* If no header has been selected then exit */
1176         if (!header)
1177                 return;
1178
1179         /* Update Main window title */
1180         if (GTK_WIDGET_HAS_FOCUS (header_view)) {
1181                 const gchar *subject = tny_header_get_subject (header);
1182                 if (subject && strcmp (subject, ""))
1183                         gtk_window_set_title (GTK_WINDOW (main_window), subject);
1184                 else
1185                         gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
1186         }
1187
1188         /* Update toolbar dimming state */
1189         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1190 }
1191
1192 void
1193 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1194                                        TnyHeader *header,
1195                                        ModestMainWindow *main_window)
1196 {
1197         TnyList *headers;
1198
1199         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1200         
1201         if (!header)
1202                 return;
1203
1204         headers = tny_simple_list_new ();
1205         tny_list_prepend (headers, G_OBJECT (header));
1206
1207         _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1208
1209         g_object_unref (headers);
1210 }
1211
1212 static void
1213 set_active_account_from_tny_account (TnyAccount *account,
1214                                      ModestWindow *window)
1215 {
1216         const gchar *server_acc_name = tny_account_get_id (account);
1217         
1218         /* We need the TnyAccount provided by the
1219            account store because that is the one that
1220            knows the name of the Modest account */
1221         TnyAccount *modest_server_account = modest_server_account = 
1222                 modest_tny_account_store_get_tny_account_by_id  (modest_runtime_get_account_store (), 
1223                                                                  server_acc_name);
1224         
1225         const gchar *modest_acc_name = 
1226                 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1227         modest_window_set_active_account (window, modest_acc_name);
1228         g_object_unref (modest_server_account);
1229 }
1230
1231 void 
1232 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1233                                                TnyFolderStore *folder_store, 
1234                                                gboolean selected,
1235                                                ModestMainWindow *main_window)
1236 {
1237         ModestConf *conf;
1238         GtkWidget *header_view;
1239         
1240         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1241
1242         header_view = modest_main_window_get_child_widget(main_window,
1243                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
1244         if (!header_view)
1245                 return;
1246         
1247         conf = modest_runtime_get_conf ();
1248
1249         if (TNY_IS_ACCOUNT (folder_store)) {
1250                 /* Update active account */
1251                 set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1252                 /* Show account details */
1253                 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1254         } else if (modest_tny_folder_store_is_virtual_local_folders  (folder_store )) {
1255                 //TODO: Set the virtual folder store as the "active account" somehow:
1256                 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1257         } else {
1258                 if (TNY_IS_FOLDER (folder_store) && selected) {
1259                         
1260                         if (!TNY_IS_MERGE_FOLDER (folder_store)) { /* TnyMergeFolder can have no get_account() implementation. */
1261                                 /* Update the active account */
1262                                 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder_store));
1263                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1264                                 g_object_unref (account);
1265                         }
1266                         
1267                         /* Set folder on header view */
1268                         modest_main_window_set_contents_style (main_window, 
1269                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1270                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1271                                                        TNY_FOLDER (folder_store));
1272                         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1273                                                       MODEST_CONF_HEADER_VIEW_KEY);
1274                 } else {
1275                         /* Update the active account */
1276                         modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
1277                         /* Do not show folder */
1278                         modest_widget_memory_save (conf, G_OBJECT (header_view), MODEST_CONF_HEADER_VIEW_KEY);
1279                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
1280                 }
1281         }
1282
1283         /* Update toolbar dimming state */
1284         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1285 }
1286
1287 void 
1288 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1289                                      ModestWindow *win)
1290 {
1291         GtkWidget *dialog;
1292         gchar *txt, *item;
1293         gboolean online;
1294
1295         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1296         
1297         if (g_main_depth > 0)   
1298                 gdk_threads_enter ();
1299         online = tny_device_is_online (modest_runtime_get_device());
1300
1301         if (online) {
1302                 /* already online -- the item is simply not there... */
1303                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1304                                                  GTK_DIALOG_MODAL,
1305                                                  GTK_MESSAGE_WARNING,
1306                                                  GTK_BUTTONS_OK,
1307                                                  _("The %s you selected cannot be found"),
1308                                                  item);
1309                 gtk_dialog_run (GTK_DIALOG(dialog));
1310         } else {
1311                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1312                                                       GTK_WINDOW (win),
1313                                                       GTK_DIALOG_MODAL,
1314                                                       GTK_STOCK_CANCEL,
1315                                                       GTK_RESPONSE_REJECT,
1316                                                       GTK_STOCK_OK,
1317                                                       GTK_RESPONSE_ACCEPT,
1318                                                       NULL);
1319                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1320                                          "Do you want to get online?"), item);
1321                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1322                                     gtk_label_new (txt), FALSE, FALSE, 0);
1323                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1324                 g_free (txt);
1325
1326                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1327                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1328 //                      modest_platform_connect_and_wait ();;
1329                 }
1330         }
1331         gtk_widget_destroy (dialog);
1332         if (g_main_depth > 0)   
1333                 gdk_threads_leave ();
1334 }
1335
1336 void
1337 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1338                                      ModestWindow *win)
1339 {
1340         /* g_message ("%s %s", __FUNCTION__, link); */
1341 }       
1342
1343
1344 void
1345 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1346                                         ModestWindow *win)
1347 {
1348         modest_platform_activate_uri (link);
1349 }
1350
1351 void
1352 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1353                                           ModestWindow *win)
1354 {
1355         modest_platform_show_uri_popup (link);
1356 }
1357
1358 void
1359 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1360                                              ModestWindow *win)
1361 {
1362         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
1363 }
1364
1365 void
1366 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1367                                           const gchar *address,
1368                                           ModestWindow *win)
1369 {
1370         /* g_message ("%s %s", __FUNCTION__, address); */
1371 }
1372
1373 void
1374 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1375 {
1376         TnyTransportAccount *transport_account;
1377         ModestMailOperation *mail_operation;
1378         MsgData *data;
1379         gchar *account_name, *from;
1380         ModestAccountMgr *account_mgr;
1381
1382         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1383         
1384         data = modest_msg_edit_window_get_msg_data (edit_window);
1385
1386         account_mgr = modest_runtime_get_account_mgr();
1387         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1388         if (!account_name) 
1389                 account_name = modest_account_mgr_get_default_account (account_mgr);
1390         if (!account_name) {
1391                 g_printerr ("modest: no account found\n");
1392                 modest_msg_edit_window_free_msg_data (edit_window, data);
1393                 return;
1394         }
1395         transport_account =
1396                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
1397                                       (modest_runtime_get_account_store(),
1398                                        account_name,
1399                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1400         if (!transport_account) {
1401                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1402                 g_free (account_name);
1403                 modest_msg_edit_window_free_msg_data (edit_window, data);
1404                 return;
1405         }
1406         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1407
1408         /* Create the mail operation */         
1409         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
1410         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1411
1412         modest_mail_operation_save_to_drafts (mail_operation,
1413                                               transport_account,
1414                                               from,
1415                                               data->to, 
1416                                               data->cc, 
1417                                               data->bcc,
1418                                               data->subject, 
1419                                               data->plain_body, 
1420                                               data->html_body,
1421                                               data->attachments,
1422                                               data->priority_flags);
1423         /* Frees */
1424         g_free (from);
1425         g_free (account_name);
1426         g_object_unref (G_OBJECT (transport_account));
1427         g_object_unref (G_OBJECT (mail_operation));
1428
1429         modest_msg_edit_window_free_msg_data (edit_window, data);
1430
1431         /* Save settings and close the window */
1432         gtk_widget_destroy (GTK_WIDGET (edit_window));
1433 }
1434
1435 /* For instance, when clicking the Send toolbar button when editing a message: */
1436 void
1437 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1438 {
1439         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1440
1441         if (!modest_msg_edit_window_check_names (edit_window))
1442                 return;
1443         
1444         /* FIXME: Code added just for testing. The final version will
1445            use the send queue provided by tinymail and some
1446            classifier */
1447         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
1448         gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1449         if (!account_name) 
1450                 account_name = modest_account_mgr_get_default_account (account_mgr);
1451                 
1452         if (!account_name) {
1453                 g_printerr ("modest: no account found\n");
1454                 return;
1455         }
1456         
1457         /* Get the currently-active transport account for this modest account: */
1458         TnyTransportAccount *transport_account =
1459                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
1460                                       (modest_runtime_get_account_store(),
1461                                        account_name));
1462         if (!transport_account) {
1463                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1464                 g_free (account_name);
1465                 return;
1466         }
1467         
1468         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
1469
1470         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
1471
1472         /* mail content checks and dialogs */
1473         if (data->subject == NULL || data->subject[0] == '\0') {
1474                 GtkResponseType response;
1475                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1476                                                                     _("mcen_nc_subject_is_empty_send"));
1477                 if (response == GTK_RESPONSE_CANCEL) {
1478                         g_free (account_name);
1479                         return;
1480                 }
1481         }
1482
1483         if (data->plain_body == NULL || data->plain_body[0] == '\0') {
1484                 GtkResponseType response;
1485                 gchar *note_message;
1486                 gchar *note_subject = data->subject;
1487                 if (note_subject == NULL || note_subject[0] == '\0')
1488                         note_subject = _("mail_va_no_subject");
1489                 note_message = g_strdup_printf (_("emev_ni_ui_smtp_message_null"), note_subject);
1490                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1491                                                                     note_message);
1492                 g_free (note_message);
1493                 if (response == GTK_RESPONSE_CANCEL) {
1494                         g_free (account_name);
1495                         return;
1496                 }
1497         }
1498
1499         /* Create the mail operation */
1500         ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
1501         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1502
1503         modest_mail_operation_send_new_mail (mail_operation,
1504                                              transport_account,
1505                                              from,
1506                                              data->to, 
1507                                              data->cc, 
1508                                              data->bcc,
1509                                              data->subject, 
1510                                              data->plain_body, 
1511                                              data->html_body,
1512                                              data->attachments,
1513                                              data->priority_flags);
1514                                              
1515         /* Free data: */
1516         g_free (from);
1517         g_free (account_name);
1518         g_object_unref (G_OBJECT (transport_account));
1519         g_object_unref (G_OBJECT (mail_operation));
1520
1521         modest_msg_edit_window_free_msg_data (edit_window, data);
1522
1523         /* Save settings and close the window: */
1524         gtk_widget_destroy (GTK_WIDGET (edit_window));
1525 }
1526
1527 void 
1528 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1529                                   ModestMsgEditWindow *window)
1530 {
1531         ModestMsgEditFormatState *format_state = NULL;
1532
1533         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1534         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1535
1536         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1537                 return;
1538
1539         format_state = modest_msg_edit_window_get_format_state (window);
1540         g_return_if_fail (format_state != NULL);
1541
1542         format_state->bold = gtk_toggle_action_get_active (action);
1543         modest_msg_edit_window_set_format_state (window, format_state);
1544         g_free (format_state);
1545         
1546 }
1547
1548 void 
1549 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1550                                      ModestMsgEditWindow *window)
1551 {
1552         ModestMsgEditFormatState *format_state = NULL;
1553
1554         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1555         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1556
1557         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1558                 return;
1559
1560         format_state = modest_msg_edit_window_get_format_state (window);
1561         g_return_if_fail (format_state != NULL);
1562
1563         format_state->italics = gtk_toggle_action_get_active (action);
1564         modest_msg_edit_window_set_format_state (window, format_state);
1565         g_free (format_state);
1566         
1567 }
1568
1569 void 
1570 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
1571                                      ModestMsgEditWindow *window)
1572 {
1573         ModestMsgEditFormatState *format_state = NULL;
1574
1575         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1576         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1577
1578         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1579                 return;
1580
1581         format_state = modest_msg_edit_window_get_format_state (window);
1582         g_return_if_fail (format_state != NULL);
1583
1584         format_state->bullet = gtk_toggle_action_get_active (action);
1585         modest_msg_edit_window_set_format_state (window, format_state);
1586         g_free (format_state);
1587         
1588 }
1589
1590 void 
1591 modest_ui_actions_on_change_justify (GtkRadioAction *action,
1592                                      GtkRadioAction *selected,
1593                                      ModestMsgEditWindow *window)
1594 {
1595         ModestMsgEditFormatState *format_state = NULL;
1596         GtkJustification value;
1597
1598         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1599
1600         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1601                 return;
1602
1603         value = gtk_radio_action_get_current_value (selected);
1604
1605         format_state = modest_msg_edit_window_get_format_state (window);
1606         g_return_if_fail (format_state != NULL);
1607
1608         format_state->justification = value;
1609         modest_msg_edit_window_set_format_state (window, format_state);
1610         g_free (format_state);
1611 }
1612
1613 void 
1614 modest_ui_actions_on_select_editor_color (GtkAction *action,
1615                                           ModestMsgEditWindow *window)
1616 {
1617         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1618         g_return_if_fail (GTK_IS_ACTION (action));
1619
1620         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1621                 return;
1622
1623         modest_msg_edit_window_select_color (window);
1624 }
1625
1626 void 
1627 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
1628                                                      ModestMsgEditWindow *window)
1629 {
1630         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1631         g_return_if_fail (GTK_IS_ACTION (action));
1632
1633         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1634                 return;
1635
1636         modest_msg_edit_window_select_background_color (window);
1637 }
1638
1639 void 
1640 modest_ui_actions_on_insert_image (GtkAction *action,
1641                                    ModestMsgEditWindow *window)
1642 {
1643         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1644         g_return_if_fail (GTK_IS_ACTION (action));
1645
1646         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1647                 return;
1648
1649         modest_msg_edit_window_insert_image (window);
1650 }
1651
1652 void 
1653 modest_ui_actions_on_attach_file (GtkAction *action,
1654                                   ModestMsgEditWindow *window)
1655 {
1656         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1657         g_return_if_fail (GTK_IS_ACTION (action));
1658
1659         modest_msg_edit_window_attach_file (window);
1660 }
1661
1662 void 
1663 modest_ui_actions_on_remove_attachments (GtkAction *action,
1664                                          ModestMsgEditWindow *window)
1665 {
1666         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1667         g_return_if_fail (GTK_IS_ACTION (action));
1668
1669         modest_msg_edit_window_remove_attachments (window, NULL);
1670 }
1671
1672 /*
1673  * Shows a dialog with an entry that asks for some text. The returned
1674  * value must be freed by the caller. The dialog window title will be
1675  * set to @title.
1676  */
1677 static gchar *
1678 ask_for_folder_name (GtkWindow *parent_window,
1679                      const gchar *title)
1680 {
1681         GtkWidget *dialog, *entry;
1682         gchar *folder_name = NULL;
1683
1684         /* Ask for folder name */
1685         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1686                                               parent_window,
1687                                               GTK_DIALOG_MODAL,
1688                                               GTK_STOCK_CANCEL,
1689                                               GTK_RESPONSE_REJECT,
1690                                               GTK_STOCK_OK,
1691                                               GTK_RESPONSE_ACCEPT,
1692                                               NULL);
1693         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1694                             gtk_label_new(title),
1695                             FALSE, FALSE, 0);
1696                 
1697         entry = gtk_entry_new_with_max_length (40);
1698         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1699                             entry,
1700                             TRUE, FALSE, 0);    
1701         
1702         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1703         
1704         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
1705                 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1706
1707         gtk_widget_destroy (dialog);
1708
1709         return folder_name;
1710 }
1711
1712 void 
1713 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1714 {
1715         TnyFolderStore *parent_folder;
1716         GtkWidget *folder_view;
1717         
1718         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1719
1720         folder_view = modest_main_window_get_child_widget (main_window,
1721                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1722         if (!folder_view)
1723                 return;
1724
1725         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1726         
1727         if (parent_folder) {
1728                 gboolean finished = FALSE;
1729                 gint result;
1730                 gchar *folder_name = NULL, *suggested_name = NULL;
1731
1732                 /* Run the new folder dialog */
1733                 while (!finished) {
1734                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (main_window),
1735                                                                         parent_folder,
1736                                                                         suggested_name,
1737                                                                         &folder_name);
1738
1739                         if (result == GTK_RESPONSE_REJECT) {
1740                                 finished = TRUE;
1741                         } else {
1742                                 ModestMailOperation *mail_op;
1743                                 TnyFolder *new_folder = NULL;
1744
1745                                 mail_op  = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, 
1746                                                                       G_OBJECT(main_window));
1747                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
1748                                                                  mail_op);
1749                                 new_folder = modest_mail_operation_create_folder (mail_op,
1750                                                                                   parent_folder,
1751                                                                                   (const gchar *) folder_name);
1752                                 if (new_folder) {
1753                                         g_object_unref (new_folder);
1754                                         finished = TRUE;
1755                                 }
1756                                 g_object_unref (mail_op);
1757                         }
1758                         g_free (folder_name);
1759                         folder_name = NULL;
1760                 }
1761
1762                 g_object_unref (parent_folder);
1763         }
1764 }
1765
1766 void 
1767 modest_ui_actions_on_rename_folder (GtkAction *action,
1768                                      ModestMainWindow *main_window)
1769 {
1770         TnyFolderStore *folder;
1771         GtkWidget *folder_view;
1772         GtkWidget *header_view; 
1773
1774         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1775
1776         folder_view = modest_main_window_get_child_widget (main_window,
1777                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1778         if (!folder_view)
1779                 return;
1780
1781         header_view = modest_main_window_get_child_widget (main_window,
1782                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1783         
1784         if (!header_view)
1785                 return;
1786
1787         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1788         
1789         if (folder && TNY_IS_FOLDER (folder)) {
1790                 gchar *folder_name;
1791                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1792                                                    _("Please enter a new name for the folder"));
1793
1794                 if (folder_name != NULL && strlen (folder_name) > 0) {
1795                         ModestMailOperation *mail_op;
1796
1797                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(main_window));
1798                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1799                                                          mail_op);
1800
1801                         modest_header_view_set_folder (MODEST_HEADER_VIEW (header_view), NULL);
1802
1803                         modest_mail_operation_rename_folder (mail_op,
1804                                                              TNY_FOLDER (folder),
1805                                                              (const gchar *) folder_name);
1806
1807                         g_object_unref (mail_op);
1808                         g_free (folder_name);
1809                 }
1810                 g_object_unref (folder);
1811         }
1812 }
1813
1814 static void
1815 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
1816                                                gpointer user_data)
1817 {
1818         GObject *win = modest_mail_operation_get_source (mail_op);
1819
1820         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
1821                                                 _("mail_in_ui_folder_delete_error"));
1822 }
1823
1824 static void
1825 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
1826 {
1827         TnyFolderStore *folder;
1828         GtkWidget *folder_view;
1829         gint response;
1830         gchar *message;
1831         
1832         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1833
1834         folder_view = modest_main_window_get_child_widget (main_window,
1835                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1836         if (!folder_view)
1837                 return;
1838
1839         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1840
1841         /* Show an error if it's an account */
1842         if (!TNY_IS_FOLDER (folder)) {
1843                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
1844                                                         _("mail_in_ui_folder_delete_error"));
1845                 return ;
1846         }
1847
1848         /* Ask the user */      
1849         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
1850                                     tny_folder_get_name (TNY_FOLDER (folder)));
1851         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window), 
1852                                                             (const gchar *) message);
1853         g_free (message);
1854
1855         if (response == GTK_RESPONSE_OK) {
1856                 ModestMailOperation *mail_op = 
1857                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
1858                                                                        G_OBJECT(main_window),
1859                                                                        modest_ui_actions_delete_folder_error_handler,
1860                                                                        NULL);
1861
1862                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1863                                                  mail_op);
1864                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
1865                 g_object_unref (G_OBJECT (mail_op));
1866         }
1867
1868         g_object_unref (G_OBJECT (folder));
1869 }
1870
1871 void 
1872 modest_ui_actions_on_delete_folder (GtkAction *action,
1873                                      ModestMainWindow *main_window)
1874 {
1875         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1876
1877         delete_folder (main_window, FALSE);
1878 }
1879
1880 void 
1881 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1882 {
1883         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1884         
1885         delete_folder (main_window, TRUE);
1886 }
1887
1888 void
1889 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
1890                                          const gchar* server_account_name,
1891                                          gchar **username,
1892                                          gchar **password, 
1893                                          gboolean *cancel, 
1894                                          gboolean *remember,
1895                                          ModestMainWindow *main_window)
1896 {
1897         g_return_if_fail(server_account_name);
1898         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
1899         
1900         /* Initalize output parameters: */
1901         if (cancel)
1902                 *cancel = FALSE;
1903                 
1904         if (remember)
1905                 *remember = TRUE;
1906                 
1907 #ifdef MODEST_PLATFORM_MAEMO
1908         /* Maemo uses a different (awkward) button order,
1909          * It should probably just use gtk_alternative_dialog_button_order ().
1910          */
1911         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
1912                                               NULL,
1913                                               GTK_DIALOG_MODAL,
1914                                               GTK_STOCK_OK,
1915                                               GTK_RESPONSE_ACCEPT,
1916                                               GTK_STOCK_CANCEL,
1917                                               GTK_RESPONSE_REJECT,
1918                                               NULL);
1919 #else
1920         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
1921                                               NULL,
1922                                               GTK_DIALOG_MODAL,
1923                                               GTK_STOCK_CANCEL,
1924                                               GTK_RESPONSE_REJECT,
1925                                               GTK_STOCK_OK,
1926                                               GTK_RESPONSE_ACCEPT,
1927                                               NULL);
1928 #endif /* MODEST_PLATFORM_MAEMO */
1929
1930         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1931         
1932         gchar *server_name = modest_server_account_get_hostname (
1933                 modest_runtime_get_account_mgr(), server_account_name);
1934         
1935         /* This causes a warning because the logical ID has no %s in it, 
1936          * though the translation does, but there is not much we can do about that: */
1937         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
1938         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1939                             FALSE, FALSE, 0);
1940         g_free (txt);
1941         g_free (server_name);
1942         server_name = NULL;
1943
1944         /* username: */
1945         gchar *initial_username = modest_server_account_get_username (
1946                 modest_runtime_get_account_mgr(), server_account_name);
1947         
1948         GtkWidget *entry_username = gtk_entry_new ();
1949         if (initial_username)
1950                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
1951         /* Dim this if a connection has ever succeeded with this username,
1952          * as per the UI spec: */
1953         const gboolean username_known = 
1954                 modest_server_account_get_username_has_succeeded(
1955                         modest_runtime_get_account_mgr(), server_account_name);
1956         gtk_widget_set_sensitive (entry_username, !username_known);
1957         
1958 #ifdef MODEST_PLATFORM_MAEMO
1959         /* Auto-capitalization is the default, so let's turn it off: */
1960         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
1961         
1962         /* Create a size group to be used by all captions.
1963          * Note that HildonCaption does not create a default size group if we do not specify one.
1964          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
1965         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
1966         
1967         GtkWidget *caption = hildon_caption_new (sizegroup, 
1968                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
1969         gtk_widget_show (entry_username);
1970         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
1971                 FALSE, FALSE, MODEST_MARGIN_HALF);
1972         gtk_widget_show (caption);
1973 #else 
1974         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
1975                             TRUE, FALSE, 0);
1976 #endif /* MODEST_PLATFORM_MAEMO */      
1977                             
1978         /* password: */
1979         GtkWidget *entry_password = gtk_entry_new ();
1980         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
1981         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
1982         
1983 #ifdef MODEST_PLATFORM_MAEMO
1984         /* Auto-capitalization is the default, so let's turn it off: */
1985         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
1986                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
1987         
1988         caption = hildon_caption_new (sizegroup, 
1989                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
1990         gtk_widget_show (entry_password);
1991         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
1992                 FALSE, FALSE, MODEST_MARGIN_HALF);
1993         gtk_widget_show (caption);
1994         g_object_unref (sizegroup);
1995 #else 
1996         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
1997                             TRUE, FALSE, 0);
1998 #endif /* MODEST_PLATFORM_MAEMO */      
1999                                 
2000 /* This is not in the Maemo UI spec:
2001         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2002         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2003                             TRUE, FALSE, 0);
2004 */
2005
2006         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2007         
2008         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2009                 if (username) {
2010                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2011                         
2012                         modest_server_account_set_username (
2013                                  modest_runtime_get_account_mgr(), server_account_name, 
2014                                  *username);
2015                                  
2016                         const gboolean username_was_changed = 
2017                                 (strcmp (*username, initial_username) != 0);
2018                         if (username_was_changed) {
2019                                 /* To actually use a changed username, 
2020                                  * we must reset the connection, according to pvanhoof.
2021                                  * This _might_ be a sensible way to do that: */
2022                                  TnyDevice *device = modest_runtime_get_device();
2023                                  tny_device_force_offline (device);
2024                                  tny_device_force_online (device);
2025                         }
2026                 }
2027                         
2028                 if (password) {
2029                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2030                         
2031                         /* We do not save the password in the configuration, 
2032                          * because this function is only called for passwords that should 
2033                          * not be remembered:
2034                         modest_server_account_set_password (
2035                                  modest_runtime_get_account_mgr(), server_account_name, 
2036                                  *password);
2037                         */
2038                 }
2039                 
2040                 if (cancel)
2041                         *cancel   = FALSE;
2042                         
2043         } else {
2044                 if (username)
2045                         *username = NULL;
2046                         
2047                 if (password)
2048                         *password = NULL;
2049                         
2050                 if (cancel)
2051                         *cancel   = TRUE;
2052         }
2053
2054 /* This is not in the Maemo UI spec:
2055         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2056                 *remember = TRUE;
2057         else
2058                 *remember = FALSE;
2059 */
2060
2061         gtk_widget_destroy (dialog);
2062         
2063         printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel);
2064 }
2065
2066 void
2067 modest_ui_actions_on_cut (GtkAction *action,
2068                           ModestWindow *window)
2069 {
2070         GtkWidget *focused_widget;
2071
2072         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2073         if (GTK_IS_EDITABLE (focused_widget)) {
2074                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2075         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2076                 GtkTextBuffer *buffer;
2077                 GtkClipboard *clipboard;
2078
2079                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2080                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2081                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2082         }
2083 }
2084
2085 void
2086 modest_ui_actions_on_copy (GtkAction *action,
2087                            ModestWindow *window)
2088 {
2089         GtkClipboard *clipboard;
2090         GtkWidget *focused_widget;
2091
2092         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2093         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2094         if (GTK_IS_LABEL (focused_widget)) {
2095                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2096         } else if (GTK_IS_EDITABLE (focused_widget)) {
2097                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2098         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2099                 GtkTextBuffer *buffer;
2100
2101                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2102                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2103         }
2104 }
2105
2106 void
2107 modest_ui_actions_on_undo (GtkAction *action,
2108                            ModestWindow *window)
2109 {
2110         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2111                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2112         } else {
2113                 g_return_if_reached ();
2114         }
2115 }
2116
2117 void
2118 modest_ui_actions_on_paste (GtkAction *action,
2119                             ModestWindow *window)
2120 {
2121         GtkWidget *focused_widget;
2122
2123         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2124         if (GTK_IS_EDITABLE (focused_widget)) {
2125                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
2126         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2127                 GtkTextBuffer *buffer;
2128                 GtkClipboard *clipboard;
2129
2130                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2131                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2132                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
2133         }
2134 }
2135
2136 void
2137 modest_ui_actions_on_select_all (GtkAction *action,
2138                                  ModestWindow *window)
2139 {
2140         GtkWidget *focused_widget;
2141
2142         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2143         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
2144                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
2145         } else if (GTK_IS_LABEL (focused_widget)) {
2146                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
2147         } else if (GTK_IS_EDITABLE (focused_widget)) {
2148                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
2149         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2150                 GtkTextBuffer *buffer;
2151                 GtkTextIter start, end;
2152
2153                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2154                 gtk_text_buffer_get_start_iter (buffer, &start);
2155                 gtk_text_buffer_get_end_iter (buffer, &end);
2156                 gtk_text_buffer_select_range (buffer, &start, &end);
2157         }
2158         else if ((MODEST_IS_FOLDER_VIEW (focused_widget)) ||
2159                  (MODEST_IS_HEADER_VIEW (focused_widget))) {
2160                 
2161                 GtkTreeSelection *selection = NULL;
2162
2163                 /* Get header view */           
2164                 GtkWidget *header_view = focused_widget;
2165                 if (MODEST_IS_FOLDER_VIEW (focused_widget))
2166                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
2167                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2168
2169                 /* Select all messages */
2170                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
2171                 gtk_tree_selection_select_all (selection);
2172         }
2173 }
2174
2175 void
2176 modest_ui_actions_on_mark_as_read (GtkAction *action,
2177                                    ModestWindow *window)
2178 {       
2179         g_return_if_fail (MODEST_IS_WINDOW(window));
2180                 
2181         /* Mark each header as read */
2182         do_headers_action (window, headers_action_mark_as_read, NULL);
2183 }
2184
2185 void
2186 modest_ui_actions_on_mark_as_unread (GtkAction *action,
2187                                      ModestWindow *window)
2188 {       
2189         g_return_if_fail (MODEST_IS_WINDOW(window));
2190                 
2191         /* Mark each header as read */
2192         do_headers_action (window, headers_action_mark_as_unread, NULL);
2193 }
2194
2195 void
2196 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
2197                                   GtkRadioAction *selected,
2198                                   ModestWindow *window)
2199 {
2200         gint value;
2201
2202         value = gtk_radio_action_get_current_value (selected);
2203         if (MODEST_IS_WINDOW (window)) {
2204                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
2205         }
2206 }
2207
2208 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
2209                                                         GtkRadioAction *selected,
2210                                                         ModestWindow *window)
2211 {
2212         TnyHeaderFlags flags;
2213         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2214
2215         flags = gtk_radio_action_get_current_value (selected);
2216         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
2217 }
2218
2219 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
2220                                                            GtkRadioAction *selected,
2221                                                            ModestWindow *window)
2222 {
2223         gint file_format;
2224
2225         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2226
2227         file_format = gtk_radio_action_get_current_value (selected);
2228         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
2229 }
2230
2231
2232 void     
2233 modest_ui_actions_on_zoom_plus (GtkAction *action,
2234                                 ModestWindow *window)
2235 {
2236         g_return_if_fail (MODEST_IS_WINDOW (window));
2237
2238         modest_window_zoom_plus (MODEST_WINDOW (window));
2239 }
2240
2241 void     
2242 modest_ui_actions_on_zoom_minus (GtkAction *action,
2243                                  ModestWindow *window)
2244 {
2245         g_return_if_fail (MODEST_IS_WINDOW (window));
2246
2247         modest_window_zoom_minus (MODEST_WINDOW (window));
2248 }
2249
2250 void     
2251 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
2252                                            ModestWindow *window)
2253 {
2254         ModestWindowMgr *mgr;
2255         gboolean fullscreen, active;
2256         g_return_if_fail (MODEST_IS_WINDOW (window));
2257
2258         mgr = modest_runtime_get_window_mgr ();
2259
2260         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
2261         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2262
2263         if (active != fullscreen) {
2264                 modest_window_mgr_set_fullscreen_mode (mgr, active);
2265                 gtk_window_present (GTK_WINDOW (window));
2266         }
2267 }
2268
2269 void
2270 modest_ui_actions_on_change_fullscreen (GtkAction *action,
2271                                         ModestWindow *window)
2272 {
2273         ModestWindowMgr *mgr;
2274         gboolean fullscreen;
2275
2276         g_return_if_fail (MODEST_IS_WINDOW (window));
2277
2278         mgr = modest_runtime_get_window_mgr ();
2279         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2280         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
2281
2282         gtk_window_present (GTK_WINDOW (window));
2283 }
2284
2285 /* 
2286  * Used by modest_ui_actions_on_details to call do_headers_action 
2287  */
2288 static void
2289 headers_action_show_details (TnyHeader *header, 
2290                              ModestWindow *window,
2291                              gpointer user_data)
2292
2293 {
2294         GtkWidget *dialog;
2295         
2296         /* Create dialog */
2297         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
2298
2299         /* Run dialog */
2300         gtk_widget_show_all (dialog);
2301         gtk_dialog_run (GTK_DIALOG (dialog));
2302
2303         gtk_widget_destroy (dialog);
2304 }
2305
2306 /*
2307  * Show the folder details in a ModestDetailsDialog widget
2308  */
2309 static void
2310 show_folder_details (TnyFolder *folder, 
2311                      GtkWindow *window)
2312 {
2313         GtkWidget *dialog;
2314         
2315         /* Create dialog */
2316         dialog = modest_details_dialog_new_with_folder (window, folder);
2317
2318         /* Run dialog */
2319         gtk_widget_show_all (dialog);
2320         gtk_dialog_run (GTK_DIALOG (dialog));
2321
2322         gtk_widget_destroy (dialog);
2323 }
2324
2325 /*
2326  * Show the header details in a ModestDetailsDialog widget
2327  */
2328 void     
2329 modest_ui_actions_on_details (GtkAction *action, 
2330                               ModestWindow *win)
2331 {
2332         TnyList * headers_list;
2333         TnyIterator *iter;
2334         TnyHeader *header;              
2335
2336         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
2337                 TnyMsg *msg;
2338
2339                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
2340                 if (!msg)
2341                         return;
2342                 g_object_unref (msg);           
2343
2344                 headers_list = get_selected_headers (win);
2345                 if (!headers_list)
2346                         return;
2347
2348                 iter = tny_list_create_iterator (headers_list);
2349
2350                 header = TNY_HEADER (tny_iterator_get_current (iter));
2351                 headers_action_show_details (header, win, NULL);
2352                 g_object_unref (header);
2353
2354                 g_object_unref (iter);
2355                 g_object_unref (headers_list);
2356
2357         } else if (MODEST_IS_MAIN_WINDOW (win)) {
2358                 GtkWidget *folder_view, *header_view;
2359
2360                 /* Check which widget has the focus */
2361                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2362                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
2363                 if (gtk_widget_is_focus (folder_view)) {
2364                         TnyFolder *folder;
2365
2366                         folder = (TnyFolder *) modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2367
2368                         /* Show only when it's a folder */
2369                         if (!folder || !TNY_IS_FOLDER (folder))
2370                                 return;
2371
2372                         show_folder_details (folder, GTK_WINDOW (win));
2373
2374                 } else {
2375                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2376                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2377                         /* Show details of each header */
2378                         do_headers_action (win, headers_action_show_details, header_view);
2379                 }
2380         }
2381 }
2382
2383 void     
2384 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
2385                                      ModestMsgEditWindow *window)
2386 {
2387         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2388
2389         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
2390 }
2391
2392 void     
2393 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
2394                                       ModestMsgEditWindow *window)
2395 {
2396         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2397
2398         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
2399 }
2400
2401 void
2402 modest_ui_actions_toggle_folders_view (GtkAction *action, 
2403                                        ModestMainWindow *main_window)
2404 {
2405         ModestConf *conf;
2406         
2407         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2408
2409         conf = modest_runtime_get_conf ();
2410         
2411         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
2412                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
2413         else
2414                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
2415 }
2416
2417 void 
2418 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
2419                                      ModestWindow *window)
2420 {
2421         gboolean active, fullscreen = FALSE;
2422         ModestWindowMgr *mgr;
2423
2424         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
2425
2426         /* Check if we want to toggle the toolbar vuew in fullscreen
2427            or normal mode */
2428         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
2429                      "ViewShowToolbarFullScreen")) {
2430                 fullscreen = TRUE;
2431         }
2432
2433         /* Toggle toolbar */
2434         mgr = modest_runtime_get_window_mgr ();
2435         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
2436 }
2437
2438 void     
2439 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
2440                                            ModestMsgEditWindow *window)
2441 {
2442         modest_msg_edit_window_select_font (window);
2443 }
2444
2445 void
2446 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
2447                                                   const gchar *display_name,
2448                                                   GtkWindow *window)
2449 {
2450         /* Do not change the application name if the widget has not
2451            the focus. This callback could be called even if the folder
2452            view has not the focus, because the handled signal could be
2453            emitted when the folder view is redrawn */
2454         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
2455                 if (display_name)
2456                         gtk_window_set_title (window, display_name);
2457                 else
2458                         gtk_window_set_title (window, " ");
2459         }
2460 }
2461
2462 void
2463 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
2464 {
2465         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2466         modest_msg_edit_window_select_contacts (window);
2467 }
2468
2469 void
2470 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
2471 {
2472         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2473         modest_msg_edit_window_check_names (window);
2474 }
2475
2476
2477 static GtkWidget*
2478 create_move_to_dialog (ModestWindow *win,
2479                        GtkWidget *folder_view,
2480                        GtkWidget **tree_view)
2481 {
2482         GtkWidget *dialog, *scroll;
2483
2484         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2485                                               GTK_WINDOW (win),
2486                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
2487                                               GTK_STOCK_OK,
2488                                               GTK_RESPONSE_ACCEPT,
2489                                               GTK_STOCK_CANCEL,
2490                                               GTK_RESPONSE_REJECT,
2491                                               NULL);
2492
2493         /* Create scrolled window */
2494         scroll = gtk_scrolled_window_new (NULL, NULL);
2495         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
2496                                          GTK_POLICY_AUTOMATIC,
2497                                          GTK_POLICY_AUTOMATIC);
2498
2499         /* Create folder view */
2500         *tree_view = modest_folder_view_new (NULL);
2501         gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
2502                                  gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
2503         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
2504
2505         /* Add scroll to dialog */
2506         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
2507                             scroll, FALSE, FALSE, 0);
2508
2509         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2510
2511         return dialog;
2512 }
2513
2514 /*
2515  * Returns TRUE if at least one of the headers of the list belongs to
2516  * a message that has been fully retrieved.
2517  */
2518 static gboolean
2519 has_retrieved_msgs (TnyList *list)
2520 {
2521         TnyIterator *iter;
2522         gboolean found = FALSE;
2523
2524         iter = tny_list_create_iterator (list);
2525         while (tny_iterator_is_done (iter) && !found) {
2526                 TnyHeader *header;
2527                 TnyHeaderFlags flags;
2528
2529                 header = TNY_HEADER (tny_iterator_get_current (iter));
2530                 flags = tny_header_get_flags (header);
2531                 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
2532                         found = TRUE;
2533
2534                 if (!found)
2535                         tny_iterator_next (iter);
2536         }
2537         g_object_unref (iter);
2538
2539         return found;
2540 }
2541
2542 /*
2543  * Shows a confirmation dialog to the user when we're moving messages
2544  * from a remote server to the local storage. Returns the dialog
2545  * response. If it's other kind of movement the it always returns
2546  * GTK_RESPONSE_OK
2547  */
2548 static gint
2549 msgs_move_to_confirmation (GtkWindow *win,
2550                            TnyFolder *dest_folder,
2551                            TnyList *headers)
2552 {
2553         gint response = GTK_RESPONSE_OK;
2554
2555         /* If the destination is a local folder */
2556         if (modest_tny_folder_is_local_folder (dest_folder)) {
2557                 TnyFolder *src_folder;
2558                 TnyIterator *iter;
2559                 TnyHeader *header;
2560
2561                 /* Get source folder */
2562                 iter = tny_list_create_iterator (headers);
2563                 header = TNY_HEADER (tny_iterator_get_current (iter));
2564                 src_folder = tny_header_get_folder (header);
2565                 g_object_unref (header);
2566                 g_object_unref (iter);
2567
2568                 /* If the source is a remote folder */
2569                 if (!modest_tny_folder_is_local_folder (src_folder)) {
2570                         const gchar *message;
2571                         
2572                         if (tny_list_get_length (headers) == 1)
2573                                 if (has_retrieved_msgs (headers))
2574                                         message = _("mcen_nc_move_retrieve");
2575                                 else
2576                                         message = _("mcen_nc_move_header");
2577                         else
2578                                 if (has_retrieved_msgs (headers))
2579                                         message = _("mcen_nc_move_retrieves");
2580                                 else
2581                                         message = _("mcen_nc_move_headers");
2582                         
2583                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
2584                                                                             (const gchar *) message);
2585                 }
2586                 g_object_unref (src_folder);
2587         }
2588         return response;
2589 }
2590
2591
2592 static void
2593 tranasfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
2594 {
2595         ModestMsgViewWindow *self = NULL;
2596         gboolean found = FALSE;
2597
2598         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
2599         self = MODEST_MSG_VIEW_WINDOW (object);
2600
2601         found = modest_msg_view_window_select_first_message (self);
2602         g_return_if_fail (found);
2603 }
2604
2605 void
2606 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
2607                                              gpointer user_data)
2608 {
2609         GObject *win = modest_mail_operation_get_source (mail_op);
2610
2611         /* TODO: show error message */
2612         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2613                                                 _("mail_in_ui_folder_move_target_error"));
2614 }
2615
2616 /*
2617  * UI handler for the "Move to" action when invoked from the
2618  * ModestMainWindow
2619  */
2620 static void 
2621 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
2622                                           ModestMainWindow *win)
2623 {
2624         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
2625         GtkWidget *header_view = NULL;
2626         gint result;
2627         TnyFolderStore *folder_store = NULL;
2628         ModestMailOperation *mail_op = NULL;
2629
2630         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
2631
2632         /* Get the folder view */
2633         folder_view = modest_main_window_get_child_widget (win,
2634                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2635
2636         /* Get header view */
2637         header_view = modest_main_window_get_child_widget (win,
2638                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2639
2640         /* Create and run the dialog */
2641         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);
2642         result = gtk_dialog_run (GTK_DIALOG(dialog));
2643         g_object_ref (tree_view);
2644
2645         /* We do this to save an indentation level ;-) */
2646         if (result != GTK_RESPONSE_ACCEPT)
2647                 goto end;
2648
2649         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2650
2651         if (TNY_IS_ACCOUNT (folder_store))
2652                 goto end;
2653
2654         /* Get folder or messages to transfer */
2655         if (gtk_widget_is_focus (folder_view)) {
2656                 TnyFolderStore *src_folder;
2657                 src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2658
2659                 /* Clean folder on header view before moving it */
2660                 modest_header_view_set_folder (MODEST_HEADER_VIEW (header_view), NULL); 
2661
2662                 if (TNY_IS_FOLDER (src_folder)) {
2663                         mail_op = 
2664                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
2665                                                                                G_OBJECT(win),
2666                                                                                modest_ui_actions_move_folder_error_handler,
2667                                                                                NULL);
2668                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
2669
2670                         modest_mail_operation_xfer_folder (mail_op, 
2671                                                            TNY_FOLDER (src_folder),
2672                                                            folder_store,
2673                                                            TRUE);
2674                         /* Unref mail operation */
2675                         g_object_unref (G_OBJECT (mail_op));
2676                 }
2677
2678                 /* Frees */
2679                 g_object_unref (G_OBJECT (src_folder));
2680         } else {
2681                 if (gtk_widget_is_focus (header_view)) {
2682                         TnyList *headers;
2683                         gint response;
2684
2685                         headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
2686
2687                         /* Ask for user confirmation */
2688                         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2689                                                               TNY_FOLDER (folder_store), 
2690                                                               headers);
2691
2692                         /* Transfer messages */
2693                         if (response == GTK_RESPONSE_OK) {
2694                                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
2695                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2696                                                                  mail_op);
2697
2698                                 modest_mail_operation_xfer_msgs (mail_op, 
2699                                                                  headers,
2700                                                                  TNY_FOLDER (folder_store),
2701                                                                  TRUE,
2702                                                                  NULL,
2703                                                                  NULL);
2704
2705                                 g_object_unref (G_OBJECT (mail_op));
2706                         }
2707                         g_object_unref (headers);
2708                 }
2709         }
2710         g_object_unref (folder_store);
2711  end:
2712         gtk_widget_destroy (dialog);
2713 }
2714
2715
2716 /*
2717  * UI handler for the "Move to" action when invoked from the
2718  * ModestMsgViewWindow
2719  */
2720 static void 
2721 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
2722                                               ModestMsgViewWindow *win)
2723 {
2724         GtkWidget *dialog, *folder_view, *tree_view = NULL;
2725         gint result;
2726         ModestMainWindow *main_window;
2727         TnyHeader *header;
2728         TnyList *headers;
2729
2730         /* Get the folder view */
2731         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2732         folder_view = modest_main_window_get_child_widget (main_window,
2733                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2734
2735         /* Create and run the dialog */
2736         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);  
2737         result = gtk_dialog_run (GTK_DIALOG(dialog));
2738         g_object_ref (tree_view);
2739
2740         if (result == GTK_RESPONSE_ACCEPT) {
2741                 TnyFolderStore *folder_store;
2742                 gint response;
2743
2744                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2745
2746                 /* Create header list */
2747                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
2748                 headers = tny_simple_list_new ();
2749                 tny_list_prepend (headers, G_OBJECT (header));
2750                 g_object_unref (header);
2751
2752                 /* Ask user for confirmation. MSG-NOT404 */
2753                 response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2754                                                       TNY_FOLDER (folder_store), 
2755                                                       headers);
2756
2757                 /* Transfer current msg */
2758                 if (response == GTK_RESPONSE_OK) {
2759                         ModestMailOperation *mail_op;
2760
2761                         /* Create mail op */
2762                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
2763                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2764                                                          mail_op);
2765                         
2766                         /* Transfer messages */
2767                         modest_mail_operation_xfer_msgs (mail_op, 
2768                                                          headers,
2769                                                          TNY_FOLDER (folder_store),
2770                                                          TRUE,
2771                                                          tranasfer_msgs_from_viewer_cb,
2772                                                          NULL);
2773                         g_object_unref (G_OBJECT (mail_op));
2774                 } 
2775                 g_object_unref (headers);
2776                 g_object_unref (folder_store);
2777         }
2778         gtk_widget_destroy (dialog);
2779 }
2780
2781 void 
2782 modest_ui_actions_on_move_to (GtkAction *action, 
2783                               ModestWindow *win)
2784 {
2785         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
2786                           MODEST_IS_MSG_VIEW_WINDOW (win));
2787
2788         if (MODEST_IS_MAIN_WINDOW (win)) 
2789                 modest_ui_actions_on_main_window_move_to (action, 
2790                                                           MODEST_MAIN_WINDOW (win));
2791         else
2792                 modest_ui_actions_on_msg_view_window_move_to (action, 
2793                                                               MODEST_MSG_VIEW_WINDOW (win));
2794 }
2795
2796 /*
2797  * Calls #HeadersFunc for each header already selected in the main
2798  * window or the message currently being shown in the msg view window
2799  */
2800 static void
2801 do_headers_action (ModestWindow *win, 
2802                    HeadersFunc func,
2803                    gpointer user_data)
2804 {
2805         TnyList *headers_list;
2806         TnyIterator *iter;
2807
2808         /* Get headers */
2809         headers_list = get_selected_headers (win);
2810         if (!headers_list)
2811                 return;
2812
2813         /* Call the function for each header */
2814         iter = tny_list_create_iterator (headers_list);
2815         while (!tny_iterator_is_done (iter)) {
2816                 TnyHeader *header;
2817
2818                 header = TNY_HEADER (tny_iterator_get_current (iter));
2819                 func (header, win, user_data);
2820                 g_object_unref (header);
2821                 tny_iterator_next (iter);
2822         }
2823         g_object_unref (iter);
2824         g_object_unref (headers_list);
2825 }
2826
2827 void 
2828 modest_ui_actions_view_attachment (GtkAction *action,
2829                                    ModestWindow *window)
2830 {
2831         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2832                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
2833         } else {
2834                 /* not supported window for this action */
2835                 g_return_if_reached ();
2836         }
2837 }
2838
2839 void
2840 modest_ui_actions_save_attachments (GtkAction *action,
2841                                     ModestWindow *window)
2842 {
2843         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2844                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
2845         } else {
2846                 /* not supported window for this action */
2847                 g_return_if_reached ();
2848         }
2849 }
2850
2851 void
2852 modest_ui_actions_remove_attachments (GtkAction *action,
2853                                       ModestWindow *window)
2854 {
2855         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2856                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
2857         } else {
2858                 /* not supported window for this action */
2859                 g_return_if_reached ();
2860         }
2861 }
2862
2863 void 
2864 modest_ui_actions_on_settings (GtkAction *action, 
2865                                ModestWindow *win)
2866 {
2867         GtkWidget *dialog;
2868
2869         dialog = modest_platform_get_global_settings_dialog ();
2870         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
2871         gtk_widget_show (dialog);
2872
2873         gtk_dialog_run (GTK_DIALOG (dialog));
2874
2875         gtk_widget_destroy (dialog);
2876 }
2877
2878 void 
2879 modest_ui_actions_on_help (GtkAction *action, 
2880                            ModestWindow *win)
2881 {
2882         const gchar *help_id = NULL;
2883
2884         if (MODEST_IS_MAIN_WINDOW (win)) {
2885                 const gchar *action_name;
2886                 action_name = gtk_action_get_name (action);
2887
2888                 if (!strcmp (action_name, "FolderViewCSMHelp") ||
2889                     !strcmp (action_name, "HeaderViewCSMHelp")) {
2890                         GtkWidget *folder_view;
2891                         TnyFolderStore *folder_store;
2892                         /* Get selected folder */
2893                         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2894                                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2895                         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2896
2897                         /* Switch help_id */
2898                         if (TNY_IS_FOLDER (folder_store)) {
2899                                 switch (tny_folder_get_folder_type (TNY_FOLDER (folder_store))) {
2900                                 case TNY_FOLDER_TYPE_NORMAL:
2901                                         help_id = "applications_email_userfolder";
2902                                         break;
2903                                 case TNY_FOLDER_TYPE_INBOX:
2904                                         help_id = "applications_email_inbox";
2905                                         break;
2906                                 case TNY_FOLDER_TYPE_OUTBOX:
2907                                         help_id = "applications_email_outbox";
2908                                         break;
2909                                 case TNY_FOLDER_TYPE_SENT:
2910                                         help_id = "applications_email_sent";
2911                                         break;
2912                                 case TNY_FOLDER_TYPE_DRAFTS:
2913                                         help_id = "applications_email_drafts";
2914                                         break;
2915                                 case TNY_FOLDER_TYPE_ARCHIVE:
2916                                         help_id = "applications_email_archive";
2917                                         break;
2918                                 default:
2919                                         help_id = NULL;
2920                                 }
2921                         }
2922                 } else {
2923                         help_id = "applications_email_mainview";        
2924                 }
2925         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
2926                 help_id = "applications_email_viewer";
2927         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
2928                 help_id = "applications_email_editor";
2929
2930         modest_platform_show_help (GTK_WINDOW (win), help_id);
2931 }
2932
2933 void 
2934 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
2935                                             ModestWindow *window)
2936 {
2937         ModestMailOperation *mail_op;
2938         TnyList *headers;
2939
2940         /* Get headers */
2941         headers = get_selected_headers (window);
2942         if (!headers)
2943                 return;
2944
2945         /* Create mail operation */
2946         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
2947                                                                  G_OBJECT (window),
2948                                                                  modest_ui_actions_get_msgs_full_error_handler, 
2949                                                                  NULL);
2950         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
2951         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
2952
2953         /* Frees */
2954         g_object_unref (headers);
2955         g_object_unref (mail_op);
2956 }
2957
2958 void
2959 modest_ui_actions_on_email_menu_activated (GtkAction *action,
2960                                           ModestWindow *window)
2961 {
2962         g_return_if_fail (MODEST_IS_WINDOW (window));
2963
2964         /* Update dimmed */     
2965         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
2966 }
2967
2968 void
2969 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
2970                                           ModestWindow *window)
2971 {
2972         g_return_if_fail (MODEST_IS_WINDOW (window));
2973
2974         /* Update dimmed */     
2975         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
2976 }
2977
2978 void
2979 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
2980                                                  ModestWindow *window)
2981 {
2982         g_return_if_fail (MODEST_IS_WINDOW (window));
2983
2984         /* Update dimmed */     
2985         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
2986 }
2987
2988 void
2989 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
2990                                                      ModestWindow *window)
2991 {
2992         g_return_if_fail (MODEST_IS_WINDOW (window));
2993
2994         /* Update dimmed */     
2995         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
2996 }
2997
2998 void
2999 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
3000                                                      ModestWindow *window)
3001 {
3002         g_return_if_fail (MODEST_IS_WINDOW (window));
3003
3004         /* Update dimmed */     
3005         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3006 }
3007
3008 void
3009 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
3010 {
3011         g_return_if_fail (MODEST_IS_WINDOW (window));
3012
3013         /* Update dimmed */     
3014         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
3015 }