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