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