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