aec999d66ee4fb94be9609fe5454331fdf6fafdb
[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 {
1237                 if (TNY_IS_FOLDER (folder_store) && selected) {
1238                         
1239                         if (!TNY_IS_MERGE_FOLDER (folder_store)) { /* TnyMergeFolder can have no get_account() implementation. */
1240                                 /* Update the active account */
1241                                 TnyAccount *account = tny_folder_get_account (TNY_FOLDER (folder_store));
1242                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1243                                 g_object_unref (account);
1244                         }
1245                         
1246                         /* Set folder on header view */
1247                         modest_main_window_set_contents_style (main_window, 
1248                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1249                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1250                                                        TNY_FOLDER (folder_store));
1251                         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1252                                                       MODEST_CONF_HEADER_VIEW_KEY);
1253                 } else {
1254                         /* Update the active account */
1255                         modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
1256                         /* Do not show folder */
1257                         modest_widget_memory_save (conf, G_OBJECT (header_view), MODEST_CONF_HEADER_VIEW_KEY);
1258                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
1259                 }
1260         }
1261
1262         /* Update toolbar dimming state */
1263         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1264 }
1265
1266 void 
1267 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1268                                      ModestWindow *win)
1269 {
1270         GtkWidget *dialog;
1271         gchar *txt, *item;
1272         gboolean online;
1273
1274         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1275         
1276         if (g_main_depth > 0)   
1277                 gdk_threads_enter ();
1278         online = tny_device_is_online (modest_runtime_get_device());
1279
1280         if (online) {
1281                 /* already online -- the item is simply not there... */
1282                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1283                                                  GTK_DIALOG_MODAL,
1284                                                  GTK_MESSAGE_WARNING,
1285                                                  GTK_BUTTONS_OK,
1286                                                  _("The %s you selected cannot be found"),
1287                                                  item);
1288                 gtk_dialog_run (GTK_DIALOG(dialog));
1289         } else {
1290                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1291                                                       GTK_WINDOW (win),
1292                                                       GTK_DIALOG_MODAL,
1293                                                       GTK_STOCK_CANCEL,
1294                                                       GTK_RESPONSE_REJECT,
1295                                                       GTK_STOCK_OK,
1296                                                       GTK_RESPONSE_ACCEPT,
1297                                                       NULL);
1298                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1299                                          "Do you want to get online?"), item);
1300                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1301                                     gtk_label_new (txt), FALSE, FALSE, 0);
1302                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1303                 g_free (txt);
1304
1305                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1306                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1307 //                      modest_platform_connect_and_wait ();;
1308                 }
1309         }
1310         gtk_widget_destroy (dialog);
1311         if (g_main_depth > 0)   
1312                 gdk_threads_leave ();
1313 }
1314
1315 void
1316 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1317                                      ModestWindow *win)
1318 {
1319         /* g_message ("%s %s", __FUNCTION__, link); */
1320 }       
1321
1322
1323 void
1324 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1325                                         ModestWindow *win)
1326 {
1327         modest_platform_activate_uri (link);
1328 }
1329
1330 void
1331 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1332                                           ModestWindow *win)
1333 {
1334         modest_platform_show_uri_popup (link);
1335 }
1336
1337 void
1338 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1339                                              ModestWindow *win)
1340 {
1341         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
1342 }
1343
1344 void
1345 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1346                                           const gchar *address,
1347                                           ModestWindow *win)
1348 {
1349         /* g_message ("%s %s", __FUNCTION__, address); */
1350 }
1351
1352 void
1353 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1354 {
1355         TnyTransportAccount *transport_account;
1356         ModestMailOperation *mail_operation;
1357         MsgData *data;
1358         gchar *account_name, *from;
1359         ModestAccountMgr *account_mgr;
1360
1361         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1362         
1363         data = modest_msg_edit_window_get_msg_data (edit_window);
1364
1365         account_mgr = modest_runtime_get_account_mgr();
1366         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1367         if (!account_name) 
1368                 account_name = modest_account_mgr_get_default_account (account_mgr);
1369         if (!account_name) {
1370                 g_printerr ("modest: no account found\n");
1371                 modest_msg_edit_window_free_msg_data (edit_window, data);
1372                 return;
1373         }
1374
1375         if (!strcmp (account_name, MODEST_ACTUAL_LOCAL_FOLDERS_ACCOUNT_ID)) {
1376                 account_name = g_strdup (data->account_name);
1377         }
1378
1379         transport_account =
1380                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
1381                                       (modest_runtime_get_account_store(),
1382                                        account_name,
1383                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1384         if (!transport_account) {
1385                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1386                 g_free (account_name);
1387                 modest_msg_edit_window_free_msg_data (edit_window, data);
1388                 return;
1389         }
1390         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1391
1392         /* Create the mail operation */         
1393         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
1394         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1395
1396         modest_mail_operation_save_to_drafts (mail_operation,
1397                                               transport_account,
1398                                               data->draft_msg,
1399                                               from,
1400                                               data->to, 
1401                                               data->cc, 
1402                                               data->bcc,
1403                                               data->subject, 
1404                                               data->plain_body, 
1405                                               data->html_body,
1406                                               data->attachments,
1407                                               data->priority_flags);
1408         /* Frees */
1409         g_free (from);
1410         g_free (account_name);
1411         g_object_unref (G_OBJECT (transport_account));
1412         g_object_unref (G_OBJECT (mail_operation));
1413
1414         modest_msg_edit_window_free_msg_data (edit_window, data);
1415
1416         /* Save settings and close the window */
1417         gtk_widget_destroy (GTK_WIDGET (edit_window));
1418 }
1419
1420 /* For instance, when clicking the Send toolbar button when editing a message: */
1421 void
1422 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1423 {
1424         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1425
1426         if (!modest_msg_edit_window_check_names (edit_window))
1427                 return;
1428         
1429         /* FIXME: Code added just for testing. The final version will
1430            use the send queue provided by tinymail and some
1431            classifier */
1432         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
1433         gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1434         if (!account_name) 
1435                 account_name = modest_account_mgr_get_default_account (account_mgr);
1436                 
1437         if (!account_name) {
1438                 g_printerr ("modest: no account found\n");
1439                 return;
1440         }
1441         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
1442
1443         if (!strcmp (account_name, MODEST_ACTUAL_LOCAL_FOLDERS_ACCOUNT_ID)) {
1444                 account_name = g_strdup (data->account_name);
1445         }
1446         
1447         /* Get the currently-active transport account for this modest account: */
1448         TnyTransportAccount *transport_account =
1449                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
1450                                       (modest_runtime_get_account_store(),
1451                                        account_name));
1452         if (!transport_account) {
1453                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1454                 g_free (account_name);
1455                 modest_msg_edit_window_free_msg_data (edit_window, data);
1456                 return;
1457         }
1458         
1459         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
1460
1461         /* mail content checks and dialogs */
1462         if (data->subject == NULL || data->subject[0] == '\0') {
1463                 GtkResponseType response;
1464                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1465                                                                     _("mcen_nc_subject_is_empty_send"));
1466                 if (response == GTK_RESPONSE_CANCEL) {
1467                         g_free (account_name);
1468                         return;
1469                 }
1470         }
1471
1472         if (data->plain_body == NULL || data->plain_body[0] == '\0') {
1473                 GtkResponseType response;
1474                 gchar *note_message;
1475                 gchar *note_subject = data->subject;
1476                 if (note_subject == NULL || note_subject[0] == '\0')
1477                         note_subject = _("mail_va_no_subject");
1478                 note_message = g_strdup_printf (_("emev_ni_ui_smtp_message_null"), note_subject);
1479                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1480                                                                     note_message);
1481                 g_free (note_message);
1482                 if (response == GTK_RESPONSE_CANCEL) {
1483                         g_free (account_name);
1484                         return;
1485                 }
1486         }
1487
1488         /* Create the mail operation */
1489         ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
1490         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1491
1492         modest_mail_operation_send_new_mail (mail_operation,
1493                                              transport_account,
1494                                              data->draft_msg,
1495                                              from,
1496                                              data->to, 
1497                                              data->cc, 
1498                                              data->bcc,
1499                                              data->subject, 
1500                                              data->plain_body, 
1501                                              data->html_body,
1502                                              data->attachments,
1503                                              data->priority_flags);
1504                                              
1505         /* Free data: */
1506         g_free (from);
1507         g_free (account_name);
1508         g_object_unref (G_OBJECT (transport_account));
1509         g_object_unref (G_OBJECT (mail_operation));
1510
1511         modest_msg_edit_window_free_msg_data (edit_window, data);
1512
1513         /* Save settings and close the window: */
1514         gtk_widget_destroy (GTK_WIDGET (edit_window));
1515 }
1516
1517 void 
1518 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1519                                   ModestMsgEditWindow *window)
1520 {
1521         ModestMsgEditFormatState *format_state = NULL;
1522
1523         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1524         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1525
1526         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1527                 return;
1528
1529         format_state = modest_msg_edit_window_get_format_state (window);
1530         g_return_if_fail (format_state != NULL);
1531
1532         format_state->bold = gtk_toggle_action_get_active (action);
1533         modest_msg_edit_window_set_format_state (window, format_state);
1534         g_free (format_state);
1535         
1536 }
1537
1538 void 
1539 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1540                                      ModestMsgEditWindow *window)
1541 {
1542         ModestMsgEditFormatState *format_state = NULL;
1543
1544         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1545         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1546
1547         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1548                 return;
1549
1550         format_state = modest_msg_edit_window_get_format_state (window);
1551         g_return_if_fail (format_state != NULL);
1552
1553         format_state->italics = gtk_toggle_action_get_active (action);
1554         modest_msg_edit_window_set_format_state (window, format_state);
1555         g_free (format_state);
1556         
1557 }
1558
1559 void 
1560 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
1561                                      ModestMsgEditWindow *window)
1562 {
1563         ModestMsgEditFormatState *format_state = NULL;
1564
1565         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1566         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1567
1568         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1569                 return;
1570
1571         format_state = modest_msg_edit_window_get_format_state (window);
1572         g_return_if_fail (format_state != NULL);
1573
1574         format_state->bullet = gtk_toggle_action_get_active (action);
1575         modest_msg_edit_window_set_format_state (window, format_state);
1576         g_free (format_state);
1577         
1578 }
1579
1580 void 
1581 modest_ui_actions_on_change_justify (GtkRadioAction *action,
1582                                      GtkRadioAction *selected,
1583                                      ModestMsgEditWindow *window)
1584 {
1585         ModestMsgEditFormatState *format_state = NULL;
1586         GtkJustification value;
1587
1588         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1589
1590         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1591                 return;
1592
1593         value = gtk_radio_action_get_current_value (selected);
1594
1595         format_state = modest_msg_edit_window_get_format_state (window);
1596         g_return_if_fail (format_state != NULL);
1597
1598         format_state->justification = value;
1599         modest_msg_edit_window_set_format_state (window, format_state);
1600         g_free (format_state);
1601 }
1602
1603 void 
1604 modest_ui_actions_on_select_editor_color (GtkAction *action,
1605                                           ModestMsgEditWindow *window)
1606 {
1607         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1608         g_return_if_fail (GTK_IS_ACTION (action));
1609
1610         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1611                 return;
1612
1613         modest_msg_edit_window_select_color (window);
1614 }
1615
1616 void 
1617 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
1618                                                      ModestMsgEditWindow *window)
1619 {
1620         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1621         g_return_if_fail (GTK_IS_ACTION (action));
1622
1623         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1624                 return;
1625
1626         modest_msg_edit_window_select_background_color (window);
1627 }
1628
1629 void 
1630 modest_ui_actions_on_insert_image (GtkAction *action,
1631                                    ModestMsgEditWindow *window)
1632 {
1633         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1634         g_return_if_fail (GTK_IS_ACTION (action));
1635
1636         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1637                 return;
1638
1639         modest_msg_edit_window_insert_image (window);
1640 }
1641
1642 void 
1643 modest_ui_actions_on_attach_file (GtkAction *action,
1644                                   ModestMsgEditWindow *window)
1645 {
1646         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1647         g_return_if_fail (GTK_IS_ACTION (action));
1648
1649         modest_msg_edit_window_attach_file (window);
1650 }
1651
1652 void 
1653 modest_ui_actions_on_remove_attachments (GtkAction *action,
1654                                          ModestMsgEditWindow *window)
1655 {
1656         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1657         g_return_if_fail (GTK_IS_ACTION (action));
1658
1659         modest_msg_edit_window_remove_attachments (window, NULL);
1660 }
1661
1662 /*
1663  * Shows a dialog with an entry that asks for some text. The returned
1664  * value must be freed by the caller. The dialog window title will be
1665  * set to @title.
1666  */
1667 static gchar *
1668 ask_for_folder_name (GtkWindow *parent_window,
1669                      const gchar *title)
1670 {
1671         GtkWidget *dialog, *entry;
1672         gchar *folder_name = NULL;
1673
1674         /* Ask for folder name */
1675         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1676                                               parent_window,
1677                                               GTK_DIALOG_MODAL,
1678                                               GTK_STOCK_CANCEL,
1679                                               GTK_RESPONSE_REJECT,
1680                                               GTK_STOCK_OK,
1681                                               GTK_RESPONSE_ACCEPT,
1682                                               NULL);
1683         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1684                             gtk_label_new(title),
1685                             FALSE, FALSE, 0);
1686                 
1687         entry = gtk_entry_new_with_max_length (40);
1688         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1689                             entry,
1690                             TRUE, FALSE, 0);    
1691         
1692         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1693         
1694         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
1695                 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1696
1697         gtk_widget_destroy (dialog);
1698
1699         return folder_name;
1700 }
1701
1702 void 
1703 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1704 {
1705         TnyFolderStore *parent_folder;
1706         GtkWidget *folder_view;
1707         
1708         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1709
1710         folder_view = modest_main_window_get_child_widget (main_window,
1711                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1712         if (!folder_view)
1713                 return;
1714
1715         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1716         
1717         if (parent_folder) {
1718                 gboolean finished = FALSE;
1719                 gint result;
1720                 gchar *folder_name = NULL, *suggested_name = NULL;
1721
1722                 /* Run the new folder dialog */
1723                 while (!finished) {
1724                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (main_window),
1725                                                                         parent_folder,
1726                                                                         suggested_name,
1727                                                                         &folder_name);
1728
1729                         if (result == GTK_RESPONSE_REJECT) {
1730                                 finished = TRUE;
1731                         } else {
1732                                 ModestMailOperation *mail_op;
1733                                 TnyFolder *new_folder = NULL;
1734
1735                                 mail_op  = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, 
1736                                                                       G_OBJECT(main_window));
1737                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
1738                                                                  mail_op);
1739                                 new_folder = modest_mail_operation_create_folder (mail_op,
1740                                                                                   parent_folder,
1741                                                                                   (const gchar *) folder_name);
1742                                 if (new_folder) {
1743                                         g_object_unref (new_folder);
1744                                         finished = TRUE;
1745                                 }
1746                                 g_object_unref (mail_op);
1747                         }
1748                         g_free (folder_name);
1749                         folder_name = NULL;
1750                 }
1751
1752                 g_object_unref (parent_folder);
1753         }
1754 }
1755
1756 void 
1757 modest_ui_actions_on_rename_folder (GtkAction *action,
1758                                      ModestMainWindow *main_window)
1759 {
1760         TnyFolderStore *folder;
1761         GtkWidget *folder_view;
1762         GtkWidget *header_view; 
1763
1764         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1765
1766         folder_view = modest_main_window_get_child_widget (main_window,
1767                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1768         if (!folder_view)
1769                 return;
1770
1771         header_view = modest_main_window_get_child_widget (main_window,
1772                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1773         
1774         if (!header_view)
1775                 return;
1776
1777         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1778         
1779         if (folder && TNY_IS_FOLDER (folder)) {
1780                 gchar *folder_name;
1781                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1782                                                    _("Please enter a new name for the folder"));
1783
1784                 if (folder_name != NULL && strlen (folder_name) > 0) {
1785                         ModestMailOperation *mail_op;
1786
1787                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(main_window));
1788                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1789                                                          mail_op);
1790
1791                         modest_header_view_set_folder (MODEST_HEADER_VIEW (header_view), NULL);
1792
1793                         modest_mail_operation_rename_folder (mail_op,
1794                                                              TNY_FOLDER (folder),
1795                                                              (const gchar *) folder_name);
1796
1797                         g_object_unref (mail_op);
1798                         g_free (folder_name);
1799                 }
1800                 g_object_unref (folder);
1801         }
1802 }
1803
1804 static void
1805 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
1806                                                gpointer user_data)
1807 {
1808         GObject *win = modest_mail_operation_get_source (mail_op);
1809
1810         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
1811                                                 _("mail_in_ui_folder_delete_error"));
1812 }
1813
1814 static void
1815 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
1816 {
1817         TnyFolderStore *folder;
1818         GtkWidget *folder_view;
1819         gint response;
1820         gchar *message;
1821         
1822         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1823
1824         folder_view = modest_main_window_get_child_widget (main_window,
1825                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1826         if (!folder_view)
1827                 return;
1828
1829         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1830
1831         /* Show an error if it's an account */
1832         if (!TNY_IS_FOLDER (folder)) {
1833                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
1834                                                         _("mail_in_ui_folder_delete_error"));
1835                 return ;
1836         }
1837
1838         /* Ask the user */      
1839         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
1840                                     tny_folder_get_name (TNY_FOLDER (folder)));
1841         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window), 
1842                                                             (const gchar *) message);
1843         g_free (message);
1844
1845         if (response == GTK_RESPONSE_OK) {
1846                 ModestMailOperation *mail_op = 
1847                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
1848                                                                        G_OBJECT(main_window),
1849                                                                        modest_ui_actions_delete_folder_error_handler,
1850                                                                        NULL);
1851
1852                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1853                                                  mail_op);
1854                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
1855                 g_object_unref (G_OBJECT (mail_op));
1856         }
1857
1858         g_object_unref (G_OBJECT (folder));
1859 }
1860
1861 void 
1862 modest_ui_actions_on_delete_folder (GtkAction *action,
1863                                      ModestMainWindow *main_window)
1864 {
1865         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1866
1867         delete_folder (main_window, FALSE);
1868 }
1869
1870 void 
1871 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1872 {
1873         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1874         
1875         delete_folder (main_window, TRUE);
1876 }
1877
1878 void
1879 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
1880                                          const gchar* server_account_name,
1881                                          gchar **username,
1882                                          gchar **password, 
1883                                          gboolean *cancel, 
1884                                          gboolean *remember,
1885                                          ModestMainWindow *main_window)
1886 {
1887         g_return_if_fail(server_account_name);
1888         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
1889         
1890         /* Initalize output parameters: */
1891         if (cancel)
1892                 *cancel = FALSE;
1893                 
1894         if (remember)
1895                 *remember = TRUE;
1896                 
1897 #ifdef MODEST_PLATFORM_MAEMO
1898         /* Maemo uses a different (awkward) button order,
1899          * It should probably just use gtk_alternative_dialog_button_order ().
1900          */
1901         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
1902                                               NULL,
1903                                               GTK_DIALOG_MODAL,
1904                                               GTK_STOCK_OK,
1905                                               GTK_RESPONSE_ACCEPT,
1906                                               GTK_STOCK_CANCEL,
1907                                               GTK_RESPONSE_REJECT,
1908                                               NULL);
1909 #else
1910         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
1911                                               NULL,
1912                                               GTK_DIALOG_MODAL,
1913                                               GTK_STOCK_CANCEL,
1914                                               GTK_RESPONSE_REJECT,
1915                                               GTK_STOCK_OK,
1916                                               GTK_RESPONSE_ACCEPT,
1917                                               NULL);
1918 #endif /* MODEST_PLATFORM_MAEMO */
1919
1920         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1921         
1922         gchar *server_name = modest_server_account_get_hostname (
1923                 modest_runtime_get_account_mgr(), server_account_name);
1924         
1925         /* This causes a warning because the logical ID has no %s in it, 
1926          * though the translation does, but there is not much we can do about that: */
1927         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
1928         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1929                             FALSE, FALSE, 0);
1930         g_free (txt);
1931         g_free (server_name);
1932         server_name = NULL;
1933
1934         /* username: */
1935         gchar *initial_username = modest_server_account_get_username (
1936                 modest_runtime_get_account_mgr(), server_account_name);
1937         
1938         GtkWidget *entry_username = gtk_entry_new ();
1939         if (initial_username)
1940                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
1941         /* Dim this if a connection has ever succeeded with this username,
1942          * as per the UI spec: */
1943         const gboolean username_known = 
1944                 modest_server_account_get_username_has_succeeded(
1945                         modest_runtime_get_account_mgr(), server_account_name);
1946         gtk_widget_set_sensitive (entry_username, !username_known);
1947         
1948 #ifdef MODEST_PLATFORM_MAEMO
1949         /* Auto-capitalization is the default, so let's turn it off: */
1950         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
1951         
1952         /* Create a size group to be used by all captions.
1953          * Note that HildonCaption does not create a default size group if we do not specify one.
1954          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
1955         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
1956         
1957         GtkWidget *caption = hildon_caption_new (sizegroup, 
1958                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
1959         gtk_widget_show (entry_username);
1960         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
1961                 FALSE, FALSE, MODEST_MARGIN_HALF);
1962         gtk_widget_show (caption);
1963 #else 
1964         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
1965                             TRUE, FALSE, 0);
1966 #endif /* MODEST_PLATFORM_MAEMO */      
1967                             
1968         /* password: */
1969         GtkWidget *entry_password = gtk_entry_new ();
1970         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
1971         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
1972         
1973 #ifdef MODEST_PLATFORM_MAEMO
1974         /* Auto-capitalization is the default, so let's turn it off: */
1975         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
1976                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
1977         
1978         caption = hildon_caption_new (sizegroup, 
1979                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
1980         gtk_widget_show (entry_password);
1981         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
1982                 FALSE, FALSE, MODEST_MARGIN_HALF);
1983         gtk_widget_show (caption);
1984         g_object_unref (sizegroup);
1985 #else 
1986         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
1987                             TRUE, FALSE, 0);
1988 #endif /* MODEST_PLATFORM_MAEMO */      
1989                                 
1990 /* This is not in the Maemo UI spec:
1991         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1992         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1993                             TRUE, FALSE, 0);
1994 */
1995
1996         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1997         
1998         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1999                 if (username) {
2000                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2001                         
2002                         modest_server_account_set_username (
2003                                  modest_runtime_get_account_mgr(), server_account_name, 
2004                                  *username);
2005                                  
2006                         const gboolean username_was_changed = 
2007                                 (strcmp (*username, initial_username) != 0);
2008                         if (username_was_changed) {
2009                                 /* To actually use a changed username, 
2010                                  * we must reset the connection, according to pvanhoof.
2011                                  * This _might_ be a sensible way to do that: */
2012                                  TnyDevice *device = modest_runtime_get_device();
2013                                  tny_device_force_offline (device);
2014                                  tny_device_force_online (device);
2015                         }
2016                 }
2017                         
2018                 if (password) {
2019                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2020                         
2021                         /* We do not save the password in the configuration, 
2022                          * because this function is only called for passwords that should 
2023                          * not be remembered:
2024                         modest_server_account_set_password (
2025                                  modest_runtime_get_account_mgr(), server_account_name, 
2026                                  *password);
2027                         */
2028                 }
2029                 
2030                 if (cancel)
2031                         *cancel   = FALSE;
2032                         
2033         } else {
2034                 if (username)
2035                         *username = NULL;
2036                         
2037                 if (password)
2038                         *password = NULL;
2039                         
2040                 if (cancel)
2041                         *cancel   = TRUE;
2042         }
2043
2044 /* This is not in the Maemo UI spec:
2045         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2046                 *remember = TRUE;
2047         else
2048                 *remember = FALSE;
2049 */
2050
2051         gtk_widget_destroy (dialog);
2052         
2053         printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel);
2054 }
2055
2056 void
2057 modest_ui_actions_on_cut (GtkAction *action,
2058                           ModestWindow *window)
2059 {
2060         GtkWidget *focused_widget;
2061
2062         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2063         if (GTK_IS_EDITABLE (focused_widget)) {
2064                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2065         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2066                 GtkTextBuffer *buffer;
2067                 GtkClipboard *clipboard;
2068
2069                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2070                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2071                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2072         }
2073 }
2074
2075 void
2076 modest_ui_actions_on_copy (GtkAction *action,
2077                            ModestWindow *window)
2078 {
2079         GtkClipboard *clipboard;
2080         GtkWidget *focused_widget;
2081
2082         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2083         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2084         if (GTK_IS_LABEL (focused_widget)) {
2085                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2086         } else if (GTK_IS_EDITABLE (focused_widget)) {
2087                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2088         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2089                 GtkTextBuffer *buffer;
2090
2091                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2092                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2093         }
2094 }
2095
2096 void
2097 modest_ui_actions_on_undo (GtkAction *action,
2098                            ModestWindow *window)
2099 {
2100         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2101                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2102         } else {
2103                 g_return_if_reached ();
2104         }
2105 }
2106
2107 void
2108 modest_ui_actions_on_paste (GtkAction *action,
2109                             ModestWindow *window)
2110 {
2111         GtkWidget *focused_widget;
2112
2113         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2114         if (GTK_IS_EDITABLE (focused_widget)) {
2115                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
2116         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2117                 GtkTextBuffer *buffer;
2118                 GtkClipboard *clipboard;
2119
2120                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2121                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2122                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
2123         }
2124 }
2125
2126 void
2127 modest_ui_actions_on_select_all (GtkAction *action,
2128                                  ModestWindow *window)
2129 {
2130         GtkWidget *focused_widget;
2131
2132         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2133         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
2134                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
2135         } else if (GTK_IS_LABEL (focused_widget)) {
2136                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
2137         } else if (GTK_IS_EDITABLE (focused_widget)) {
2138                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
2139         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2140                 GtkTextBuffer *buffer;
2141                 GtkTextIter start, end;
2142
2143                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2144                 gtk_text_buffer_get_start_iter (buffer, &start);
2145                 gtk_text_buffer_get_end_iter (buffer, &end);
2146                 gtk_text_buffer_select_range (buffer, &start, &end);
2147         }
2148         else if ((MODEST_IS_FOLDER_VIEW (focused_widget)) ||
2149                  (MODEST_IS_HEADER_VIEW (focused_widget))) {
2150                 
2151                 GtkTreeSelection *selection = NULL;
2152
2153                 /* Get header view */           
2154                 GtkWidget *header_view = focused_widget;
2155                 if (MODEST_IS_FOLDER_VIEW (focused_widget))
2156                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
2157                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2158
2159                 /* Select all messages */
2160                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
2161                 gtk_tree_selection_select_all (selection);
2162         }
2163 }
2164
2165 void
2166 modest_ui_actions_on_mark_as_read (GtkAction *action,
2167                                    ModestWindow *window)
2168 {       
2169         g_return_if_fail (MODEST_IS_WINDOW(window));
2170                 
2171         /* Mark each header as read */
2172         do_headers_action (window, headers_action_mark_as_read, NULL);
2173 }
2174
2175 void
2176 modest_ui_actions_on_mark_as_unread (GtkAction *action,
2177                                      ModestWindow *window)
2178 {       
2179         g_return_if_fail (MODEST_IS_WINDOW(window));
2180                 
2181         /* Mark each header as read */
2182         do_headers_action (window, headers_action_mark_as_unread, NULL);
2183 }
2184
2185 void
2186 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
2187                                   GtkRadioAction *selected,
2188                                   ModestWindow *window)
2189 {
2190         gint value;
2191
2192         value = gtk_radio_action_get_current_value (selected);
2193         if (MODEST_IS_WINDOW (window)) {
2194                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
2195         }
2196 }
2197
2198 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
2199                                                         GtkRadioAction *selected,
2200                                                         ModestWindow *window)
2201 {
2202         TnyHeaderFlags flags;
2203         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2204
2205         flags = gtk_radio_action_get_current_value (selected);
2206         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
2207 }
2208
2209 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
2210                                                            GtkRadioAction *selected,
2211                                                            ModestWindow *window)
2212 {
2213         gint file_format;
2214
2215         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2216
2217         file_format = gtk_radio_action_get_current_value (selected);
2218         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
2219 }
2220
2221
2222 void     
2223 modest_ui_actions_on_zoom_plus (GtkAction *action,
2224                                 ModestWindow *window)
2225 {
2226         g_return_if_fail (MODEST_IS_WINDOW (window));
2227
2228         modest_window_zoom_plus (MODEST_WINDOW (window));
2229 }
2230
2231 void     
2232 modest_ui_actions_on_zoom_minus (GtkAction *action,
2233                                  ModestWindow *window)
2234 {
2235         g_return_if_fail (MODEST_IS_WINDOW (window));
2236
2237         modest_window_zoom_minus (MODEST_WINDOW (window));
2238 }
2239
2240 void     
2241 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
2242                                            ModestWindow *window)
2243 {
2244         ModestWindowMgr *mgr;
2245         gboolean fullscreen, active;
2246         g_return_if_fail (MODEST_IS_WINDOW (window));
2247
2248         mgr = modest_runtime_get_window_mgr ();
2249
2250         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
2251         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2252
2253         if (active != fullscreen) {
2254                 modest_window_mgr_set_fullscreen_mode (mgr, active);
2255                 gtk_window_present (GTK_WINDOW (window));
2256         }
2257 }
2258
2259 void
2260 modest_ui_actions_on_change_fullscreen (GtkAction *action,
2261                                         ModestWindow *window)
2262 {
2263         ModestWindowMgr *mgr;
2264         gboolean fullscreen;
2265
2266         g_return_if_fail (MODEST_IS_WINDOW (window));
2267
2268         mgr = modest_runtime_get_window_mgr ();
2269         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2270         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
2271
2272         gtk_window_present (GTK_WINDOW (window));
2273 }
2274
2275 /* 
2276  * Used by modest_ui_actions_on_details to call do_headers_action 
2277  */
2278 static void
2279 headers_action_show_details (TnyHeader *header, 
2280                              ModestWindow *window,
2281                              gpointer user_data)
2282
2283 {
2284         GtkWidget *dialog;
2285         
2286         /* Create dialog */
2287         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
2288
2289         /* Run dialog */
2290         gtk_widget_show_all (dialog);
2291         gtk_dialog_run (GTK_DIALOG (dialog));
2292
2293         gtk_widget_destroy (dialog);
2294 }
2295
2296 /*
2297  * Show the folder details in a ModestDetailsDialog widget
2298  */
2299 static void
2300 show_folder_details (TnyFolder *folder, 
2301                      GtkWindow *window)
2302 {
2303         GtkWidget *dialog;
2304         
2305         /* Create dialog */
2306         dialog = modest_details_dialog_new_with_folder (window, folder);
2307
2308         /* Run dialog */
2309         gtk_widget_show_all (dialog);
2310         gtk_dialog_run (GTK_DIALOG (dialog));
2311
2312         gtk_widget_destroy (dialog);
2313 }
2314
2315 /*
2316  * Show the header details in a ModestDetailsDialog widget
2317  */
2318 void     
2319 modest_ui_actions_on_details (GtkAction *action, 
2320                               ModestWindow *win)
2321 {
2322         TnyList * headers_list;
2323         TnyIterator *iter;
2324         TnyHeader *header;              
2325
2326         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
2327                 TnyMsg *msg;
2328
2329                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
2330                 if (!msg)
2331                         return;
2332                 g_object_unref (msg);           
2333
2334                 headers_list = get_selected_headers (win);
2335                 if (!headers_list)
2336                         return;
2337
2338                 iter = tny_list_create_iterator (headers_list);
2339
2340                 header = TNY_HEADER (tny_iterator_get_current (iter));
2341                 headers_action_show_details (header, win, NULL);
2342                 g_object_unref (header);
2343
2344                 g_object_unref (iter);
2345                 g_object_unref (headers_list);
2346
2347         } else if (MODEST_IS_MAIN_WINDOW (win)) {
2348                 GtkWidget *folder_view, *header_view;
2349
2350                 /* Check which widget has the focus */
2351                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2352                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
2353                 if (gtk_widget_is_focus (folder_view)) {
2354                         TnyFolder *folder;
2355
2356                         folder = (TnyFolder *) modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2357
2358                         /* Show only when it's a folder */
2359                         if (!folder || !TNY_IS_FOLDER (folder))
2360                                 return;
2361
2362                         show_folder_details (folder, GTK_WINDOW (win));
2363
2364                 } else {
2365                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2366                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2367                         /* Show details of each header */
2368                         do_headers_action (win, headers_action_show_details, header_view);
2369                 }
2370         }
2371 }
2372
2373 void     
2374 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
2375                                      ModestMsgEditWindow *window)
2376 {
2377         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2378
2379         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
2380 }
2381
2382 void     
2383 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
2384                                       ModestMsgEditWindow *window)
2385 {
2386         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2387
2388         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
2389 }
2390
2391 void
2392 modest_ui_actions_toggle_folders_view (GtkAction *action, 
2393                                        ModestMainWindow *main_window)
2394 {
2395         ModestConf *conf;
2396         
2397         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2398
2399         conf = modest_runtime_get_conf ();
2400         
2401         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
2402                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
2403         else
2404                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
2405 }
2406
2407 void 
2408 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
2409                                      ModestWindow *window)
2410 {
2411         gboolean active, fullscreen = FALSE;
2412         ModestWindowMgr *mgr;
2413
2414         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
2415
2416         /* Check if we want to toggle the toolbar vuew in fullscreen
2417            or normal mode */
2418         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
2419                      "ViewShowToolbarFullScreen")) {
2420                 fullscreen = TRUE;
2421         }
2422
2423         /* Toggle toolbar */
2424         mgr = modest_runtime_get_window_mgr ();
2425         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
2426 }
2427
2428 void     
2429 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
2430                                            ModestMsgEditWindow *window)
2431 {
2432         modest_msg_edit_window_select_font (window);
2433 }
2434
2435 void
2436 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
2437                                                   const gchar *display_name,
2438                                                   GtkWindow *window)
2439 {
2440         /* Do not change the application name if the widget has not
2441            the focus. This callback could be called even if the folder
2442            view has not the focus, because the handled signal could be
2443            emitted when the folder view is redrawn */
2444         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
2445                 if (display_name)
2446                         gtk_window_set_title (window, display_name);
2447                 else
2448                         gtk_window_set_title (window, " ");
2449         }
2450 }
2451
2452 void
2453 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
2454 {
2455         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2456         modest_msg_edit_window_select_contacts (window);
2457 }
2458
2459 void
2460 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
2461 {
2462         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2463         modest_msg_edit_window_check_names (window);
2464 }
2465
2466
2467 static GtkWidget*
2468 create_move_to_dialog (ModestWindow *win,
2469                        GtkWidget *folder_view,
2470                        GtkWidget **tree_view)
2471 {
2472         GtkWidget *dialog, *scroll;
2473
2474         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2475                                               GTK_WINDOW (win),
2476                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
2477                                               GTK_STOCK_OK,
2478                                               GTK_RESPONSE_ACCEPT,
2479                                               GTK_STOCK_CANCEL,
2480                                               GTK_RESPONSE_REJECT,
2481                                               NULL);
2482
2483         /* Create scrolled window */
2484         scroll = gtk_scrolled_window_new (NULL, NULL);
2485         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
2486                                          GTK_POLICY_AUTOMATIC,
2487                                          GTK_POLICY_AUTOMATIC);
2488
2489         /* Create folder view */
2490         *tree_view = modest_folder_view_new (NULL);
2491         gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
2492                                  gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
2493         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
2494
2495         /* Add scroll to dialog */
2496         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
2497                             scroll, FALSE, FALSE, 0);
2498
2499         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2500
2501         return dialog;
2502 }
2503
2504 /*
2505  * Returns TRUE if at least one of the headers of the list belongs to
2506  * a message that has been fully retrieved.
2507  */
2508 static gboolean
2509 has_retrieved_msgs (TnyList *list)
2510 {
2511         TnyIterator *iter;
2512         gboolean found = FALSE;
2513
2514         iter = tny_list_create_iterator (list);
2515         while (tny_iterator_is_done (iter) && !found) {
2516                 TnyHeader *header;
2517                 TnyHeaderFlags flags;
2518
2519                 header = TNY_HEADER (tny_iterator_get_current (iter));
2520                 flags = tny_header_get_flags (header);
2521                 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
2522                         found = TRUE;
2523
2524                 if (!found)
2525                         tny_iterator_next (iter);
2526         }
2527         g_object_unref (iter);
2528
2529         return found;
2530 }
2531
2532 /*
2533  * Shows a confirmation dialog to the user when we're moving messages
2534  * from a remote server to the local storage. Returns the dialog
2535  * response. If it's other kind of movement the it always returns
2536  * GTK_RESPONSE_OK
2537  */
2538 static gint
2539 msgs_move_to_confirmation (GtkWindow *win,
2540                            TnyFolder *dest_folder,
2541                            TnyList *headers)
2542 {
2543         gint response = GTK_RESPONSE_OK;
2544
2545         /* If the destination is a local folder */
2546         if (modest_tny_folder_is_local_folder (dest_folder)) {
2547                 TnyFolder *src_folder;
2548                 TnyIterator *iter;
2549                 TnyHeader *header;
2550
2551                 /* Get source folder */
2552                 iter = tny_list_create_iterator (headers);
2553                 header = TNY_HEADER (tny_iterator_get_current (iter));
2554                 src_folder = tny_header_get_folder (header);
2555                 g_object_unref (header);
2556                 g_object_unref (iter);
2557
2558                 /* If the source is a remote folder */
2559                 if (!modest_tny_folder_is_local_folder (src_folder)) {
2560                         const gchar *message;
2561                         
2562                         if (tny_list_get_length (headers) == 1)
2563                                 if (has_retrieved_msgs (headers))
2564                                         message = _("mcen_nc_move_retrieve");
2565                                 else
2566                                         message = _("mcen_nc_move_header");
2567                         else
2568                                 if (has_retrieved_msgs (headers))
2569                                         message = _("mcen_nc_move_retrieves");
2570                                 else
2571                                         message = _("mcen_nc_move_headers");
2572                         
2573                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
2574                                                                             (const gchar *) message);
2575                 }
2576                 g_object_unref (src_folder);
2577         }
2578         return response;
2579 }
2580
2581
2582 static void
2583 tranasfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
2584 {
2585         ModestMsgViewWindow *self = NULL;
2586         gboolean found = FALSE;
2587
2588         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
2589         self = MODEST_MSG_VIEW_WINDOW (object);
2590
2591         found = modest_msg_view_window_select_first_message (self);
2592         g_return_if_fail (found);
2593 }
2594
2595 void
2596 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
2597                                              gpointer user_data)
2598 {
2599         GObject *win = modest_mail_operation_get_source (mail_op);
2600
2601         /* TODO: show error message */
2602         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2603                                                 _("mail_in_ui_folder_move_target_error"));
2604 }
2605
2606 /*
2607  * UI handler for the "Move to" action when invoked from the
2608  * ModestMainWindow
2609  */
2610 static void 
2611 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
2612                                           ModestMainWindow *win)
2613 {
2614         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
2615         GtkWidget *header_view = NULL;
2616         gint result;
2617         TnyFolderStore *folder_store = NULL;
2618         ModestMailOperation *mail_op = NULL;
2619
2620         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
2621
2622         /* Get the folder view */
2623         folder_view = modest_main_window_get_child_widget (win,
2624                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2625
2626         /* Get header view */
2627         header_view = modest_main_window_get_child_widget (win,
2628                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2629
2630         /* Create and run the dialog */
2631         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);
2632         result = gtk_dialog_run (GTK_DIALOG(dialog));
2633         g_object_ref (tree_view);
2634
2635         /* We do this to save an indentation level ;-) */
2636         if (result != GTK_RESPONSE_ACCEPT)
2637                 goto end;
2638
2639         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2640
2641         if (TNY_IS_ACCOUNT (folder_store))
2642                 goto end;
2643
2644         /* Get folder or messages to transfer */
2645         if (gtk_widget_is_focus (folder_view)) {
2646                 TnyFolderStore *src_folder;
2647                 src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2648
2649                 /* Clean folder on header view before moving it */
2650                 modest_header_view_set_folder (MODEST_HEADER_VIEW (header_view), NULL); 
2651
2652                 if (TNY_IS_FOLDER (src_folder)) {
2653                         mail_op = 
2654                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
2655                                                                                G_OBJECT(win),
2656                                                                                modest_ui_actions_move_folder_error_handler,
2657                                                                                NULL);
2658                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
2659
2660                         modest_mail_operation_xfer_folder (mail_op, 
2661                                                            TNY_FOLDER (src_folder),
2662                                                            folder_store,
2663                                                            TRUE);
2664                         /* Unref mail operation */
2665                         g_object_unref (G_OBJECT (mail_op));
2666                 }
2667
2668                 /* Frees */
2669                 g_object_unref (G_OBJECT (src_folder));
2670         } else {
2671                 if (gtk_widget_is_focus (header_view)) {
2672                         TnyList *headers;
2673                         gint response;
2674
2675                         headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
2676
2677                         /* Ask for user confirmation */
2678                         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2679                                                               TNY_FOLDER (folder_store), 
2680                                                               headers);
2681
2682                         /* Transfer messages */
2683                         if (response == GTK_RESPONSE_OK) {
2684                                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
2685                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2686                                                                  mail_op);
2687
2688                                 modest_mail_operation_xfer_msgs (mail_op, 
2689                                                                  headers,
2690                                                                  TNY_FOLDER (folder_store),
2691                                                                  TRUE,
2692                                                                  NULL,
2693                                                                  NULL);
2694
2695                                 g_object_unref (G_OBJECT (mail_op));
2696                         }
2697                         g_object_unref (headers);
2698                 }
2699         }
2700         g_object_unref (folder_store);
2701  end:
2702         gtk_widget_destroy (dialog);
2703 }
2704
2705
2706 /*
2707  * UI handler for the "Move to" action when invoked from the
2708  * ModestMsgViewWindow
2709  */
2710 static void 
2711 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
2712                                               ModestMsgViewWindow *win)
2713 {
2714         GtkWidget *dialog, *folder_view, *tree_view = NULL;
2715         gint result;
2716         ModestMainWindow *main_window;
2717         TnyHeader *header;
2718         TnyList *headers;
2719
2720         /* Get the folder view */
2721         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2722         folder_view = modest_main_window_get_child_widget (main_window,
2723                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2724
2725         /* Create and run the dialog */
2726         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);  
2727         result = gtk_dialog_run (GTK_DIALOG(dialog));
2728         g_object_ref (tree_view);
2729
2730         if (result == GTK_RESPONSE_ACCEPT) {
2731                 TnyFolderStore *folder_store;
2732                 gint response;
2733
2734                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2735
2736                 /* Create header list */
2737                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
2738                 headers = tny_simple_list_new ();
2739                 tny_list_prepend (headers, G_OBJECT (header));
2740                 g_object_unref (header);
2741
2742                 /* Ask user for confirmation. MSG-NOT404 */
2743                 response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2744                                                       TNY_FOLDER (folder_store), 
2745                                                       headers);
2746
2747                 /* Transfer current msg */
2748                 if (response == GTK_RESPONSE_OK) {
2749                         ModestMailOperation *mail_op;
2750
2751                         /* Create mail op */
2752                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
2753                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2754                                                          mail_op);
2755                         
2756                         /* Transfer messages */
2757                         modest_mail_operation_xfer_msgs (mail_op, 
2758                                                          headers,
2759                                                          TNY_FOLDER (folder_store),
2760                                                          TRUE,
2761                                                          tranasfer_msgs_from_viewer_cb,
2762                                                          NULL);
2763                         g_object_unref (G_OBJECT (mail_op));
2764                 } 
2765                 g_object_unref (headers);
2766                 g_object_unref (folder_store);
2767         }
2768         gtk_widget_destroy (dialog);
2769 }
2770
2771 void 
2772 modest_ui_actions_on_move_to (GtkAction *action, 
2773                               ModestWindow *win)
2774 {
2775         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
2776                           MODEST_IS_MSG_VIEW_WINDOW (win));
2777
2778         if (MODEST_IS_MAIN_WINDOW (win)) 
2779                 modest_ui_actions_on_main_window_move_to (action, 
2780                                                           MODEST_MAIN_WINDOW (win));
2781         else
2782                 modest_ui_actions_on_msg_view_window_move_to (action, 
2783                                                               MODEST_MSG_VIEW_WINDOW (win));
2784 }
2785
2786 /*
2787  * Calls #HeadersFunc for each header already selected in the main
2788  * window or the message currently being shown in the msg view window
2789  */
2790 static void
2791 do_headers_action (ModestWindow *win, 
2792                    HeadersFunc func,
2793                    gpointer user_data)
2794 {
2795         TnyList *headers_list;
2796         TnyIterator *iter;
2797
2798         /* Get headers */
2799         headers_list = get_selected_headers (win);
2800         if (!headers_list)
2801                 return;
2802
2803         /* Call the function for each header */
2804         iter = tny_list_create_iterator (headers_list);
2805         while (!tny_iterator_is_done (iter)) {
2806                 TnyHeader *header;
2807
2808                 header = TNY_HEADER (tny_iterator_get_current (iter));
2809                 func (header, win, user_data);
2810                 g_object_unref (header);
2811                 tny_iterator_next (iter);
2812         }
2813         g_object_unref (iter);
2814         g_object_unref (headers_list);
2815 }
2816
2817 void 
2818 modest_ui_actions_view_attachment (GtkAction *action,
2819                                    ModestWindow *window)
2820 {
2821         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2822                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
2823         } else {
2824                 /* not supported window for this action */
2825                 g_return_if_reached ();
2826         }
2827 }
2828
2829 void
2830 modest_ui_actions_save_attachments (GtkAction *action,
2831                                     ModestWindow *window)
2832 {
2833         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2834                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
2835         } else {
2836                 /* not supported window for this action */
2837                 g_return_if_reached ();
2838         }
2839 }
2840
2841 void
2842 modest_ui_actions_remove_attachments (GtkAction *action,
2843                                       ModestWindow *window)
2844 {
2845         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2846                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
2847         } else {
2848                 /* not supported window for this action */
2849                 g_return_if_reached ();
2850         }
2851 }
2852
2853 void 
2854 modest_ui_actions_on_settings (GtkAction *action, 
2855                                ModestWindow *win)
2856 {
2857         GtkWidget *dialog;
2858
2859         dialog = modest_platform_get_global_settings_dialog ();
2860         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
2861         gtk_widget_show (dialog);
2862
2863         gtk_dialog_run (GTK_DIALOG (dialog));
2864
2865         gtk_widget_destroy (dialog);
2866 }
2867
2868 void 
2869 modest_ui_actions_on_help (GtkAction *action, 
2870                            ModestWindow *win)
2871 {
2872         const gchar *help_id = NULL;
2873
2874         if (MODEST_IS_MAIN_WINDOW (win)) {
2875                 const gchar *action_name;
2876                 action_name = gtk_action_get_name (action);
2877
2878                 if (!strcmp (action_name, "FolderViewCSMHelp") ||
2879                     !strcmp (action_name, "HeaderViewCSMHelp")) {
2880                         GtkWidget *folder_view;
2881                         TnyFolderStore *folder_store;
2882                         /* Get selected folder */
2883                         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2884                                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2885                         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2886
2887                         /* Switch help_id */
2888                         if (TNY_IS_FOLDER (folder_store)) {
2889                                 switch (tny_folder_get_folder_type (TNY_FOLDER (folder_store))) {
2890                                 case TNY_FOLDER_TYPE_NORMAL:
2891                                         help_id = "applications_email_userfolder";
2892                                         break;
2893                                 case TNY_FOLDER_TYPE_INBOX:
2894                                         help_id = "applications_email_inbox";
2895                                         break;
2896                                 case TNY_FOLDER_TYPE_OUTBOX:
2897                                         help_id = "applications_email_outbox";
2898                                         break;
2899                                 case TNY_FOLDER_TYPE_SENT:
2900                                         help_id = "applications_email_sent";
2901                                         break;
2902                                 case TNY_FOLDER_TYPE_DRAFTS:
2903                                         help_id = "applications_email_drafts";
2904                                         break;
2905                                 case TNY_FOLDER_TYPE_ARCHIVE:
2906                                         help_id = "applications_email_archive";
2907                                         break;
2908                                 default:
2909                                         help_id = NULL;
2910                                 }
2911                         }
2912                 } else {
2913                         help_id = "applications_email_mainview";        
2914                 }
2915         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
2916                 help_id = "applications_email_viewer";
2917         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
2918                 help_id = "applications_email_editor";
2919
2920         modest_platform_show_help (GTK_WINDOW (win), help_id);
2921 }
2922
2923 void 
2924 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
2925                                             ModestWindow *window)
2926 {
2927         ModestMailOperation *mail_op;
2928         TnyList *headers;
2929
2930         /* Get headers */
2931         headers = get_selected_headers (window);
2932         if (!headers)
2933                 return;
2934
2935         /* Create mail operation */
2936         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
2937                                                                  G_OBJECT (window),
2938                                                                  modest_ui_actions_get_msgs_full_error_handler, 
2939                                                                  NULL);
2940         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
2941         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
2942
2943         /* Frees */
2944         g_object_unref (headers);
2945         g_object_unref (mail_op);
2946 }
2947
2948 void
2949 modest_ui_actions_on_email_menu_activated (GtkAction *action,
2950                                           ModestWindow *window)
2951 {
2952         g_return_if_fail (MODEST_IS_WINDOW (window));
2953
2954         /* Update dimmed */     
2955         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
2956 }
2957
2958 void
2959 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
2960                                           ModestWindow *window)
2961 {
2962         g_return_if_fail (MODEST_IS_WINDOW (window));
2963
2964         /* Update dimmed */     
2965         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
2966 }
2967
2968 void
2969 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
2970                                                  ModestWindow *window)
2971 {
2972         g_return_if_fail (MODEST_IS_WINDOW (window));
2973
2974         /* Update dimmed */     
2975         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
2976 }
2977
2978 void
2979 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
2980                                                      ModestWindow *window)
2981 {
2982         g_return_if_fail (MODEST_IS_WINDOW (window));
2983
2984         /* Update dimmed */     
2985         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
2986 }
2987
2988 void
2989 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
2990                                                      ModestWindow *window)
2991 {
2992         g_return_if_fail (MODEST_IS_WINDOW (window));
2993
2994         /* Update dimmed */     
2995         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
2996 }
2997
2998 void
2999 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
3000 {
3001         g_return_if_fail (MODEST_IS_WINDOW (window));
3002
3003         /* Update dimmed */     
3004         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
3005 }