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