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