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