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