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