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