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