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