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