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