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