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