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