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