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