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