f0195a2d48671dbd17e80efb28bed791a20c7842
[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 /*
2879  * UI handler for the "Move to" action when invoked from the
2880  * ModestMainWindow
2881  */
2882 static void 
2883 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
2884                                           ModestMainWindow *win)
2885 {
2886         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
2887         GtkWidget *header_view = NULL;
2888         gint result;
2889         TnyFolderStore *folder_store = NULL;
2890         ModestMailOperation *mail_op = NULL;
2891
2892         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
2893
2894         /* Get the folder view */
2895         folder_view = modest_main_window_get_child_widget (win,
2896                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2897
2898         /* Get header view */
2899         header_view = modest_main_window_get_child_widget (win,
2900                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2901
2902         /* Create and run the dialog */
2903         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);
2904         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
2905         result = gtk_dialog_run (GTK_DIALOG(dialog));
2906         g_object_ref (tree_view);
2907
2908         /* We do this to save an indentation level ;-) */
2909         if (result != GTK_RESPONSE_ACCEPT)
2910                 goto end;
2911
2912         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2913
2914         if (TNY_IS_ACCOUNT (folder_store))
2915                 goto end;
2916
2917         /* Get folder or messages to transfer */
2918         if (gtk_widget_is_focus (folder_view)) {
2919                 TnyFolderStore *src_folder;
2920                 src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2921
2922                 /* Clean folder on header view before moving it */
2923                 modest_header_view_clear (MODEST_HEADER_VIEW (header_view)); 
2924
2925                 if (TNY_IS_FOLDER (src_folder)) {
2926                         mail_op = 
2927                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
2928                                                                                G_OBJECT(win),
2929                                                                                modest_ui_actions_move_folder_error_handler,
2930                                                                                NULL);
2931                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
2932
2933                         modest_mail_operation_xfer_folder (mail_op, 
2934                                                            TNY_FOLDER (src_folder),
2935                                                            folder_store,
2936                                                            TRUE);
2937                         /* Unref mail operation */
2938                         g_object_unref (G_OBJECT (mail_op));
2939                 }
2940
2941                 /* Frees */
2942                 g_object_unref (G_OBJECT (src_folder));
2943         } else {
2944                 if (gtk_widget_is_focus (header_view)) {
2945                         TnyList *headers;
2946                         gint response;
2947
2948                         headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
2949
2950                         /* Ask for user confirmation */
2951                         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2952                                                               TNY_FOLDER (folder_store), 
2953                                                               headers);
2954
2955                         /* Transfer messages */
2956                         if (response == GTK_RESPONSE_OK) {
2957                                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
2958                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2959                                                                  mail_op);
2960
2961                                 modest_mail_operation_xfer_msgs (mail_op, 
2962                                                                  headers,
2963                                                                  TNY_FOLDER (folder_store),
2964                                                                  TRUE,
2965                                                                  NULL,
2966                                                                  NULL);
2967
2968                                 g_object_unref (G_OBJECT (mail_op));
2969                         }
2970                         g_object_unref (headers);
2971                 }
2972         }
2973  end:
2974         if (folder_store != NULL)
2975                 g_object_unref (folder_store);
2976         gtk_widget_destroy (dialog);
2977 }
2978
2979
2980 /*
2981  * UI handler for the "Move to" action when invoked from the
2982  * ModestMsgViewWindow
2983  */
2984 static void 
2985 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
2986                                               ModestMsgViewWindow *win)
2987 {
2988         GtkWidget *dialog, *folder_view, *tree_view = NULL;
2989         gint result;
2990         ModestMainWindow *main_window;
2991         TnyHeader *header;
2992         TnyList *headers;
2993
2994         /* Get the folder view */
2995         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2996         if (main_window)
2997                 folder_view = modest_main_window_get_child_widget (main_window,
2998                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
2999         else
3000                 folder_view = NULL;
3001
3002         /* Create and run the dialog */
3003         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);  
3004         result = gtk_dialog_run (GTK_DIALOG(dialog));
3005         g_object_ref (tree_view);
3006
3007         if (result == GTK_RESPONSE_ACCEPT) {
3008                 TnyFolderStore *folder_store;
3009                 gint response;
3010
3011                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
3012
3013                 /* Create header list */
3014                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
3015                         
3016                 headers = tny_simple_list_new ();
3017                 tny_list_prepend (headers, G_OBJECT (header));
3018                 g_object_unref (header);
3019
3020                 /* Ask user for confirmation. MSG-NOT404 */
3021                 response = msgs_move_to_confirmation (GTK_WINDOW (win), 
3022                                                       TNY_FOLDER (folder_store), 
3023                                                       headers);
3024
3025                 /* Transfer current msg */
3026                 if (response == GTK_RESPONSE_OK) {
3027                         ModestMailOperation *mail_op;
3028
3029                         /* Create mail op */
3030                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
3031                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3032                                                          mail_op);
3033                         
3034                         /* Transfer messages */
3035                         modest_mail_operation_xfer_msgs (mail_op, 
3036                                                          headers,
3037                                                          TNY_FOLDER (folder_store),
3038                                                          TRUE,
3039                                                          transfer_msgs_from_viewer_cb,
3040                                                          NULL);
3041                         g_object_unref (G_OBJECT (mail_op));
3042                 }
3043                 g_object_unref (headers);
3044                 g_object_unref (folder_store);
3045         }
3046         gtk_widget_destroy (dialog);
3047 }
3048
3049 void 
3050 modest_ui_actions_on_move_to (GtkAction *action, 
3051                               ModestWindow *win)
3052 {
3053         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
3054                           MODEST_IS_MSG_VIEW_WINDOW (win));
3055
3056         if (MODEST_IS_MAIN_WINDOW (win)) 
3057                 modest_ui_actions_on_main_window_move_to (action, 
3058                                                           MODEST_MAIN_WINDOW (win));
3059         else
3060                 modest_ui_actions_on_msg_view_window_move_to (action, 
3061                                                               MODEST_MSG_VIEW_WINDOW (win));
3062 }
3063
3064 /*
3065  * Calls #HeadersFunc for each header already selected in the main
3066  * window or the message currently being shown in the msg view window
3067  */
3068 static void
3069 do_headers_action (ModestWindow *win, 
3070                    HeadersFunc func,
3071                    gpointer user_data)
3072 {
3073         TnyList *headers_list;
3074         TnyIterator *iter;
3075         TnyHeader *header;
3076         TnyFolder *folder;
3077
3078         /* Get headers */
3079         headers_list = get_selected_headers (win);
3080         if (!headers_list)
3081                 return;
3082
3083         /* Get the folder */
3084         iter = tny_list_create_iterator (headers_list);
3085         header = TNY_HEADER (tny_iterator_get_current (iter));
3086         folder = tny_header_get_folder (header);
3087         g_object_unref (header);
3088
3089         /* Call the function for each header */
3090         while (!tny_iterator_is_done (iter)) {
3091                 header = TNY_HEADER (tny_iterator_get_current (iter));
3092                 func (header, win, user_data);
3093                 g_object_unref (header);
3094                 tny_iterator_next (iter);
3095         }
3096
3097         /* Trick: do a poke status in order to speed up the signaling
3098            of observers */
3099         tny_folder_poke_status (folder);
3100
3101         /* Frees */
3102         g_object_unref (folder);
3103         g_object_unref (iter);
3104         g_object_unref (headers_list);
3105 }
3106
3107 void 
3108 modest_ui_actions_view_attachment (GtkAction *action,
3109                                    ModestWindow *window)
3110 {
3111         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3112                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
3113         } else {
3114                 /* not supported window for this action */
3115                 g_return_if_reached ();
3116         }
3117 }
3118
3119 void
3120 modest_ui_actions_save_attachments (GtkAction *action,
3121                                     ModestWindow *window)
3122 {
3123         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3124                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
3125         } else {
3126                 /* not supported window for this action */
3127                 g_return_if_reached ();
3128         }
3129 }
3130
3131 void
3132 modest_ui_actions_remove_attachments (GtkAction *action,
3133                                       ModestWindow *window)
3134 {
3135         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3136                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window));
3137         } else {
3138                 /* not supported window for this action */
3139                 g_return_if_reached ();
3140         }
3141 }
3142
3143 void 
3144 modest_ui_actions_on_settings (GtkAction *action, 
3145                                ModestWindow *win)
3146 {
3147         GtkWidget *dialog;
3148
3149         dialog = modest_platform_get_global_settings_dialog ();
3150         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
3151         gtk_widget_show_all (dialog);
3152
3153         gtk_dialog_run (GTK_DIALOG (dialog));
3154
3155         gtk_widget_destroy (dialog);
3156 }
3157
3158 void 
3159 modest_ui_actions_on_help (GtkAction *action, 
3160                            ModestWindow *win)
3161 {
3162         const gchar *help_id = NULL;
3163
3164         if (MODEST_IS_MAIN_WINDOW (win)) {
3165                 const gchar *action_name;
3166                 action_name = gtk_action_get_name (action);
3167
3168                 if (!strcmp (action_name, "FolderViewCSMHelp") ||
3169                     !strcmp (action_name, "HeaderViewCSMHelp")) {
3170                         GtkWidget *folder_view;
3171                         TnyFolderStore *folder_store;
3172                         /* Get selected folder */
3173                         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3174                                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
3175                         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3176
3177                         /* Switch help_id */
3178                         if (TNY_IS_FOLDER (folder_store)) {
3179                                 switch (tny_folder_get_folder_type (TNY_FOLDER (folder_store))) {
3180                                 case TNY_FOLDER_TYPE_NORMAL:
3181                                         help_id = "applications_email_userfolder";
3182                                         break;
3183                                 case TNY_FOLDER_TYPE_INBOX:
3184                                         help_id = "applications_email_inbox";
3185                                         break;
3186                                 case TNY_FOLDER_TYPE_OUTBOX:
3187                                         help_id = "applications_email_outbox";
3188                                         break;
3189                                 case TNY_FOLDER_TYPE_SENT:
3190                                         help_id = "applications_email_sent";
3191                                         break;
3192                                 case TNY_FOLDER_TYPE_DRAFTS:
3193                                         help_id = "applications_email_drafts";
3194                                         break;
3195                                 case TNY_FOLDER_TYPE_ARCHIVE:
3196                                         help_id = "applications_email_archive";
3197                                         break;
3198                                 default:
3199                                         help_id = NULL;
3200                                 }
3201                         }
3202                         g_object_unref (folder_store);
3203                 } else {
3204                         help_id = "applications_email_mainview";        
3205                 }
3206         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3207                 help_id = "applications_email_viewer";
3208         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
3209                 help_id = "applications_email_editor";
3210
3211         modest_platform_show_help (GTK_WINDOW (win), help_id);
3212 }
3213
3214 void 
3215 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
3216                                             ModestWindow *window)
3217 {
3218         ModestMailOperation *mail_op;
3219         TnyList *headers;
3220
3221         /* Get headers */
3222         headers = get_selected_headers (window);
3223         if (!headers)
3224                 return;
3225
3226         /* Create mail operation */
3227         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3228                                                                  G_OBJECT (window),
3229                                                                  modest_ui_actions_get_msgs_full_error_handler, 
3230                                                                  NULL);
3231         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3232         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
3233
3234         /* Frees */
3235         g_object_unref (headers);
3236         g_object_unref (mail_op);
3237 }
3238
3239 void
3240 modest_ui_actions_on_email_menu_activated (GtkAction *action,
3241                                           ModestWindow *window)
3242 {
3243         g_return_if_fail (MODEST_IS_WINDOW (window));
3244
3245         /* Update dimmed */     
3246         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3247 }
3248
3249 void
3250 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
3251                                           ModestWindow *window)
3252 {
3253         g_return_if_fail (MODEST_IS_WINDOW (window));
3254
3255         /* Update dimmed */     
3256         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3257 }
3258
3259 void
3260 modest_ui_actions_on_view_menu_activated (GtkAction *action,
3261                                           ModestWindow *window)
3262 {
3263         g_return_if_fail (MODEST_IS_WINDOW (window));
3264
3265         /* Update dimmed */     
3266         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3267 }
3268
3269 void
3270 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
3271                                           ModestWindow *window)
3272 {
3273         g_return_if_fail (MODEST_IS_WINDOW (window));
3274
3275         /* Update dimmed */     
3276         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3277 }
3278
3279 void
3280 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
3281                                           ModestWindow *window)
3282 {
3283         g_return_if_fail (MODEST_IS_WINDOW (window));
3284
3285         /* Update dimmed */     
3286         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3287 }
3288
3289 void
3290 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
3291                                                  ModestWindow *window)
3292 {
3293         g_return_if_fail (MODEST_IS_WINDOW (window));
3294
3295         /* Update dimmed */     
3296         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3297 }
3298
3299 void
3300 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
3301                                                      ModestWindow *window)
3302 {
3303         g_return_if_fail (MODEST_IS_WINDOW (window));
3304
3305         /* Update dimmed */     
3306         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3307 }
3308
3309 void
3310 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
3311                                                      ModestWindow *window)
3312 {
3313         g_return_if_fail (MODEST_IS_WINDOW (window));
3314
3315         /* Update dimmed */     
3316         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3317 }
3318
3319 void
3320 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
3321 {
3322         g_return_if_fail (MODEST_IS_WINDOW (window));
3323
3324         /* Update dimmed */     
3325         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
3326 }
3327
3328 void
3329 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
3330 {
3331         g_return_if_fail (MODEST_IS_WINDOW (window));
3332
3333         modest_platform_show_search_messages (GTK_WINDOW (window));
3334 }
3335
3336 void     
3337 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
3338 {
3339         g_return_if_fail (MODEST_IS_WINDOW (win));
3340         modest_platform_show_addressbook (GTK_WINDOW (win));
3341 }
3342
3343
3344 void
3345 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
3346                                           ModestWindow *window)
3347 {
3348         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3349
3350         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
3351 }
3352
3353 static void 
3354 _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
3355                                    ModestMailOperationState *state,
3356                                    gpointer user_data)
3357 {
3358         g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
3359
3360         /* Set send/receive operation finished */       
3361         if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3362                 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));
3363         
3364 }
3365
3366