* src/modest-ui-actions.c:
[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         TnyAccount *account = NULL;
742         ModestWindowMgr *mgr;
743         gchar *signature = NULL;
744                         
745         g_return_if_fail (user_data != NULL);
746         rf_helper = (ReplyForwardHelper *) user_data;
747
748         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
749                                                    rf_helper->account_name);
750         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
751                                          rf_helper->account_name,
752                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
753                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
754                                                            rf_helper->account_name,
755                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
756         }
757
758         /* Create reply mail */
759         switch (rf_helper->action) {
760         case ACTION_REPLY:
761                 new_msg = 
762                         modest_tny_msg_create_reply_msg (msg,  from, signature,
763                                                          rf_helper->reply_forward_type,
764                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
765                 break;
766         case ACTION_REPLY_TO_ALL:
767                 new_msg = 
768                         modest_tny_msg_create_reply_msg (msg, from, signature, rf_helper->reply_forward_type,
769                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
770                 edit_type = MODEST_EDIT_TYPE_REPLY;
771                 break;
772         case ACTION_FORWARD:
773                 new_msg = 
774                         modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
775                 edit_type = MODEST_EDIT_TYPE_FORWARD;
776                 break;
777         default:
778                 g_return_if_reached ();
779                 return;
780         }
781
782         g_free (signature);
783
784         if (!new_msg) {
785                 g_printerr ("modest: failed to create message\n");
786                 goto cleanup;
787         }
788
789         account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
790                                                                        rf_helper->account_name,
791                                                                        TNY_ACCOUNT_TYPE_STORE);
792         if (!account) {
793                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
794                 goto cleanup;
795         }
796
797         /* Create and register the windows */
798         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
799         mgr = modest_runtime_get_window_mgr ();
800         modest_window_mgr_register_window (mgr, msg_win);
801
802         if (rf_helper->parent_window != NULL) {
803                 gdouble parent_zoom;
804
805                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
806                 modest_window_set_zoom (msg_win, parent_zoom);
807         }
808
809         /* Show edit window */
810         gtk_widget_show_all (GTK_WIDGET (msg_win));
811
812 cleanup:
813         if (new_msg)
814                 g_object_unref (G_OBJECT (new_msg));
815         if (account)
816                 g_object_unref (G_OBJECT (account));
817         g_object_unref (msg);
818         g_object_unref (header);
819 }
820
821 /*
822  * Checks a list of headers. If any of them are not currently
823  * downloaded (CACHED) then it asks the user for permission to
824  * download them.
825  *
826  * Returns FALSE if the user does not want to download the
827  * messages. Returns TRUE if the user allowed the download or if all
828  * of them are currently downloaded
829  */
830 static gboolean
831 download_uncached_messages (TnyList *header_list, GtkWindow *win)
832 {
833         TnyIterator *iter;
834         gboolean found, retval;
835
836         iter = tny_list_create_iterator (header_list);
837         found = FALSE;
838         while (!tny_iterator_is_done (iter) && !found) {
839                 TnyHeader *header;
840                 TnyHeaderFlags flags;
841
842                 header = TNY_HEADER (tny_iterator_get_current (iter));
843                 flags = tny_header_get_flags (header);
844                 /* TODO: is this the right flag?, it seems that some
845                    headers that have been previously downloaded do not
846                    come with it */
847                 found = !(flags & TNY_HEADER_FLAG_CACHED);
848                 g_object_unref (header);
849                 tny_iterator_next (iter);
850         }
851         g_object_unref (iter);
852
853         /* Ask for user permission to download the messages */
854         retval = TRUE;
855         if (found) {
856                 GtkResponseType response;
857                 response = 
858                         modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
859                                                                  _("mcen_nc_get_multi_msg_txt"));
860                 if (response == GTK_RESPONSE_CANCEL)
861                         retval = FALSE;
862         }
863         return retval;
864 }
865
866
867 /*
868  * Common code for the reply and forward actions
869  */
870 static void
871 reply_forward (ReplyForwardAction action, ModestWindow *win)
872 {
873         ModestMailOperation *mail_op = NULL;
874         TnyList *header_list = NULL;
875         ReplyForwardHelper *rf_helper = NULL;
876         guint reply_forward_type;
877         gboolean continue_download;
878         
879         g_return_if_fail (MODEST_IS_WINDOW(win));
880
881         header_list = get_selected_headers (win);
882         if (!header_list)
883                 return;
884
885         /* Check that the messages have been previously downloaded */
886         continue_download = download_uncached_messages (header_list, GTK_WINDOW (win));
887         if (!continue_download) {
888                 g_object_unref (header_list);
889                 return;
890         }
891         
892         reply_forward_type = 
893                 modest_conf_get_int (modest_runtime_get_conf (),
894                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
895                                      NULL);
896         /* We assume that we can only select messages of the
897            same folder and that we reply all of them from the
898            same account. In fact the interface currently only
899            allows single selection */
900         
901         /* Fill helpers */
902         rf_helper = g_slice_new0 (ReplyForwardHelper);
903         rf_helper->reply_forward_type = reply_forward_type;
904         rf_helper->action = action;
905         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
906         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
907                 rf_helper->parent_window = GTK_WIDGET (win);
908         if (!rf_helper->account_name)
909                 rf_helper->account_name =
910                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
911
912         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
913                 TnyMsg *msg;
914                 TnyHeader *header;
915                 /* Get header and message. Do not free them here, the
916                    reply_forward_cb must do it */
917                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
918                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
919                 if (!msg || !header) {
920                         if (msg)
921                                 g_object_unref (msg);
922                         if (header)
923                                 g_object_unref (header);
924                         g_printerr ("modest: no message found\n");
925                         return;
926                 } else
927                         reply_forward_cb (NULL, header, msg, rf_helper);
928         } else {
929                 /* Retrieve messages */
930                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
931                                                                          G_OBJECT(win),
932                                                                          modest_ui_actions_get_msgs_full_error_handler, 
933                                                                          NULL);
934                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
935                 modest_mail_operation_get_msgs_full (mail_op, 
936                                                      header_list, 
937                                                      reply_forward_cb, 
938                                                      rf_helper, 
939                                                      free_reply_forward_helper);
940
941                 /* Clean */
942                 g_object_unref(mail_op);
943         }
944
945         /* Free */
946         g_object_unref (header_list);
947 }
948
949 void
950 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
951 {
952         g_return_if_fail (MODEST_IS_WINDOW(win));
953
954         reply_forward (ACTION_REPLY, win);
955 }
956
957 void
958 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
959 {
960         g_return_if_fail (MODEST_IS_WINDOW(win));
961
962         reply_forward (ACTION_FORWARD, win);
963 }
964
965 void
966 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
967 {
968         g_return_if_fail (MODEST_IS_WINDOW(win));
969
970         reply_forward (ACTION_REPLY_TO_ALL, win);
971 }
972
973 void 
974 modest_ui_actions_on_next (GtkAction *action, 
975                            ModestWindow *window)
976 {
977         if (MODEST_IS_MAIN_WINDOW (window)) {
978                 GtkWidget *header_view;
979
980                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
981                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
982                 if (!header_view)
983                         return;
984         
985                 modest_header_view_select_next (MODEST_HEADER_VIEW(header_view)); 
986         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
987                 modest_msg_view_window_select_next_message (MODEST_MSG_VIEW_WINDOW (window));
988         } else {
989                 g_return_if_reached ();
990         }
991 }
992
993 void 
994 modest_ui_actions_on_prev (GtkAction *action, 
995                            ModestWindow *window)
996 {
997         g_return_if_fail (MODEST_IS_WINDOW(window));
998
999         if (MODEST_IS_MAIN_WINDOW (window)) {
1000                 GtkWidget *header_view;
1001                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1002                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1003                 if (!header_view)
1004                         return;
1005                 
1006                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1007         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1008                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1009         } else {
1010                 g_return_if_reached ();
1011         }
1012 }
1013
1014 void 
1015 modest_ui_actions_on_sort (GtkAction *action, 
1016                            ModestWindow *window)
1017 {
1018         g_return_if_fail (MODEST_IS_WINDOW(window));
1019
1020         if (MODEST_IS_MAIN_WINDOW (window)) {
1021                 GtkWidget *header_view;
1022                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1023                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1024                 if (!header_view)
1025                         return;
1026
1027                 /* Show sorting dialog */
1028                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1029         }
1030 }
1031
1032 /*
1033  * This function performs the send & receive required actions. The
1034  * window is used to create the mail operation. Typically it should
1035  * always be the main window, but we pass it as argument in order to
1036  * be more flexible.
1037  */
1038 void
1039 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
1040 {
1041         gchar *acc_name = NULL;
1042         ModestMailOperation *mail_op;
1043
1044         /* If no account name was provided then get the current account, and if
1045            there is no current account then pick the default one: */
1046         if (!account_name) {
1047                 acc_name = g_strdup (modest_window_get_active_account(win));
1048                 if (!acc_name)
1049                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1050                 if (!acc_name) {
1051                         g_printerr ("modest: cannot get default account\n");
1052                         return;
1053                 }
1054         } else {
1055                 acc_name = g_strdup (account_name);
1056         }
1057
1058         /* Send & receive. */
1059         /* TODO: The spec wants us to first do any pending deletions, before receiving. */
1060         /* Receive and then send. The operation is tagged initially as
1061            a receive operation because the account update performs a
1062            receive and then a send. The operation changes its type
1063            internally, so the progress objects will receive the proper
1064            progress information */
1065         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
1066         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1067         modest_mail_operation_update_account (mail_op, acc_name);
1068         g_object_unref (G_OBJECT (mail_op));
1069         
1070         /* Free */
1071         g_free (acc_name);
1072 }
1073
1074 /*
1075  * Refreshes all accounts. This function will be used by automatic
1076  * updates
1077  */
1078 void
1079 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1080 {
1081         GSList *account_names, *iter;
1082
1083         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1084                                                           TRUE);
1085
1086         iter = account_names;
1087         while (iter) {                  
1088                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1089                 iter = g_slist_next (iter);
1090         }
1091         
1092         g_slist_foreach (account_names, (GFunc) g_free, NULL);
1093         g_slist_free (account_names);
1094 }
1095
1096 /*
1097  * Handler of the click on Send&Receive button in the main toolbar
1098  */
1099 void
1100 modest_ui_actions_on_send_receive (GtkAction *action,  ModestWindow *win)
1101 {
1102         /* Check that at least one account exists: */
1103         GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
1104                                 TRUE /* enabled accounts only */);
1105         gboolean accounts_exist = account_names != NULL;
1106         g_slist_free (account_names);
1107         
1108         /* If not, allow the user to create an account before trying to send/receive. */
1109         if (!accounts_exist)
1110                 modest_ui_actions_on_accounts (NULL, win);
1111         
1112         /* Refresh the active account */
1113         modest_ui_actions_do_send_receive (NULL, win);
1114 }
1115
1116
1117 void
1118 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1119 {
1120         ModestConf *conf;
1121         GtkWidget *header_view;
1122         
1123         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1124
1125         header_view = modest_main_window_get_child_widget (main_window,
1126                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1127         if (!header_view)
1128                 return;
1129
1130         conf = modest_runtime_get_conf ();
1131         
1132         /* what is saved/restored is depending on the style; thus; we save with
1133          * old style, then update the style, and restore for this new style
1134          */
1135         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1136         
1137         if (modest_header_view_get_style
1138             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1139                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1140                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1141         else
1142                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1143                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1144
1145         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1146                                       MODEST_CONF_HEADER_VIEW_KEY);
1147 }
1148
1149
1150 void 
1151 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1152                                       TnyHeader *header,
1153                                       ModestMainWindow *main_window)
1154 {
1155         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1156
1157         /* If no header has been selected then exit */
1158         if (!header)
1159                 return;
1160
1161         /* Update Main window title */
1162         if (GTK_WIDGET_HAS_FOCUS (header_view)) {
1163                 const gchar *subject = tny_header_get_subject (header);
1164                 if (subject && strcmp (subject, ""))
1165                         gtk_window_set_title (GTK_WINDOW (main_window), subject);
1166                 else
1167                         gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
1168         }
1169
1170         /* Update toolbar dimming state */
1171         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1172 }
1173
1174 void
1175 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1176                                        TnyHeader *header,
1177                                        ModestMainWindow *main_window)
1178 {
1179         TnyList *headers;
1180
1181         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1182         
1183         if (!header)
1184                 return;
1185
1186         headers = tny_simple_list_new ();
1187         tny_list_prepend (headers, G_OBJECT (header));
1188
1189         _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1190
1191         g_object_unref (headers);
1192 }
1193
1194 static void
1195 set_active_account_from_tny_account (TnyAccount *account,
1196                                      ModestWindow *window)
1197 {
1198         const gchar *server_acc_name = tny_account_get_id (account);
1199         
1200         /* We need the TnyAccount provided by the
1201            account store because that is the one that
1202            knows the name of the Modest account */
1203         TnyAccount *modest_server_account = modest_server_account = 
1204                 modest_tny_account_store_get_tny_account_by_id  (modest_runtime_get_account_store (), 
1205                                                                  server_acc_name);
1206         
1207         const gchar *modest_acc_name = 
1208                 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1209         modest_window_set_active_account (window, modest_acc_name);
1210         g_object_unref (modest_server_account);
1211 }
1212
1213 void 
1214 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1215                                                TnyFolderStore *folder_store, 
1216                                                gboolean selected,
1217                                                ModestMainWindow *main_window)
1218 {
1219         ModestConf *conf;
1220         GtkWidget *header_view;
1221         
1222         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1223
1224         header_view = modest_main_window_get_child_widget(main_window,
1225                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
1226         if (!header_view)
1227                 return;
1228         
1229         conf = modest_runtime_get_conf ();
1230
1231         if (TNY_IS_ACCOUNT (folder_store)) {
1232                 /* Update active account */
1233                 set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1234                 /* Show account details */
1235                 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1236         } else if (modest_tny_folder_store_is_virtual_local_folders  (folder_store )) {
1237                 //TODO: Set the virtual folder store as the "active account" somehow:
1238                 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1239         } else {
1240                 if (TNY_IS_FOLDER (folder_store) && selected) {
1241                         
1242                         if (!TNY_IS_MERGE_FOLDER (folder_store)) { /* TnyMergeFolder can have no get_account() implementation. */
1243                                 /* Update the active account */
1244                                 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder_store));
1245                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1246                                 g_object_unref (account);
1247                         }
1248                         
1249                         /* Set folder on header view */
1250                         modest_main_window_set_contents_style (main_window, 
1251                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1252                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1253                                                        TNY_FOLDER (folder_store));
1254                         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1255                                                       MODEST_CONF_HEADER_VIEW_KEY);
1256                 } else {
1257                         /* Update the active account */
1258                         modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
1259                         /* Do not show folder */
1260                         modest_widget_memory_save (conf, G_OBJECT (header_view), MODEST_CONF_HEADER_VIEW_KEY);
1261                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
1262                 }
1263         }
1264
1265         /* Update toolbar dimming state */
1266         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1267 }
1268
1269 void 
1270 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1271                                      ModestWindow *win)
1272 {
1273         GtkWidget *dialog;
1274         gchar *txt, *item;
1275         gboolean online;
1276
1277         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1278         
1279         if (g_main_depth > 0)   
1280                 gdk_threads_enter ();
1281         online = tny_device_is_online (modest_runtime_get_device());
1282
1283         if (online) {
1284                 /* already online -- the item is simply not there... */
1285                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1286                                                  GTK_DIALOG_MODAL,
1287                                                  GTK_MESSAGE_WARNING,
1288                                                  GTK_BUTTONS_OK,
1289                                                  _("The %s you selected cannot be found"),
1290                                                  item);
1291                 gtk_dialog_run (GTK_DIALOG(dialog));
1292         } else {
1293                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1294                                                       GTK_WINDOW (win),
1295                                                       GTK_DIALOG_MODAL,
1296                                                       GTK_STOCK_CANCEL,
1297                                                       GTK_RESPONSE_REJECT,
1298                                                       GTK_STOCK_OK,
1299                                                       GTK_RESPONSE_ACCEPT,
1300                                                       NULL);
1301                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1302                                          "Do you want to get online?"), item);
1303                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1304                                     gtk_label_new (txt), FALSE, FALSE, 0);
1305                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1306                 g_free (txt);
1307
1308                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1309                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1310 //                      modest_platform_connect_and_wait ();;
1311                 }
1312         }
1313         gtk_widget_destroy (dialog);
1314         if (g_main_depth > 0)   
1315                 gdk_threads_leave ();
1316 }
1317
1318 void
1319 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1320                                      ModestWindow *win)
1321 {
1322         /* g_message ("%s %s", __FUNCTION__, link); */
1323 }       
1324
1325
1326 void
1327 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1328                                         ModestWindow *win)
1329 {
1330         modest_platform_activate_uri (link);
1331 }
1332
1333 void
1334 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1335                                           ModestWindow *win)
1336 {
1337         modest_platform_show_uri_popup (link);
1338 }
1339
1340 void
1341 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1342                                              ModestWindow *win)
1343 {
1344         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
1345 }
1346
1347 void
1348 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1349                                           const gchar *address,
1350                                           ModestWindow *win)
1351 {
1352         /* g_message ("%s %s", __FUNCTION__, address); */
1353 }
1354
1355 void
1356 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1357 {
1358         TnyTransportAccount *transport_account;
1359         ModestMailOperation *mail_operation;
1360         MsgData *data;
1361         gchar *account_name, *from;
1362         ModestAccountMgr *account_mgr;
1363
1364         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1365         
1366         data = modest_msg_edit_window_get_msg_data (edit_window);
1367
1368         account_mgr = modest_runtime_get_account_mgr();
1369         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1370         if (!account_name) 
1371                 account_name = modest_account_mgr_get_default_account (account_mgr);
1372         if (!account_name) {
1373                 g_printerr ("modest: no account found\n");
1374                 modest_msg_edit_window_free_msg_data (edit_window, data);
1375                 return;
1376         }
1377
1378         if (!strcmp (account_name, MODEST_ACTUAL_LOCAL_FOLDERS_ACCOUNT_ID)) {
1379                 account_name = g_strdup (data->account_name);
1380         }
1381
1382         transport_account =
1383                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
1384                                       (modest_runtime_get_account_store(),
1385                                        account_name,
1386                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1387         if (!transport_account) {
1388                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1389                 g_free (account_name);
1390                 modest_msg_edit_window_free_msg_data (edit_window, data);
1391                 return;
1392         }
1393         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1394
1395         /* Create the mail operation */         
1396         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
1397         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1398
1399         modest_mail_operation_save_to_drafts (mail_operation,
1400                                               transport_account,
1401                                               data->draft_msg,
1402                                               from,
1403                                               data->to, 
1404                                               data->cc, 
1405                                               data->bcc,
1406                                               data->subject, 
1407                                               data->plain_body, 
1408                                               data->html_body,
1409                                               data->attachments,
1410                                               data->priority_flags);
1411         /* Frees */
1412         g_free (from);
1413         g_free (account_name);
1414         g_object_unref (G_OBJECT (transport_account));
1415         g_object_unref (G_OBJECT (mail_operation));
1416
1417         modest_msg_edit_window_free_msg_data (edit_window, data);
1418
1419         /* Save settings and close the window */
1420         gtk_widget_destroy (GTK_WIDGET (edit_window));
1421 }
1422
1423 /* For instance, when clicking the Send toolbar button when editing a message: */
1424 void
1425 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1426 {
1427         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1428
1429         if (!modest_msg_edit_window_check_names (edit_window))
1430                 return;
1431         
1432         /* FIXME: Code added just for testing. The final version will
1433            use the send queue provided by tinymail and some
1434            classifier */
1435         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
1436         gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1437         if (!account_name) 
1438                 account_name = modest_account_mgr_get_default_account (account_mgr);
1439                 
1440         if (!account_name) {
1441                 g_printerr ("modest: no account found\n");
1442                 return;
1443         }
1444         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
1445
1446         if (!strcmp (account_name, MODEST_ACTUAL_LOCAL_FOLDERS_ACCOUNT_ID)) {
1447                 account_name = g_strdup (data->account_name);
1448         }
1449         
1450         /* Get the currently-active transport account for this modest account: */
1451         TnyTransportAccount *transport_account =
1452                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
1453                                       (modest_runtime_get_account_store(),
1454                                        account_name));
1455         if (!transport_account) {
1456                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1457                 g_free (account_name);
1458                 modest_msg_edit_window_free_msg_data (edit_window, data);
1459                 return;
1460         }
1461         
1462         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
1463
1464         /* mail content checks and dialogs */
1465         if (data->subject == NULL || data->subject[0] == '\0') {
1466                 GtkResponseType response;
1467                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1468                                                                     _("mcen_nc_subject_is_empty_send"));
1469                 if (response == GTK_RESPONSE_CANCEL) {
1470                         g_free (account_name);
1471                         return;
1472                 }
1473         }
1474
1475         if (data->plain_body == NULL || data->plain_body[0] == '\0') {
1476                 GtkResponseType response;
1477                 gchar *note_message;
1478                 gchar *note_subject = data->subject;
1479                 if (note_subject == NULL || note_subject[0] == '\0')
1480                         note_subject = _("mail_va_no_subject");
1481                 note_message = g_strdup_printf (_("emev_ni_ui_smtp_message_null"), note_subject);
1482                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1483                                                                     note_message);
1484                 g_free (note_message);
1485                 if (response == GTK_RESPONSE_CANCEL) {
1486                         g_free (account_name);
1487                         return;
1488                 }
1489         }
1490
1491         /* Create the mail operation */
1492         ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
1493         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1494
1495         modest_mail_operation_send_new_mail (mail_operation,
1496                                              transport_account,
1497                                              data->draft_msg,
1498                                              from,
1499                                              data->to, 
1500                                              data->cc, 
1501                                              data->bcc,
1502                                              data->subject, 
1503                                              data->plain_body, 
1504                                              data->html_body,
1505                                              data->attachments,
1506                                              data->priority_flags);
1507                                              
1508         /* Free data: */
1509         g_free (from);
1510         g_free (account_name);
1511         g_object_unref (G_OBJECT (transport_account));
1512         g_object_unref (G_OBJECT (mail_operation));
1513
1514         modest_msg_edit_window_free_msg_data (edit_window, data);
1515
1516         /* Save settings and close the window: */
1517         gtk_widget_destroy (GTK_WIDGET (edit_window));
1518 }
1519
1520 void 
1521 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1522                                   ModestMsgEditWindow *window)
1523 {
1524         ModestMsgEditFormatState *format_state = NULL;
1525
1526         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1527         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1528
1529         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1530                 return;
1531
1532         format_state = modest_msg_edit_window_get_format_state (window);
1533         g_return_if_fail (format_state != NULL);
1534
1535         format_state->bold = gtk_toggle_action_get_active (action);
1536         modest_msg_edit_window_set_format_state (window, format_state);
1537         g_free (format_state);
1538         
1539 }
1540
1541 void 
1542 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1543                                      ModestMsgEditWindow *window)
1544 {
1545         ModestMsgEditFormatState *format_state = NULL;
1546
1547         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1548         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1549
1550         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1551                 return;
1552
1553         format_state = modest_msg_edit_window_get_format_state (window);
1554         g_return_if_fail (format_state != NULL);
1555
1556         format_state->italics = gtk_toggle_action_get_active (action);
1557         modest_msg_edit_window_set_format_state (window, format_state);
1558         g_free (format_state);
1559         
1560 }
1561
1562 void 
1563 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
1564                                      ModestMsgEditWindow *window)
1565 {
1566         ModestMsgEditFormatState *format_state = NULL;
1567
1568         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1569         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1570
1571         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1572                 return;
1573
1574         format_state = modest_msg_edit_window_get_format_state (window);
1575         g_return_if_fail (format_state != NULL);
1576
1577         format_state->bullet = gtk_toggle_action_get_active (action);
1578         modest_msg_edit_window_set_format_state (window, format_state);
1579         g_free (format_state);
1580         
1581 }
1582
1583 void 
1584 modest_ui_actions_on_change_justify (GtkRadioAction *action,
1585                                      GtkRadioAction *selected,
1586                                      ModestMsgEditWindow *window)
1587 {
1588         ModestMsgEditFormatState *format_state = NULL;
1589         GtkJustification value;
1590
1591         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1592
1593         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1594                 return;
1595
1596         value = gtk_radio_action_get_current_value (selected);
1597
1598         format_state = modest_msg_edit_window_get_format_state (window);
1599         g_return_if_fail (format_state != NULL);
1600
1601         format_state->justification = value;
1602         modest_msg_edit_window_set_format_state (window, format_state);
1603         g_free (format_state);
1604 }
1605
1606 void 
1607 modest_ui_actions_on_select_editor_color (GtkAction *action,
1608                                           ModestMsgEditWindow *window)
1609 {
1610         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1611         g_return_if_fail (GTK_IS_ACTION (action));
1612
1613         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1614                 return;
1615
1616         modest_msg_edit_window_select_color (window);
1617 }
1618
1619 void 
1620 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
1621                                                      ModestMsgEditWindow *window)
1622 {
1623         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1624         g_return_if_fail (GTK_IS_ACTION (action));
1625
1626         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1627                 return;
1628
1629         modest_msg_edit_window_select_background_color (window);
1630 }
1631
1632 void 
1633 modest_ui_actions_on_insert_image (GtkAction *action,
1634                                    ModestMsgEditWindow *window)
1635 {
1636         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1637         g_return_if_fail (GTK_IS_ACTION (action));
1638
1639         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1640                 return;
1641
1642         modest_msg_edit_window_insert_image (window);
1643 }
1644
1645 void 
1646 modest_ui_actions_on_attach_file (GtkAction *action,
1647                                   ModestMsgEditWindow *window)
1648 {
1649         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1650         g_return_if_fail (GTK_IS_ACTION (action));
1651
1652         modest_msg_edit_window_attach_file (window);
1653 }
1654
1655 void 
1656 modest_ui_actions_on_remove_attachments (GtkAction *action,
1657                                          ModestMsgEditWindow *window)
1658 {
1659         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1660         g_return_if_fail (GTK_IS_ACTION (action));
1661
1662         modest_msg_edit_window_remove_attachments (window, NULL);
1663 }
1664
1665 /*
1666  * Shows a dialog with an entry that asks for some text. The returned
1667  * value must be freed by the caller. The dialog window title will be
1668  * set to @title.
1669  */
1670 static gchar *
1671 ask_for_folder_name (GtkWindow *parent_window,
1672                      const gchar *title)
1673 {
1674         GtkWidget *dialog, *entry;
1675         gchar *folder_name = NULL;
1676
1677         /* Ask for folder name */
1678         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1679                                               parent_window,
1680                                               GTK_DIALOG_MODAL,
1681                                               GTK_STOCK_CANCEL,
1682                                               GTK_RESPONSE_REJECT,
1683                                               GTK_STOCK_OK,
1684                                               GTK_RESPONSE_ACCEPT,
1685                                               NULL);
1686         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1687                             gtk_label_new(title),
1688                             FALSE, FALSE, 0);
1689                 
1690         entry = gtk_entry_new_with_max_length (40);
1691         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1692                             entry,
1693                             TRUE, FALSE, 0);    
1694         
1695         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1696         
1697         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
1698                 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1699
1700         gtk_widget_destroy (dialog);
1701
1702         return folder_name;
1703 }
1704
1705 void 
1706 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1707 {
1708         TnyFolderStore *parent_folder;
1709         GtkWidget *folder_view;
1710         
1711         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1712
1713         folder_view = modest_main_window_get_child_widget (main_window,
1714                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1715         if (!folder_view)
1716                 return;
1717
1718         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1719         
1720         if (parent_folder) {
1721                 gboolean finished = FALSE;
1722                 gint result;
1723                 gchar *folder_name = NULL, *suggested_name = NULL;
1724
1725                 /* Run the new folder dialog */
1726                 while (!finished) {
1727                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (main_window),
1728                                                                         parent_folder,
1729                                                                         suggested_name,
1730                                                                         &folder_name);
1731
1732                         if (result == GTK_RESPONSE_REJECT) {
1733                                 finished = TRUE;
1734                         } else {
1735                                 ModestMailOperation *mail_op;
1736                                 TnyFolder *new_folder = NULL;
1737
1738                                 mail_op  = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, 
1739                                                                       G_OBJECT(main_window));
1740                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
1741                                                                  mail_op);
1742                                 new_folder = modest_mail_operation_create_folder (mail_op,
1743                                                                                   parent_folder,
1744                                                                                   (const gchar *) folder_name);
1745                                 if (new_folder) {
1746                                         g_object_unref (new_folder);
1747                                         finished = TRUE;
1748                                 }
1749                                 g_object_unref (mail_op);
1750                         }
1751                         g_free (folder_name);
1752                         folder_name = NULL;
1753                 }
1754
1755                 g_object_unref (parent_folder);
1756         }
1757 }
1758
1759 void 
1760 modest_ui_actions_on_rename_folder (GtkAction *action,
1761                                      ModestMainWindow *main_window)
1762 {
1763         TnyFolderStore *folder;
1764         GtkWidget *folder_view;
1765         GtkWidget *header_view; 
1766
1767         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1768
1769         folder_view = modest_main_window_get_child_widget (main_window,
1770                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1771         if (!folder_view)
1772                 return;
1773
1774         header_view = modest_main_window_get_child_widget (main_window,
1775                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1776         
1777         if (!header_view)
1778                 return;
1779
1780         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1781         
1782         if (folder && TNY_IS_FOLDER (folder)) {
1783                 gchar *folder_name;
1784                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1785                                                    _("Please enter a new name for the folder"));
1786
1787                 if (folder_name != NULL && strlen (folder_name) > 0) {
1788                         ModestMailOperation *mail_op;
1789
1790                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(main_window));
1791                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1792                                                          mail_op);
1793
1794                         modest_header_view_set_folder (MODEST_HEADER_VIEW (header_view), NULL);
1795
1796                         modest_mail_operation_rename_folder (mail_op,
1797                                                              TNY_FOLDER (folder),
1798                                                              (const gchar *) folder_name);
1799
1800                         g_object_unref (mail_op);
1801                         g_free (folder_name);
1802                 }
1803                 g_object_unref (folder);
1804         }
1805 }
1806
1807 static void
1808 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
1809                                                gpointer user_data)
1810 {
1811         GObject *win = modest_mail_operation_get_source (mail_op);
1812
1813         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
1814                                                 _("mail_in_ui_folder_delete_error"));
1815 }
1816
1817 static void
1818 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
1819 {
1820         TnyFolderStore *folder;
1821         GtkWidget *folder_view;
1822         gint response;
1823         gchar *message;
1824         
1825         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1826
1827         folder_view = modest_main_window_get_child_widget (main_window,
1828                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1829         if (!folder_view)
1830                 return;
1831
1832         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1833
1834         /* Show an error if it's an account */
1835         if (!TNY_IS_FOLDER (folder)) {
1836                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
1837                                                         _("mail_in_ui_folder_delete_error"));
1838                 return ;
1839         }
1840
1841         /* Ask the user */      
1842         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
1843                                     tny_folder_get_name (TNY_FOLDER (folder)));
1844         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window), 
1845                                                             (const gchar *) message);
1846         g_free (message);
1847
1848         if (response == GTK_RESPONSE_OK) {
1849                 ModestMailOperation *mail_op = 
1850                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
1851                                                                        G_OBJECT(main_window),
1852                                                                        modest_ui_actions_delete_folder_error_handler,
1853                                                                        NULL);
1854
1855                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1856                                                  mail_op);
1857                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
1858                 g_object_unref (G_OBJECT (mail_op));
1859         }
1860
1861         g_object_unref (G_OBJECT (folder));
1862 }
1863
1864 void 
1865 modest_ui_actions_on_delete_folder (GtkAction *action,
1866                                      ModestMainWindow *main_window)
1867 {
1868         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1869
1870         delete_folder (main_window, FALSE);
1871 }
1872
1873 void 
1874 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1875 {
1876         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1877         
1878         delete_folder (main_window, TRUE);
1879 }
1880
1881 void
1882 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
1883                                          const gchar* server_account_name,
1884                                          gchar **username,
1885                                          gchar **password, 
1886                                          gboolean *cancel, 
1887                                          gboolean *remember,
1888                                          ModestMainWindow *main_window)
1889 {
1890         g_return_if_fail(server_account_name);
1891         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
1892         
1893         /* Initalize output parameters: */
1894         if (cancel)
1895                 *cancel = FALSE;
1896                 
1897         if (remember)
1898                 *remember = TRUE;
1899                 
1900 #ifdef MODEST_PLATFORM_MAEMO
1901         /* Maemo uses a different (awkward) button order,
1902          * It should probably just use gtk_alternative_dialog_button_order ().
1903          */
1904         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
1905                                               NULL,
1906                                               GTK_DIALOG_MODAL,
1907                                               GTK_STOCK_OK,
1908                                               GTK_RESPONSE_ACCEPT,
1909                                               GTK_STOCK_CANCEL,
1910                                               GTK_RESPONSE_REJECT,
1911                                               NULL);
1912 #else
1913         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
1914                                               NULL,
1915                                               GTK_DIALOG_MODAL,
1916                                               GTK_STOCK_CANCEL,
1917                                               GTK_RESPONSE_REJECT,
1918                                               GTK_STOCK_OK,
1919                                               GTK_RESPONSE_ACCEPT,
1920                                               NULL);
1921 #endif /* MODEST_PLATFORM_MAEMO */
1922
1923         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1924         
1925         gchar *server_name = modest_server_account_get_hostname (
1926                 modest_runtime_get_account_mgr(), server_account_name);
1927         
1928         /* This causes a warning because the logical ID has no %s in it, 
1929          * though the translation does, but there is not much we can do about that: */
1930         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
1931         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1932                             FALSE, FALSE, 0);
1933         g_free (txt);
1934         g_free (server_name);
1935         server_name = NULL;
1936
1937         /* username: */
1938         gchar *initial_username = modest_server_account_get_username (
1939                 modest_runtime_get_account_mgr(), server_account_name);
1940         
1941         GtkWidget *entry_username = gtk_entry_new ();
1942         if (initial_username)
1943                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
1944         /* Dim this if a connection has ever succeeded with this username,
1945          * as per the UI spec: */
1946         const gboolean username_known = 
1947                 modest_server_account_get_username_has_succeeded(
1948                         modest_runtime_get_account_mgr(), server_account_name);
1949         gtk_widget_set_sensitive (entry_username, !username_known);
1950         
1951 #ifdef MODEST_PLATFORM_MAEMO
1952         /* Auto-capitalization is the default, so let's turn it off: */
1953         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
1954         
1955         /* Create a size group to be used by all captions.
1956          * Note that HildonCaption does not create a default size group if we do not specify one.
1957          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
1958         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
1959         
1960         GtkWidget *caption = hildon_caption_new (sizegroup, 
1961                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
1962         gtk_widget_show (entry_username);
1963         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
1964                 FALSE, FALSE, MODEST_MARGIN_HALF);
1965         gtk_widget_show (caption);
1966 #else 
1967         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
1968                             TRUE, FALSE, 0);
1969 #endif /* MODEST_PLATFORM_MAEMO */      
1970                             
1971         /* password: */
1972         GtkWidget *entry_password = gtk_entry_new ();
1973         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
1974         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
1975         
1976 #ifdef MODEST_PLATFORM_MAEMO
1977         /* Auto-capitalization is the default, so let's turn it off: */
1978         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
1979                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
1980         
1981         caption = hildon_caption_new (sizegroup, 
1982                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
1983         gtk_widget_show (entry_password);
1984         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
1985                 FALSE, FALSE, MODEST_MARGIN_HALF);
1986         gtk_widget_show (caption);
1987         g_object_unref (sizegroup);
1988 #else 
1989         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
1990                             TRUE, FALSE, 0);
1991 #endif /* MODEST_PLATFORM_MAEMO */      
1992                                 
1993 /* This is not in the Maemo UI spec:
1994         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1995         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1996                             TRUE, FALSE, 0);
1997 */
1998
1999         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2000         
2001         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2002                 if (username) {
2003                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2004                         
2005                         modest_server_account_set_username (
2006                                  modest_runtime_get_account_mgr(), server_account_name, 
2007                                  *username);
2008                                  
2009                         const gboolean username_was_changed = 
2010                                 (strcmp (*username, initial_username) != 0);
2011                         if (username_was_changed) {
2012                                 /* To actually use a changed username, 
2013                                  * we must reset the connection, according to pvanhoof.
2014                                  * This _might_ be a sensible way to do that: */
2015                                  TnyDevice *device = modest_runtime_get_device();
2016                                  tny_device_force_offline (device);
2017                                  tny_device_force_online (device);
2018                         }
2019                 }
2020                         
2021                 if (password) {
2022                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2023                         
2024                         /* We do not save the password in the configuration, 
2025                          * because this function is only called for passwords that should 
2026                          * not be remembered:
2027                         modest_server_account_set_password (
2028                                  modest_runtime_get_account_mgr(), server_account_name, 
2029                                  *password);
2030                         */
2031                 }
2032                 
2033                 if (cancel)
2034                         *cancel   = FALSE;
2035                         
2036         } else {
2037                 if (username)
2038                         *username = NULL;
2039                         
2040                 if (password)
2041                         *password = NULL;
2042                         
2043                 if (cancel)
2044                         *cancel   = TRUE;
2045         }
2046
2047 /* This is not in the Maemo UI spec:
2048         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2049                 *remember = TRUE;
2050         else
2051                 *remember = FALSE;
2052 */
2053
2054         gtk_widget_destroy (dialog);
2055         
2056         printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel);
2057 }
2058
2059 void
2060 modest_ui_actions_on_cut (GtkAction *action,
2061                           ModestWindow *window)
2062 {
2063         GtkWidget *focused_widget;
2064
2065         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2066         if (GTK_IS_EDITABLE (focused_widget)) {
2067                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2068         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2069                 GtkTextBuffer *buffer;
2070                 GtkClipboard *clipboard;
2071
2072                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2073                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2074                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2075         }
2076 }
2077
2078 void
2079 modest_ui_actions_on_copy (GtkAction *action,
2080                            ModestWindow *window)
2081 {
2082         GtkClipboard *clipboard;
2083         GtkWidget *focused_widget;
2084
2085         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2086         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2087         if (GTK_IS_LABEL (focused_widget)) {
2088                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2089         } else if (GTK_IS_EDITABLE (focused_widget)) {
2090                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2091         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2092                 GtkTextBuffer *buffer;
2093
2094                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2095                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2096         }
2097 }
2098
2099 void
2100 modest_ui_actions_on_undo (GtkAction *action,
2101                            ModestWindow *window)
2102 {
2103         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2104                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2105         } else {
2106                 g_return_if_reached ();
2107         }
2108 }
2109
2110 void
2111 modest_ui_actions_on_paste (GtkAction *action,
2112                             ModestWindow *window)
2113 {
2114         GtkWidget *focused_widget;
2115
2116         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2117         if (GTK_IS_EDITABLE (focused_widget)) {
2118                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
2119         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2120                 GtkTextBuffer *buffer;
2121                 GtkClipboard *clipboard;
2122
2123                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2124                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2125                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
2126         }
2127 }
2128
2129 void
2130 modest_ui_actions_on_select_all (GtkAction *action,
2131                                  ModestWindow *window)
2132 {
2133         GtkWidget *focused_widget;
2134
2135         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2136         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
2137                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
2138         } else if (GTK_IS_LABEL (focused_widget)) {
2139                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
2140         } else if (GTK_IS_EDITABLE (focused_widget)) {
2141                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
2142         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2143                 GtkTextBuffer *buffer;
2144                 GtkTextIter start, end;
2145
2146                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2147                 gtk_text_buffer_get_start_iter (buffer, &start);
2148                 gtk_text_buffer_get_end_iter (buffer, &end);
2149                 gtk_text_buffer_select_range (buffer, &start, &end);
2150         }
2151         else if ((MODEST_IS_FOLDER_VIEW (focused_widget)) ||
2152                  (MODEST_IS_HEADER_VIEW (focused_widget))) {
2153                 
2154                 GtkTreeSelection *selection = NULL;
2155
2156                 /* Get header view */           
2157                 GtkWidget *header_view = focused_widget;
2158                 if (MODEST_IS_FOLDER_VIEW (focused_widget))
2159                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
2160                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2161
2162                 /* Select all messages */
2163                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
2164                 gtk_tree_selection_select_all (selection);
2165         }
2166 }
2167
2168 void
2169 modest_ui_actions_on_mark_as_read (GtkAction *action,
2170                                    ModestWindow *window)
2171 {       
2172         g_return_if_fail (MODEST_IS_WINDOW(window));
2173                 
2174         /* Mark each header as read */
2175         do_headers_action (window, headers_action_mark_as_read, NULL);
2176 }
2177
2178 void
2179 modest_ui_actions_on_mark_as_unread (GtkAction *action,
2180                                      ModestWindow *window)
2181 {       
2182         g_return_if_fail (MODEST_IS_WINDOW(window));
2183                 
2184         /* Mark each header as read */
2185         do_headers_action (window, headers_action_mark_as_unread, NULL);
2186 }
2187
2188 void
2189 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
2190                                   GtkRadioAction *selected,
2191                                   ModestWindow *window)
2192 {
2193         gint value;
2194
2195         value = gtk_radio_action_get_current_value (selected);
2196         if (MODEST_IS_WINDOW (window)) {
2197                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
2198         }
2199 }
2200
2201 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
2202                                                         GtkRadioAction *selected,
2203                                                         ModestWindow *window)
2204 {
2205         TnyHeaderFlags flags;
2206         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2207
2208         flags = gtk_radio_action_get_current_value (selected);
2209         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
2210 }
2211
2212 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
2213                                                            GtkRadioAction *selected,
2214                                                            ModestWindow *window)
2215 {
2216         gint file_format;
2217
2218         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2219
2220         file_format = gtk_radio_action_get_current_value (selected);
2221         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
2222 }
2223
2224
2225 void     
2226 modest_ui_actions_on_zoom_plus (GtkAction *action,
2227                                 ModestWindow *window)
2228 {
2229         g_return_if_fail (MODEST_IS_WINDOW (window));
2230
2231         modest_window_zoom_plus (MODEST_WINDOW (window));
2232 }
2233
2234 void     
2235 modest_ui_actions_on_zoom_minus (GtkAction *action,
2236                                  ModestWindow *window)
2237 {
2238         g_return_if_fail (MODEST_IS_WINDOW (window));
2239
2240         modest_window_zoom_minus (MODEST_WINDOW (window));
2241 }
2242
2243 void     
2244 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
2245                                            ModestWindow *window)
2246 {
2247         ModestWindowMgr *mgr;
2248         gboolean fullscreen, active;
2249         g_return_if_fail (MODEST_IS_WINDOW (window));
2250
2251         mgr = modest_runtime_get_window_mgr ();
2252
2253         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
2254         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2255
2256         if (active != fullscreen) {
2257                 modest_window_mgr_set_fullscreen_mode (mgr, active);
2258                 gtk_window_present (GTK_WINDOW (window));
2259         }
2260 }
2261
2262 void
2263 modest_ui_actions_on_change_fullscreen (GtkAction *action,
2264                                         ModestWindow *window)
2265 {
2266         ModestWindowMgr *mgr;
2267         gboolean fullscreen;
2268
2269         g_return_if_fail (MODEST_IS_WINDOW (window));
2270
2271         mgr = modest_runtime_get_window_mgr ();
2272         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2273         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
2274
2275         gtk_window_present (GTK_WINDOW (window));
2276 }
2277
2278 /* 
2279  * Used by modest_ui_actions_on_details to call do_headers_action 
2280  */
2281 static void
2282 headers_action_show_details (TnyHeader *header, 
2283                              ModestWindow *window,
2284                              gpointer user_data)
2285
2286 {
2287         GtkWidget *dialog;
2288         
2289         /* Create dialog */
2290         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
2291
2292         /* Run dialog */
2293         gtk_widget_show_all (dialog);
2294         gtk_dialog_run (GTK_DIALOG (dialog));
2295
2296         gtk_widget_destroy (dialog);
2297 }
2298
2299 /*
2300  * Show the folder details in a ModestDetailsDialog widget
2301  */
2302 static void
2303 show_folder_details (TnyFolder *folder, 
2304                      GtkWindow *window)
2305 {
2306         GtkWidget *dialog;
2307         
2308         /* Create dialog */
2309         dialog = modest_details_dialog_new_with_folder (window, folder);
2310
2311         /* Run dialog */
2312         gtk_widget_show_all (dialog);
2313         gtk_dialog_run (GTK_DIALOG (dialog));
2314
2315         gtk_widget_destroy (dialog);
2316 }
2317
2318 /*
2319  * Show the header details in a ModestDetailsDialog widget
2320  */
2321 void     
2322 modest_ui_actions_on_details (GtkAction *action, 
2323                               ModestWindow *win)
2324 {
2325         TnyList * headers_list;
2326         TnyIterator *iter;
2327         TnyHeader *header;              
2328
2329         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
2330                 TnyMsg *msg;
2331
2332                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
2333                 if (!msg)
2334                         return;
2335                 g_object_unref (msg);           
2336
2337                 headers_list = get_selected_headers (win);
2338                 if (!headers_list)
2339                         return;
2340
2341                 iter = tny_list_create_iterator (headers_list);
2342
2343                 header = TNY_HEADER (tny_iterator_get_current (iter));
2344                 headers_action_show_details (header, win, NULL);
2345                 g_object_unref (header);
2346
2347                 g_object_unref (iter);
2348                 g_object_unref (headers_list);
2349
2350         } else if (MODEST_IS_MAIN_WINDOW (win)) {
2351                 GtkWidget *folder_view, *header_view;
2352
2353                 /* Check which widget has the focus */
2354                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2355                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
2356                 if (gtk_widget_is_focus (folder_view)) {
2357                         TnyFolder *folder;
2358
2359                         folder = (TnyFolder *) modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2360
2361                         /* Show only when it's a folder */
2362                         if (!folder || !TNY_IS_FOLDER (folder))
2363                                 return;
2364
2365                         show_folder_details (folder, GTK_WINDOW (win));
2366
2367                 } else {
2368                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2369                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2370                         /* Show details of each header */
2371                         do_headers_action (win, headers_action_show_details, header_view);
2372                 }
2373         }
2374 }
2375
2376 void     
2377 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
2378                                      ModestMsgEditWindow *window)
2379 {
2380         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2381
2382         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
2383 }
2384
2385 void     
2386 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
2387                                       ModestMsgEditWindow *window)
2388 {
2389         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2390
2391         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
2392 }
2393
2394 void
2395 modest_ui_actions_toggle_folders_view (GtkAction *action, 
2396                                        ModestMainWindow *main_window)
2397 {
2398         ModestConf *conf;
2399         
2400         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2401
2402         conf = modest_runtime_get_conf ();
2403         
2404         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
2405                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
2406         else
2407                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
2408 }
2409
2410 void 
2411 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
2412                                      ModestWindow *window)
2413 {
2414         gboolean active, fullscreen = FALSE;
2415         ModestWindowMgr *mgr;
2416
2417         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
2418
2419         /* Check if we want to toggle the toolbar vuew in fullscreen
2420            or normal mode */
2421         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
2422                      "ViewShowToolbarFullScreen")) {
2423                 fullscreen = TRUE;
2424         }
2425
2426         /* Toggle toolbar */
2427         mgr = modest_runtime_get_window_mgr ();
2428         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
2429 }
2430
2431 void     
2432 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
2433                                            ModestMsgEditWindow *window)
2434 {
2435         modest_msg_edit_window_select_font (window);
2436 }
2437
2438 void
2439 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
2440                                                   const gchar *display_name,
2441                                                   GtkWindow *window)
2442 {
2443         /* Do not change the application name if the widget has not
2444            the focus. This callback could be called even if the folder
2445            view has not the focus, because the handled signal could be
2446            emitted when the folder view is redrawn */
2447         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
2448                 if (display_name)
2449                         gtk_window_set_title (window, display_name);
2450                 else
2451                         gtk_window_set_title (window, " ");
2452         }
2453 }
2454
2455 void
2456 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
2457 {
2458         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2459         modest_msg_edit_window_select_contacts (window);
2460 }
2461
2462 void
2463 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
2464 {
2465         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2466         modest_msg_edit_window_check_names (window);
2467 }
2468
2469
2470 static GtkWidget*
2471 create_move_to_dialog (ModestWindow *win,
2472                        GtkWidget *folder_view,
2473                        GtkWidget **tree_view)
2474 {
2475         GtkWidget *dialog, *scroll;
2476
2477         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2478                                               GTK_WINDOW (win),
2479                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
2480                                               GTK_STOCK_OK,
2481                                               GTK_RESPONSE_ACCEPT,
2482                                               GTK_STOCK_CANCEL,
2483                                               GTK_RESPONSE_REJECT,
2484                                               NULL);
2485
2486         /* Create scrolled window */
2487         scroll = gtk_scrolled_window_new (NULL, NULL);
2488         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
2489                                          GTK_POLICY_AUTOMATIC,
2490                                          GTK_POLICY_AUTOMATIC);
2491
2492         /* Create folder view */
2493         *tree_view = modest_folder_view_new (NULL);
2494         gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
2495                                  gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
2496         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
2497
2498         /* Add scroll to dialog */
2499         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
2500                             scroll, FALSE, FALSE, 0);
2501
2502         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2503
2504         return dialog;
2505 }
2506
2507 /*
2508  * Returns TRUE if at least one of the headers of the list belongs to
2509  * a message that has been fully retrieved.
2510  */
2511 static gboolean
2512 has_retrieved_msgs (TnyList *list)
2513 {
2514         TnyIterator *iter;
2515         gboolean found = FALSE;
2516
2517         iter = tny_list_create_iterator (list);
2518         while (tny_iterator_is_done (iter) && !found) {
2519                 TnyHeader *header;
2520                 TnyHeaderFlags flags;
2521
2522                 header = TNY_HEADER (tny_iterator_get_current (iter));
2523                 flags = tny_header_get_flags (header);
2524                 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
2525                         found = TRUE;
2526
2527                 if (!found)
2528                         tny_iterator_next (iter);
2529         }
2530         g_object_unref (iter);
2531
2532         return found;
2533 }
2534
2535 /*
2536  * Shows a confirmation dialog to the user when we're moving messages
2537  * from a remote server to the local storage. Returns the dialog
2538  * response. If it's other kind of movement the it always returns
2539  * GTK_RESPONSE_OK
2540  */
2541 static gint
2542 msgs_move_to_confirmation (GtkWindow *win,
2543                            TnyFolder *dest_folder,
2544                            TnyList *headers)
2545 {
2546         gint response = GTK_RESPONSE_OK;
2547
2548         /* If the destination is a local folder */
2549         if (modest_tny_folder_is_local_folder (dest_folder)) {
2550                 TnyFolder *src_folder;
2551                 TnyIterator *iter;
2552                 TnyHeader *header;
2553
2554                 /* Get source folder */
2555                 iter = tny_list_create_iterator (headers);
2556                 header = TNY_HEADER (tny_iterator_get_current (iter));
2557                 src_folder = tny_header_get_folder (header);
2558                 g_object_unref (header);
2559                 g_object_unref (iter);
2560
2561                 /* If the source is a remote folder */
2562                 if (!modest_tny_folder_is_local_folder (src_folder)) {
2563                         const gchar *message;
2564                         
2565                         if (tny_list_get_length (headers) == 1)
2566                                 if (has_retrieved_msgs (headers))
2567                                         message = _("mcen_nc_move_retrieve");
2568                                 else
2569                                         message = _("mcen_nc_move_header");
2570                         else
2571                                 if (has_retrieved_msgs (headers))
2572                                         message = _("mcen_nc_move_retrieves");
2573                                 else
2574                                         message = _("mcen_nc_move_headers");
2575                         
2576                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
2577                                                                             (const gchar *) message);
2578                 }
2579                 g_object_unref (src_folder);
2580         }
2581         return response;
2582 }
2583
2584
2585 static void
2586 tranasfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
2587 {
2588         ModestMsgViewWindow *self = NULL;
2589         gboolean found = FALSE;
2590
2591         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
2592         self = MODEST_MSG_VIEW_WINDOW (object);
2593
2594         found = modest_msg_view_window_select_first_message (self);
2595         g_return_if_fail (found);
2596 }
2597
2598 void
2599 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
2600                                              gpointer user_data)
2601 {
2602         GObject *win = modest_mail_operation_get_source (mail_op);
2603
2604         /* TODO: show error message */
2605         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2606                                                 _("mail_in_ui_folder_move_target_error"));
2607 }
2608
2609 /*
2610  * UI handler for the "Move to" action when invoked from the
2611  * ModestMainWindow
2612  */
2613 static void 
2614 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
2615                                           ModestMainWindow *win)
2616 {
2617         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
2618         GtkWidget *header_view = NULL;
2619         gint result;
2620         TnyFolderStore *folder_store = NULL;
2621         ModestMailOperation *mail_op = NULL;
2622
2623         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
2624
2625         /* Get the folder view */
2626         folder_view = modest_main_window_get_child_widget (win,
2627                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2628
2629         /* Get header view */
2630         header_view = modest_main_window_get_child_widget (win,
2631                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2632
2633         /* Create and run the dialog */
2634         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);
2635         result = gtk_dialog_run (GTK_DIALOG(dialog));
2636         g_object_ref (tree_view);
2637
2638         /* We do this to save an indentation level ;-) */
2639         if (result != GTK_RESPONSE_ACCEPT)
2640                 goto end;
2641
2642         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2643
2644         if (TNY_IS_ACCOUNT (folder_store))
2645                 goto end;
2646
2647         /* Get folder or messages to transfer */
2648         if (gtk_widget_is_focus (folder_view)) {
2649                 TnyFolderStore *src_folder;
2650                 src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2651
2652                 /* Clean folder on header view before moving it */
2653                 modest_header_view_set_folder (MODEST_HEADER_VIEW (header_view), NULL); 
2654
2655                 if (TNY_IS_FOLDER (src_folder)) {
2656                         mail_op = 
2657                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
2658                                                                                G_OBJECT(win),
2659                                                                                modest_ui_actions_move_folder_error_handler,
2660                                                                                NULL);
2661                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
2662
2663                         modest_mail_operation_xfer_folder (mail_op, 
2664                                                            TNY_FOLDER (src_folder),
2665                                                            folder_store,
2666                                                            TRUE);
2667                         /* Unref mail operation */
2668                         g_object_unref (G_OBJECT (mail_op));
2669                 }
2670
2671                 /* Frees */
2672                 g_object_unref (G_OBJECT (src_folder));
2673         } else {
2674                 if (gtk_widget_is_focus (header_view)) {
2675                         TnyList *headers;
2676                         gint response;
2677
2678                         headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
2679
2680                         /* Ask for user confirmation */
2681                         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2682                                                               TNY_FOLDER (folder_store), 
2683                                                               headers);
2684
2685                         /* Transfer messages */
2686                         if (response == GTK_RESPONSE_OK) {
2687                                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
2688                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2689                                                                  mail_op);
2690
2691                                 modest_mail_operation_xfer_msgs (mail_op, 
2692                                                                  headers,
2693                                                                  TNY_FOLDER (folder_store),
2694                                                                  TRUE,
2695                                                                  NULL,
2696                                                                  NULL);
2697
2698                                 g_object_unref (G_OBJECT (mail_op));
2699                         }
2700                         g_object_unref (headers);
2701                 }
2702         }
2703         g_object_unref (folder_store);
2704  end:
2705         gtk_widget_destroy (dialog);
2706 }
2707
2708
2709 /*
2710  * UI handler for the "Move to" action when invoked from the
2711  * ModestMsgViewWindow
2712  */
2713 static void 
2714 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
2715                                               ModestMsgViewWindow *win)
2716 {
2717         GtkWidget *dialog, *folder_view, *tree_view = NULL;
2718         gint result;
2719         ModestMainWindow *main_window;
2720         TnyHeader *header;
2721         TnyList *headers;
2722
2723         /* Get the folder view */
2724         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2725         folder_view = modest_main_window_get_child_widget (main_window,
2726                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2727
2728         /* Create and run the dialog */
2729         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);  
2730         result = gtk_dialog_run (GTK_DIALOG(dialog));
2731         g_object_ref (tree_view);
2732
2733         if (result == GTK_RESPONSE_ACCEPT) {
2734                 TnyFolderStore *folder_store;
2735                 gint response;
2736
2737                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2738
2739                 /* Create header list */
2740                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
2741                 headers = tny_simple_list_new ();
2742                 tny_list_prepend (headers, G_OBJECT (header));
2743                 g_object_unref (header);
2744
2745                 /* Ask user for confirmation. MSG-NOT404 */
2746                 response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2747                                                       TNY_FOLDER (folder_store), 
2748                                                       headers);
2749
2750                 /* Transfer current msg */
2751                 if (response == GTK_RESPONSE_OK) {
2752                         ModestMailOperation *mail_op;
2753
2754                         /* Create mail op */
2755                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
2756                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2757                                                          mail_op);
2758                         
2759                         /* Transfer messages */
2760                         modest_mail_operation_xfer_msgs (mail_op, 
2761                                                          headers,
2762                                                          TNY_FOLDER (folder_store),
2763                                                          TRUE,
2764                                                          tranasfer_msgs_from_viewer_cb,
2765                                                          NULL);
2766                         g_object_unref (G_OBJECT (mail_op));
2767                 } 
2768                 g_object_unref (headers);
2769                 g_object_unref (folder_store);
2770         }
2771         gtk_widget_destroy (dialog);
2772 }
2773
2774 void 
2775 modest_ui_actions_on_move_to (GtkAction *action, 
2776                               ModestWindow *win)
2777 {
2778         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
2779                           MODEST_IS_MSG_VIEW_WINDOW (win));
2780
2781         if (MODEST_IS_MAIN_WINDOW (win)) 
2782                 modest_ui_actions_on_main_window_move_to (action, 
2783                                                           MODEST_MAIN_WINDOW (win));
2784         else
2785                 modest_ui_actions_on_msg_view_window_move_to (action, 
2786                                                               MODEST_MSG_VIEW_WINDOW (win));
2787 }
2788
2789 /*
2790  * Calls #HeadersFunc for each header already selected in the main
2791  * window or the message currently being shown in the msg view window
2792  */
2793 static void
2794 do_headers_action (ModestWindow *win, 
2795                    HeadersFunc func,
2796                    gpointer user_data)
2797 {
2798         TnyList *headers_list;
2799         TnyIterator *iter;
2800
2801         /* Get headers */
2802         headers_list = get_selected_headers (win);
2803         if (!headers_list)
2804                 return;
2805
2806         /* Call the function for each header */
2807         iter = tny_list_create_iterator (headers_list);
2808         while (!tny_iterator_is_done (iter)) {
2809                 TnyHeader *header;
2810
2811                 header = TNY_HEADER (tny_iterator_get_current (iter));
2812                 func (header, win, user_data);
2813                 g_object_unref (header);
2814                 tny_iterator_next (iter);
2815         }
2816         g_object_unref (iter);
2817         g_object_unref (headers_list);
2818 }
2819
2820 void 
2821 modest_ui_actions_view_attachment (GtkAction *action,
2822                                    ModestWindow *window)
2823 {
2824         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2825                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
2826         } else {
2827                 /* not supported window for this action */
2828                 g_return_if_reached ();
2829         }
2830 }
2831
2832 void
2833 modest_ui_actions_save_attachments (GtkAction *action,
2834                                     ModestWindow *window)
2835 {
2836         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2837                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
2838         } else {
2839                 /* not supported window for this action */
2840                 g_return_if_reached ();
2841         }
2842 }
2843
2844 void
2845 modest_ui_actions_remove_attachments (GtkAction *action,
2846                                       ModestWindow *window)
2847 {
2848         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2849                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
2850         } else {
2851                 /* not supported window for this action */
2852                 g_return_if_reached ();
2853         }
2854 }
2855
2856 void 
2857 modest_ui_actions_on_settings (GtkAction *action, 
2858                                ModestWindow *win)
2859 {
2860         GtkWidget *dialog;
2861
2862         dialog = modest_platform_get_global_settings_dialog ();
2863         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
2864         gtk_widget_show (dialog);
2865
2866         gtk_dialog_run (GTK_DIALOG (dialog));
2867
2868         gtk_widget_destroy (dialog);
2869 }
2870
2871 void 
2872 modest_ui_actions_on_help (GtkAction *action, 
2873                            ModestWindow *win)
2874 {
2875         const gchar *help_id = NULL;
2876
2877         if (MODEST_IS_MAIN_WINDOW (win)) {
2878                 const gchar *action_name;
2879                 action_name = gtk_action_get_name (action);
2880
2881                 if (!strcmp (action_name, "FolderViewCSMHelp") ||
2882                     !strcmp (action_name, "HeaderViewCSMHelp")) {
2883                         GtkWidget *folder_view;
2884                         TnyFolderStore *folder_store;
2885                         /* Get selected folder */
2886                         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2887                                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2888                         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2889
2890                         /* Switch help_id */
2891                         if (TNY_IS_FOLDER (folder_store)) {
2892                                 switch (tny_folder_get_folder_type (TNY_FOLDER (folder_store))) {
2893                                 case TNY_FOLDER_TYPE_NORMAL:
2894                                         help_id = "applications_email_userfolder";
2895                                         break;
2896                                 case TNY_FOLDER_TYPE_INBOX:
2897                                         help_id = "applications_email_inbox";
2898                                         break;
2899                                 case TNY_FOLDER_TYPE_OUTBOX:
2900                                         help_id = "applications_email_outbox";
2901                                         break;
2902                                 case TNY_FOLDER_TYPE_SENT:
2903                                         help_id = "applications_email_sent";
2904                                         break;
2905                                 case TNY_FOLDER_TYPE_DRAFTS:
2906                                         help_id = "applications_email_drafts";
2907                                         break;
2908                                 case TNY_FOLDER_TYPE_ARCHIVE:
2909                                         help_id = "applications_email_archive";
2910                                         break;
2911                                 default:
2912                                         help_id = NULL;
2913                                 }
2914                         }
2915                 } else {
2916                         help_id = "applications_email_mainview";        
2917                 }
2918         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
2919                 help_id = "applications_email_viewer";
2920         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
2921                 help_id = "applications_email_editor";
2922
2923         modest_platform_show_help (GTK_WINDOW (win), help_id);
2924 }
2925
2926 void 
2927 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
2928                                             ModestWindow *window)
2929 {
2930         ModestMailOperation *mail_op;
2931         TnyList *headers;
2932
2933         /* Get headers */
2934         headers = get_selected_headers (window);
2935         if (!headers)
2936                 return;
2937
2938         /* Create mail operation */
2939         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
2940                                                                  G_OBJECT (window),
2941                                                                  modest_ui_actions_get_msgs_full_error_handler, 
2942                                                                  NULL);
2943         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
2944         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
2945
2946         /* Frees */
2947         g_object_unref (headers);
2948         g_object_unref (mail_op);
2949 }
2950
2951 void
2952 modest_ui_actions_on_email_menu_activated (GtkAction *action,
2953                                           ModestWindow *window)
2954 {
2955         g_return_if_fail (MODEST_IS_WINDOW (window));
2956
2957         /* Update dimmed */     
2958         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
2959 }
2960
2961 void
2962 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
2963                                           ModestWindow *window)
2964 {
2965         g_return_if_fail (MODEST_IS_WINDOW (window));
2966
2967         /* Update dimmed */     
2968         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
2969 }
2970
2971 void
2972 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
2973                                                  ModestWindow *window)
2974 {
2975         g_return_if_fail (MODEST_IS_WINDOW (window));
2976
2977         /* Update dimmed */     
2978         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
2979 }
2980
2981 void
2982 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
2983                                                      ModestWindow *window)
2984 {
2985         g_return_if_fail (MODEST_IS_WINDOW (window));
2986
2987         /* Update dimmed */     
2988         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
2989 }
2990
2991 void
2992 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
2993                                                      ModestWindow *window)
2994 {
2995         g_return_if_fail (MODEST_IS_WINDOW (window));
2996
2997         /* Update dimmed */     
2998         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
2999 }
3000
3001 void
3002 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
3003 {
3004         g_return_if_fail (MODEST_IS_WINDOW (window));
3005
3006         /* Update dimmed */     
3007         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
3008 }