2007-07-10 Johannes Schmid <johannes.schmid@openismus.com>
[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         TnyMsg *new_draft = NULL;
1843
1844         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1845         
1846         data = modest_msg_edit_window_get_msg_data (edit_window);
1847
1848         account_mgr = modest_runtime_get_account_mgr();
1849         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1850         if (!account_name) 
1851                 account_name = modest_account_mgr_get_default_account (account_mgr);
1852         if (!account_name) {
1853                 g_printerr ("modest: no account found\n");
1854                 modest_msg_edit_window_free_msg_data (edit_window, data);
1855                 return;
1856         }
1857
1858         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1859                 account_name = g_strdup (data->account_name);
1860         }
1861
1862         transport_account =
1863                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1864                                       (modest_runtime_get_account_store(),
1865                                        account_name,
1866                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1867         if (!transport_account) {
1868                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1869                 g_free (account_name);
1870                 modest_msg_edit_window_free_msg_data (edit_window, data);
1871                 return;
1872         }
1873         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1874
1875         /* Create the mail operation */         
1876         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
1877         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1878
1879         new_draft = modest_mail_operation_save_to_drafts (mail_operation,
1880                                                           transport_account,
1881                                                           data->draft_msg,
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         modest_msg_edit_window_set_draft (edit_window, new_draft);
1900         if (new_draft != NULL)
1901                 g_object_unref (new_draft);
1902
1903         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
1904         modest_platform_information_banner (NULL, NULL, info_text);
1905         g_free (info_text);
1906 }
1907
1908 /* For instance, when clicking the Send toolbar button when editing a message: */
1909 void
1910 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1911 {
1912         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1913
1914         if (!modest_msg_edit_window_check_names (edit_window))
1915                 return;
1916         
1917         /* Offer the connection dialog, if necessary: */        
1918         if (!modest_platform_connect_and_wait (GTK_WINDOW (edit_window)))
1919                 return;
1920         
1921         /* FIXME: Code added just for testing. The final version will
1922            use the send queue provided by tinymail and some
1923            classifier */
1924         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
1925         gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1926         if (!account_name) 
1927                 account_name = modest_account_mgr_get_default_account (account_mgr);
1928                 
1929         if (!account_name) {
1930                 g_printerr ("modest: no account found\n");
1931                 return;
1932         }
1933         
1934         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
1935
1936         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1937                 account_name = g_strdup (data->account_name);
1938         }
1939         
1940         /* Get the currently-active transport account for this modest account: */
1941         TnyTransportAccount *transport_account =
1942                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
1943                                       (modest_runtime_get_account_store(),
1944                                        account_name));
1945         if (!transport_account) {
1946                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1947                 g_free (account_name);
1948                 modest_msg_edit_window_free_msg_data (edit_window, data);
1949                 return;
1950         }
1951         
1952         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
1953
1954         /* mail content checks and dialogs */
1955         if (data->subject == NULL || data->subject[0] == '\0') {
1956                 GtkResponseType response;
1957                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1958                                                                     _("mcen_nc_subject_is_empty_send"));
1959                 if (response == GTK_RESPONSE_CANCEL) {
1960                         g_free (account_name);
1961                         return;
1962                 }
1963         }
1964
1965         if (data->plain_body == NULL || data->plain_body[0] == '\0') {
1966                 GtkResponseType response;
1967                 gchar *note_message;
1968                 gchar *note_subject = data->subject;
1969                 if (note_subject == NULL || note_subject[0] == '\0')
1970                         note_subject = _("mail_va_no_subject");
1971                 note_message = g_strdup_printf (_("emev_ni_ui_smtp_message_null"), note_subject);
1972                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1973                                                                     note_message);
1974                 g_free (note_message);
1975                 if (response == GTK_RESPONSE_CANCEL) {
1976                         g_free (account_name);
1977                         return;
1978                 }
1979         }
1980
1981         modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
1982
1983         /* Create the mail operation */
1984         ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
1985         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1986
1987         modest_mail_operation_send_new_mail (mail_operation,
1988                                              transport_account,
1989                                              data->draft_msg,
1990                                              from,
1991                                              data->to, 
1992                                              data->cc, 
1993                                              data->bcc,
1994                                              data->subject, 
1995                                              data->plain_body, 
1996                                              data->html_body,
1997                                              data->attachments,
1998                                              data->priority_flags);
1999                                              
2000         /* Free data: */
2001         g_free (from);
2002         g_free (account_name);
2003         g_object_unref (G_OBJECT (transport_account));
2004         g_object_unref (G_OBJECT (mail_operation));
2005
2006         modest_msg_edit_window_free_msg_data (edit_window, data);
2007         modest_msg_edit_window_set_sent (edit_window, TRUE);
2008
2009         /* Save settings and close the window: */
2010         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2011 }
2012
2013 void 
2014 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2015                                   ModestMsgEditWindow *window)
2016 {
2017         ModestMsgEditFormatState *format_state = NULL;
2018
2019         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2020         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2021
2022         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2023                 return;
2024
2025         format_state = modest_msg_edit_window_get_format_state (window);
2026         g_return_if_fail (format_state != NULL);
2027
2028         format_state->bold = gtk_toggle_action_get_active (action);
2029         modest_msg_edit_window_set_format_state (window, format_state);
2030         g_free (format_state);
2031         
2032 }
2033
2034 void 
2035 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2036                                      ModestMsgEditWindow *window)
2037 {
2038         ModestMsgEditFormatState *format_state = NULL;
2039
2040         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2041         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2042
2043         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2044                 return;
2045
2046         format_state = modest_msg_edit_window_get_format_state (window);
2047         g_return_if_fail (format_state != NULL);
2048
2049         format_state->italics = gtk_toggle_action_get_active (action);
2050         modest_msg_edit_window_set_format_state (window, format_state);
2051         g_free (format_state);
2052         
2053 }
2054
2055 void 
2056 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2057                                      ModestMsgEditWindow *window)
2058 {
2059         ModestMsgEditFormatState *format_state = NULL;
2060
2061         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2062         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2063
2064         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2065                 return;
2066
2067         format_state = modest_msg_edit_window_get_format_state (window);
2068         g_return_if_fail (format_state != NULL);
2069
2070         format_state->bullet = gtk_toggle_action_get_active (action);
2071         modest_msg_edit_window_set_format_state (window, format_state);
2072         g_free (format_state);
2073         
2074 }
2075
2076 void 
2077 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2078                                      GtkRadioAction *selected,
2079                                      ModestMsgEditWindow *window)
2080 {
2081         ModestMsgEditFormatState *format_state = NULL;
2082         GtkJustification value;
2083
2084         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2085
2086         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2087                 return;
2088
2089         value = gtk_radio_action_get_current_value (selected);
2090
2091         format_state = modest_msg_edit_window_get_format_state (window);
2092         g_return_if_fail (format_state != NULL);
2093
2094         format_state->justification = value;
2095         modest_msg_edit_window_set_format_state (window, format_state);
2096         g_free (format_state);
2097 }
2098
2099 void 
2100 modest_ui_actions_on_select_editor_color (GtkAction *action,
2101                                           ModestMsgEditWindow *window)
2102 {
2103         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2104         g_return_if_fail (GTK_IS_ACTION (action));
2105
2106         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2107                 return;
2108
2109         modest_msg_edit_window_select_color (window);
2110 }
2111
2112 void 
2113 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2114                                                      ModestMsgEditWindow *window)
2115 {
2116         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2117         g_return_if_fail (GTK_IS_ACTION (action));
2118
2119         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2120                 return;
2121
2122         modest_msg_edit_window_select_background_color (window);
2123 }
2124
2125 void 
2126 modest_ui_actions_on_insert_image (GtkAction *action,
2127                                    ModestMsgEditWindow *window)
2128 {
2129         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2130         g_return_if_fail (GTK_IS_ACTION (action));
2131
2132         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2133                 return;
2134
2135         modest_msg_edit_window_insert_image (window);
2136 }
2137
2138 void 
2139 modest_ui_actions_on_attach_file (GtkAction *action,
2140                                   ModestMsgEditWindow *window)
2141 {
2142         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2143         g_return_if_fail (GTK_IS_ACTION (action));
2144
2145         modest_msg_edit_window_attach_file (window);
2146 }
2147
2148 void 
2149 modest_ui_actions_on_remove_attachments (GtkAction *action,
2150                                          ModestMsgEditWindow *window)
2151 {
2152         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2153         g_return_if_fail (GTK_IS_ACTION (action));
2154
2155         modest_msg_edit_window_remove_attachments (window, NULL);
2156 }
2157
2158 static void
2159 modest_ui_actions_new_folder_error_handler (ModestMailOperation *mail_op,
2160                                             gpointer user_data)
2161 {
2162         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2163
2164         /* TODO: Note that folder creation might go wrong due to other
2165          * failures such as when the parent folder is non-writable. We can
2166          * query a GError* with modest_mail_operation_get_error(), but the
2167          * the error code (from tinymail) does not give us a clue about what
2168          * has gone wrong. We might use the error->message but it might come
2169          * from camel and not be suitable to show to the user directly. */
2170         modest_platform_information_banner (GTK_WIDGET (window), NULL,
2171                                             _CS("ckdg_ib_folder_already_exists"));
2172
2173 /*      modest_platform_information_banner (GTK_WIDGET (window), NULL,
2174                                             modest_mail_operation_get_error (mail_op)->message);*/
2175 }
2176
2177 void 
2178 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2179 {
2180         TnyFolderStore *parent_folder;
2181         GtkWidget *folder_view;
2182         
2183         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2184
2185         folder_view = modest_main_window_get_child_widget (main_window,
2186                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2187         if (!folder_view)
2188                 return;
2189
2190         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2191         
2192         if (parent_folder) {
2193                 gboolean finished = FALSE;
2194                 gint result;
2195                 gchar *folder_name = NULL, *suggested_name = NULL;
2196
2197                 /* Run the new folder dialog */
2198                 while (!finished) {
2199                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (main_window),
2200                                                                         parent_folder,
2201                                                                         suggested_name,
2202                                                                         &folder_name);
2203
2204                         g_free (suggested_name);
2205                         suggested_name = NULL;
2206
2207                         if (result == GTK_RESPONSE_REJECT) {
2208                                 finished = TRUE;
2209                         } else {
2210                                 ModestMailOperation *mail_op;
2211                                 TnyFolder *new_folder = NULL;
2212
2213                                 mail_op  = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2214                                                                                           G_OBJECT(main_window),
2215                                                                                           modest_ui_actions_new_folder_error_handler,
2216                                                                                           main_window);
2217
2218                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2219                                                                  mail_op);
2220                                 new_folder = modest_mail_operation_create_folder (mail_op,
2221                                                                                   parent_folder,
2222                                                                                   (const gchar *) folder_name);
2223                                 if (new_folder) {
2224                                         g_object_unref (new_folder);
2225                                         finished = TRUE;
2226                                 }
2227                                 g_object_unref (mail_op);
2228                         }
2229
2230                         suggested_name = folder_name;
2231                         folder_name = NULL;
2232                 }
2233
2234                 g_object_unref (parent_folder);
2235         }
2236 }
2237
2238 static void
2239 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2240                                                gpointer user_data)
2241 {
2242         GObject *win = modest_mail_operation_get_source (mail_op);
2243         const GError *error = NULL;
2244         const gchar *message = NULL;
2245         
2246         /* Get error message */
2247         error = modest_mail_operation_get_error (mail_op);
2248         if (error != NULL && error->message != NULL) {
2249                 message = error->message;
2250         } else {
2251                 message = _("!!! FIXME: Unable to rename");
2252         }
2253         
2254         /* Show notification dialog */
2255         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
2256         g_object_unref (win);
2257 }
2258
2259 void 
2260 modest_ui_actions_on_rename_folder (GtkAction *action,
2261                                      ModestMainWindow *main_window)
2262 {
2263         TnyFolderStore *folder;
2264         GtkWidget *folder_view;
2265         GtkWidget *header_view; 
2266
2267         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2268
2269         folder_view = modest_main_window_get_child_widget (main_window,
2270                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2271         if (!folder_view)
2272                 return;
2273
2274         header_view = modest_main_window_get_child_widget (main_window,
2275                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2276         
2277         if (!header_view)
2278                 return;
2279
2280         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2281
2282         /* Offer the connection dialog if necessary: */
2283         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2284                 g_object_unref (G_OBJECT (folder));
2285                 return;
2286         }
2287
2288         
2289         if (folder && TNY_IS_FOLDER (folder)) {
2290                 gchar *folder_name;
2291                 gint response;
2292                 const gchar *current_name;
2293
2294                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2295                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), NULL,
2296                                                                      current_name, &folder_name);
2297
2298                 if (response == GTK_RESPONSE_ACCEPT && strlen (folder_name) > 0) {
2299                         ModestMailOperation *mail_op;
2300
2301                         mail_op = 
2302                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO, 
2303                                                                                G_OBJECT(main_window),
2304                                                                                modest_ui_actions_rename_folder_error_handler,
2305                                                                                NULL);
2306
2307
2308                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2309                                                          mail_op);
2310
2311                         modest_header_view_clear (MODEST_HEADER_VIEW (header_view));
2312
2313                         modest_mail_operation_rename_folder (mail_op,
2314                                                              TNY_FOLDER (folder),
2315                                                              (const gchar *) folder_name);
2316
2317                         g_object_unref (mail_op);
2318                         g_free (folder_name);
2319                 }
2320                 g_object_unref (folder);
2321         }
2322 }
2323
2324 static void
2325 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2326                                                gpointer user_data)
2327 {
2328         GObject *win = modest_mail_operation_get_source (mail_op);
2329
2330         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2331                                                 _("mail_in_ui_folder_delete_error"));
2332         g_object_unref (win);
2333 }
2334
2335 static void
2336 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2337 {
2338         TnyFolderStore *folder;
2339         GtkWidget *folder_view;
2340         gint response;
2341         gchar *message;
2342         
2343         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2344
2345         folder_view = modest_main_window_get_child_widget (main_window,
2346                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2347         if (!folder_view)
2348                 return;
2349
2350         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2351
2352         /* Show an error if it's an account */
2353         if (!TNY_IS_FOLDER (folder)) {
2354                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2355                                                         _("mail_in_ui_folder_delete_error"));
2356                 g_object_unref (G_OBJECT (folder));
2357                 return ;
2358         }
2359
2360         /* Offer the connection dialog if necessary: */
2361         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2362                 g_object_unref (G_OBJECT (folder));
2363                 return;
2364         }
2365
2366         /* Ask the user */      
2367         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2368                                     tny_folder_get_name (TNY_FOLDER (folder)));
2369         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2370                                                             (const gchar *) message);
2371         g_free (message);
2372
2373         if (response == GTK_RESPONSE_OK) {
2374                 ModestMailOperation *mail_op = 
2375                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
2376                                                                        G_OBJECT(main_window),
2377                                                                        modest_ui_actions_delete_folder_error_handler,
2378                                                                        NULL);
2379
2380                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2381                                                  mail_op);
2382                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2383                 g_object_unref (G_OBJECT (mail_op));
2384         }
2385
2386         g_object_unref (G_OBJECT (folder));
2387 }
2388
2389 void 
2390 modest_ui_actions_on_delete_folder (GtkAction *action,
2391                                      ModestMainWindow *main_window)
2392 {
2393         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2394
2395         delete_folder (main_window, FALSE);
2396 }
2397
2398 void 
2399 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2400 {
2401         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2402         
2403         delete_folder (main_window, TRUE);
2404 }
2405
2406 void
2407 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2408                                          const gchar* server_account_name,
2409                                          gchar **username,
2410                                          gchar **password, 
2411                                          gboolean *cancel, 
2412                                          gboolean *remember,
2413                                          ModestMainWindow *main_window)
2414 {
2415         g_return_if_fail(server_account_name);
2416         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2417         
2418         /* Initalize output parameters: */
2419         if (cancel)
2420                 *cancel = FALSE;
2421                 
2422         if (remember)
2423                 *remember = TRUE;
2424                 
2425 #ifdef MODEST_PLATFORM_MAEMO
2426         /* Maemo uses a different (awkward) button order,
2427          * It should probably just use gtk_alternative_dialog_button_order ().
2428          */
2429         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2430                                               NULL,
2431                                               GTK_DIALOG_MODAL,
2432                                               GTK_STOCK_OK,
2433                                               GTK_RESPONSE_ACCEPT,
2434                                               GTK_STOCK_CANCEL,
2435                                               GTK_RESPONSE_REJECT,
2436                                               NULL);
2437 #else
2438         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2439                                               NULL,
2440                                               GTK_DIALOG_MODAL,
2441                                               GTK_STOCK_CANCEL,
2442                                               GTK_RESPONSE_REJECT,
2443                                               GTK_STOCK_OK,
2444                                               GTK_RESPONSE_ACCEPT,
2445                                               NULL);
2446 #endif /* MODEST_PLATFORM_MAEMO */
2447
2448         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2449         
2450         gchar *server_name = modest_server_account_get_hostname (
2451                 modest_runtime_get_account_mgr(), server_account_name);
2452         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2453                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2454                 *cancel = TRUE;
2455                 return;
2456         }
2457         
2458         /* This causes a warning because the logical ID has no %s in it, 
2459          * though the translation does, but there is not much we can do about that: */
2460         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2461         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2462                             FALSE, FALSE, 0);
2463         g_free (txt);
2464         g_free (server_name);
2465         server_name = NULL;
2466
2467         /* username: */
2468         gchar *initial_username = modest_server_account_get_username (
2469                 modest_runtime_get_account_mgr(), server_account_name);
2470         
2471         GtkWidget *entry_username = gtk_entry_new ();
2472         if (initial_username)
2473                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2474         /* Dim this if a connection has ever succeeded with this username,
2475          * as per the UI spec: */
2476         const gboolean username_known = 
2477                 modest_server_account_get_username_has_succeeded(
2478                         modest_runtime_get_account_mgr(), server_account_name);
2479         gtk_widget_set_sensitive (entry_username, !username_known);
2480         
2481 #ifdef MODEST_PLATFORM_MAEMO
2482         /* Auto-capitalization is the default, so let's turn it off: */
2483         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2484         
2485         /* Create a size group to be used by all captions.
2486          * Note that HildonCaption does not create a default size group if we do not specify one.
2487          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2488         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2489         
2490         GtkWidget *caption = hildon_caption_new (sizegroup, 
2491                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2492         gtk_widget_show (entry_username);
2493         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2494                 FALSE, FALSE, MODEST_MARGIN_HALF);
2495         gtk_widget_show (caption);
2496 #else 
2497         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2498                             TRUE, FALSE, 0);
2499 #endif /* MODEST_PLATFORM_MAEMO */      
2500                             
2501         /* password: */
2502         GtkWidget *entry_password = gtk_entry_new ();
2503         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2504         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2505         
2506 #ifdef MODEST_PLATFORM_MAEMO
2507         /* Auto-capitalization is the default, so let's turn it off: */
2508         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2509                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2510         
2511         caption = hildon_caption_new (sizegroup, 
2512                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2513         gtk_widget_show (entry_password);
2514         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2515                 FALSE, FALSE, MODEST_MARGIN_HALF);
2516         gtk_widget_show (caption);
2517         g_object_unref (sizegroup);
2518 #else 
2519         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2520                             TRUE, FALSE, 0);
2521 #endif /* MODEST_PLATFORM_MAEMO */      
2522                                 
2523 /* This is not in the Maemo UI spec:
2524         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2525         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2526                             TRUE, FALSE, 0);
2527 */
2528
2529         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2530         
2531         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2532                 if (username) {
2533                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2534                         
2535                         modest_server_account_set_username (
2536                                  modest_runtime_get_account_mgr(), server_account_name, 
2537                                  *username);
2538                                  
2539                         const gboolean username_was_changed = 
2540                                 (strcmp (*username, initial_username) != 0);
2541                         if (username_was_changed) {
2542                                 g_warning ("%s: tinymail does not yet support changing the "
2543                                         "username in the get_password() callback.\n", __FUNCTION__);
2544                         }
2545                 }
2546                         
2547                 if (password) {
2548                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2549                         
2550                         /* We do not save the password in the configuration, 
2551                          * because this function is only called for passwords that should 
2552                          * not be remembered:
2553                         modest_server_account_set_password (
2554                                  modest_runtime_get_account_mgr(), server_account_name, 
2555                                  *password);
2556                         */
2557                 }
2558                 
2559                 if (cancel)
2560                         *cancel   = FALSE;
2561                         
2562         } else {
2563                 if (username)
2564                         *username = NULL;
2565                         
2566                 if (password)
2567                         *password = NULL;
2568                         
2569                 if (cancel)
2570                         *cancel   = TRUE;
2571         }
2572
2573 /* This is not in the Maemo UI spec:
2574         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2575                 *remember = TRUE;
2576         else
2577                 *remember = FALSE;
2578 */
2579
2580         gtk_widget_destroy (dialog);
2581         
2582         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2583 }
2584
2585 void
2586 modest_ui_actions_on_cut (GtkAction *action,
2587                           ModestWindow *window)
2588 {
2589         GtkWidget *focused_widget;
2590
2591         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2592         if (GTK_IS_EDITABLE (focused_widget)) {
2593                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2594         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2595                 GtkTextBuffer *buffer;
2596                 GtkClipboard *clipboard;
2597
2598                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2599                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2600                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2601                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2602         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2603                 modest_header_view_cut_selection (MODEST_HEADER_VIEW (focused_widget));
2604         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2605                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2606         }
2607 }
2608
2609 void
2610 modest_ui_actions_on_copy (GtkAction *action,
2611                            ModestWindow *window)
2612 {
2613         GtkClipboard *clipboard;
2614         GtkWidget *focused_widget;
2615
2616         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2617         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2618
2619         if (GTK_IS_LABEL (focused_widget)) {
2620                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2621         } else if (GTK_IS_EDITABLE (focused_widget)) {
2622                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2623         } else if (GTK_IS_HTML (focused_widget)) {
2624                 gtk_html_copy (GTK_HTML (focused_widget));
2625         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2626                 GtkTextBuffer *buffer;
2627                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2628                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2629                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2630         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2631                 TnyList *header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (focused_widget));
2632                 TnyIterator *iter = tny_list_create_iterator (header_list);
2633                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2634                 TnyFolder *folder = tny_header_get_folder (header);
2635                 TnyAccount *account = tny_folder_get_account (folder);
2636                 const gchar *proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2637                 /* If it's POP then ask */
2638                 gboolean ask = (modest_protocol_info_get_transport_store_protocol (proto_str) == 
2639                        MODEST_PROTOCOL_STORE_POP) ? TRUE : FALSE;
2640                 g_object_unref (account);
2641                 g_object_unref (folder);
2642                 g_object_unref (header);
2643                 g_object_unref (iter);
2644                 
2645                 /* Check that the messages have been previously downloaded */
2646                 gboolean continue_download = TRUE;
2647                 if (ask)
2648                         continue_download = download_uncached_messages (header_list, GTK_WINDOW (window), FALSE);
2649                 if (continue_download)
2650                         modest_header_view_copy_selection (MODEST_HEADER_VIEW (focused_widget));
2651                 g_object_unref (header_list);
2652         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2653                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
2654         }    
2655
2656         /* Show information banner */
2657         modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
2658         
2659 }
2660
2661 void
2662 modest_ui_actions_on_undo (GtkAction *action,
2663                            ModestWindow *window)
2664 {
2665         ModestEmailClipboard *clipboard = NULL;
2666
2667         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2668                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2669         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2670                 /* Clear clipboard source */
2671                 clipboard = modest_runtime_get_email_clipboard ();
2672                 modest_email_clipboard_clear (clipboard);               
2673         }
2674         else {
2675                 g_return_if_reached ();
2676         }
2677 }
2678
2679 void
2680 modest_ui_actions_on_redo (GtkAction *action,
2681                            ModestWindow *window)
2682 {
2683         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2684                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
2685         }
2686         else {
2687                 g_return_if_reached ();
2688         }
2689 }
2690
2691
2692 static void
2693 paste_msgs_cb (const GObject *object, gpointer user_data)
2694 {
2695         g_return_if_fail (MODEST_IS_MAIN_WINDOW (object));
2696         g_return_if_fail (GTK_IS_WIDGET (user_data));
2697         
2698         /* destroy information note */
2699         gtk_widget_destroy (GTK_WIDGET(user_data));
2700 }
2701
2702 void
2703 modest_ui_actions_on_paste (GtkAction *action,
2704                             ModestWindow *window)
2705 {
2706         GtkWidget *focused_widget = NULL;
2707         GtkWidget *inf_note = NULL;
2708         ModestMailOperation *mail_op = NULL;
2709
2710         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2711         if (GTK_IS_EDITABLE (focused_widget)) {
2712                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
2713         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2714                 GtkTextBuffer *buffer;
2715                 GtkClipboard *clipboard;
2716
2717                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2718                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2719                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
2720         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2721                 ModestEmailClipboard *clipboard = NULL;
2722                 TnyFolder *src_folder = NULL;
2723                 TnyFolderStore *folder_store = NULL;
2724                 TnyList *data = NULL;           
2725                 gboolean delete = FALSE;
2726                 
2727                 /* Check clipboard source */
2728                 clipboard = modest_runtime_get_email_clipboard ();
2729                 if (modest_email_clipboard_cleared (clipboard)) 
2730                         return;
2731                 
2732                 /* Get elements to paste */
2733                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
2734
2735                 /* Create a new mail operation */
2736                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
2737                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2738                                                  mail_op);
2739                 
2740                 /* Get destination folder */
2741                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
2742
2743                 /* Launch notification */
2744                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
2745                                                              _CS("ckct_nw_pasting"));
2746                 if (inf_note != NULL)  {
2747                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
2748                         gtk_widget_show (GTK_WIDGET(inf_note));
2749                 }
2750
2751                 /* transfer messages  */
2752                 if (data != NULL) {
2753                         modest_mail_operation_xfer_msgs (mail_op, 
2754                                                          data,
2755                                                          TNY_FOLDER (folder_store),
2756                                                          delete,
2757                                                          paste_msgs_cb,
2758                                                          inf_note);
2759                         
2760                 } else if (src_folder != NULL) {                        
2761                         modest_mail_operation_xfer_folder (mail_op, 
2762                                                            src_folder,
2763                                                            folder_store,
2764                                                            delete,
2765                                                            paste_msgs_cb,
2766                                                            inf_note);
2767                 }
2768
2769                 /* Free */
2770                 if (data != NULL) 
2771                         g_object_unref (data);
2772                 if (src_folder != NULL) 
2773                         g_object_unref (src_folder);
2774                 if (folder_store != NULL) 
2775                         g_object_unref (folder_store);
2776         }
2777 }
2778
2779
2780 void
2781 modest_ui_actions_on_select_all (GtkAction *action,
2782                                  ModestWindow *window)
2783 {
2784         GtkWidget *focused_widget;
2785
2786         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2787         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
2788                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
2789         } else if (GTK_IS_LABEL (focused_widget)) {
2790                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
2791         } else if (GTK_IS_EDITABLE (focused_widget)) {
2792                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
2793         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2794                 GtkTextBuffer *buffer;
2795                 GtkTextIter start, end;
2796
2797                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2798                 gtk_text_buffer_get_start_iter (buffer, &start);
2799                 gtk_text_buffer_get_end_iter (buffer, &end);
2800                 gtk_text_buffer_select_range (buffer, &start, &end);
2801         } else if (GTK_IS_HTML (focused_widget)) {
2802                 gtk_html_select_all (GTK_HTML (focused_widget));
2803         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2804                 GtkWidget *header_view = focused_widget;
2805                 GtkTreeSelection *selection = NULL;
2806                 
2807                 if (!(MODEST_IS_HEADER_VIEW (focused_widget)))
2808                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
2809                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2810                                 
2811                 /* Select all messages */
2812                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
2813                 gtk_tree_selection_select_all (selection);
2814
2815                 /* Set focuse on header view */
2816                 gtk_widget_grab_focus (header_view);
2817         }
2818
2819 }
2820
2821 void
2822 modest_ui_actions_on_mark_as_read (GtkAction *action,
2823                                    ModestWindow *window)
2824 {       
2825         g_return_if_fail (MODEST_IS_WINDOW(window));
2826                 
2827         /* Mark each header as read */
2828         do_headers_action (window, headers_action_mark_as_read, NULL);
2829 }
2830
2831 void
2832 modest_ui_actions_on_mark_as_unread (GtkAction *action,
2833                                      ModestWindow *window)
2834 {       
2835         g_return_if_fail (MODEST_IS_WINDOW(window));
2836                 
2837         /* Mark each header as read */
2838         do_headers_action (window, headers_action_mark_as_unread, NULL);
2839 }
2840
2841 void
2842 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
2843                                   GtkRadioAction *selected,
2844                                   ModestWindow *window)
2845 {
2846         gint value;
2847
2848         value = gtk_radio_action_get_current_value (selected);
2849         if (MODEST_IS_WINDOW (window)) {
2850                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
2851         }
2852 }
2853
2854 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
2855                                                         GtkRadioAction *selected,
2856                                                         ModestWindow *window)
2857 {
2858         TnyHeaderFlags flags;
2859         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2860
2861         flags = gtk_radio_action_get_current_value (selected);
2862         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
2863 }
2864
2865 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
2866                                                            GtkRadioAction *selected,
2867                                                            ModestWindow *window)
2868 {
2869         gint file_format;
2870
2871         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2872
2873         file_format = gtk_radio_action_get_current_value (selected);
2874         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
2875 }
2876
2877
2878 void     
2879 modest_ui_actions_on_zoom_plus (GtkAction *action,
2880                                 ModestWindow *window)
2881 {
2882         g_return_if_fail (MODEST_IS_WINDOW (window));
2883
2884         modest_window_zoom_plus (MODEST_WINDOW (window));
2885 }
2886
2887 void     
2888 modest_ui_actions_on_zoom_minus (GtkAction *action,
2889                                  ModestWindow *window)
2890 {
2891         g_return_if_fail (MODEST_IS_WINDOW (window));
2892
2893         modest_window_zoom_minus (MODEST_WINDOW (window));
2894 }
2895
2896 void     
2897 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
2898                                            ModestWindow *window)
2899 {
2900         ModestWindowMgr *mgr;
2901         gboolean fullscreen, active;
2902         g_return_if_fail (MODEST_IS_WINDOW (window));
2903
2904         mgr = modest_runtime_get_window_mgr ();
2905
2906         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
2907         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2908
2909         if (active != fullscreen) {
2910                 modest_window_mgr_set_fullscreen_mode (mgr, active);
2911                 gtk_window_present (GTK_WINDOW (window));
2912         }
2913 }
2914
2915 void
2916 modest_ui_actions_on_change_fullscreen (GtkAction *action,
2917                                         ModestWindow *window)
2918 {
2919         ModestWindowMgr *mgr;
2920         gboolean fullscreen;
2921
2922         g_return_if_fail (MODEST_IS_WINDOW (window));
2923
2924         mgr = modest_runtime_get_window_mgr ();
2925         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2926         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
2927
2928         gtk_window_present (GTK_WINDOW (window));
2929 }
2930
2931 /* 
2932  * Used by modest_ui_actions_on_details to call do_headers_action 
2933  */
2934 static void
2935 headers_action_show_details (TnyHeader *header, 
2936                              ModestWindow *window,
2937                              gpointer user_data)
2938
2939 {
2940         GtkWidget *dialog;
2941         
2942         /* Create dialog */
2943         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
2944
2945         /* Run dialog */
2946         gtk_widget_show_all (dialog);
2947         gtk_dialog_run (GTK_DIALOG (dialog));
2948
2949         gtk_widget_destroy (dialog);
2950 }
2951
2952 /*
2953  * Show the folder details in a ModestDetailsDialog widget
2954  */
2955 static void
2956 show_folder_details (TnyFolder *folder, 
2957                      GtkWindow *window)
2958 {
2959         GtkWidget *dialog;
2960         
2961         /* Create dialog */
2962         dialog = modest_details_dialog_new_with_folder (window, folder);
2963
2964         /* Run dialog */
2965         gtk_widget_show_all (dialog);
2966         gtk_dialog_run (GTK_DIALOG (dialog));
2967
2968         gtk_widget_destroy (dialog);
2969 }
2970
2971 /*
2972  * Show the header details in a ModestDetailsDialog widget
2973  */
2974 void     
2975 modest_ui_actions_on_details (GtkAction *action, 
2976                               ModestWindow *win)
2977 {
2978         TnyList * headers_list;
2979         TnyIterator *iter;
2980         TnyHeader *header;              
2981
2982         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
2983                 TnyMsg *msg;
2984
2985                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
2986                 if (!msg)
2987                         return;
2988                 g_object_unref (msg);           
2989
2990                 headers_list = get_selected_headers (win);
2991                 if (!headers_list)
2992                         return;
2993
2994                 iter = tny_list_create_iterator (headers_list);
2995
2996                 header = TNY_HEADER (tny_iterator_get_current (iter));
2997                 headers_action_show_details (header, win, NULL);
2998                 g_object_unref (header);
2999
3000                 g_object_unref (iter);
3001                 g_object_unref (headers_list);
3002
3003         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3004                 GtkWidget *folder_view, *header_view;
3005
3006                 /* Check which widget has the focus */
3007                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3008                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
3009                 if (gtk_widget_is_focus (folder_view)) {
3010                         TnyFolderStore *folder_store
3011                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3012                         if (!folder_store) {
3013                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3014                                 return; 
3015                         }
3016                         /* Show only when it's a folder */
3017                         /* This function should not be called for account items, 
3018                          * because we dim the menu item for them. */
3019                         if (TNY_IS_FOLDER (folder_store)) {
3020                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3021                         }
3022
3023                         g_object_unref (folder_store);
3024
3025                 } else {
3026                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3027                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3028                         /* Show details of each header */
3029                         do_headers_action (win, headers_action_show_details, header_view);
3030                 }
3031         }
3032 }
3033
3034 void     
3035 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3036                                      ModestMsgEditWindow *window)
3037 {
3038         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3039
3040         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3041 }
3042
3043 void     
3044 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3045                                       ModestMsgEditWindow *window)
3046 {
3047         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3048
3049         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3050 }
3051
3052 void
3053 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3054                                        ModestMainWindow *main_window)
3055 {
3056         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3057
3058         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3059                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3060         else
3061                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3062 }
3063
3064 void 
3065 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3066                                      ModestWindow *window)
3067 {
3068         gboolean active, fullscreen = FALSE;
3069         ModestWindowMgr *mgr;
3070
3071         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3072
3073         /* Check if we want to toggle the toolbar vuew in fullscreen
3074            or normal mode */
3075         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3076                      "ViewShowToolbarFullScreen")) {
3077                 fullscreen = TRUE;
3078         }
3079
3080         /* Toggle toolbar */
3081         mgr = modest_runtime_get_window_mgr ();
3082         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
3083 }
3084
3085 void     
3086 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3087                                            ModestMsgEditWindow *window)
3088 {
3089         modest_msg_edit_window_select_font (window);
3090 }
3091
3092 void
3093 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3094                                                   const gchar *display_name,
3095                                                   GtkWindow *window)
3096 {
3097         /* Do not change the application name if the widget has not
3098            the focus. This callback could be called even if the folder
3099            view has not the focus, because the handled signal could be
3100            emitted when the folder view is redrawn */
3101         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3102                 if (display_name)
3103                         gtk_window_set_title (window, display_name);
3104                 else
3105                         gtk_window_set_title (window, " ");
3106         }
3107 }
3108
3109 void
3110 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3111 {
3112         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3113         modest_msg_edit_window_select_contacts (window);
3114 }
3115
3116 void
3117 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3118 {
3119         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3120         modest_msg_edit_window_check_names (window);
3121 }
3122
3123
3124 static GtkWidget*
3125 create_move_to_dialog (GtkWindow *win,
3126                        GtkWidget *folder_view,
3127                        GtkWidget **tree_view)
3128 {
3129         GtkWidget *dialog, *scroll;
3130
3131         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3132                                               GTK_WINDOW (win),
3133                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3134                                               GTK_STOCK_OK,
3135                                               GTK_RESPONSE_ACCEPT,
3136                                               GTK_STOCK_CANCEL,
3137                                               GTK_RESPONSE_REJECT,
3138                                               NULL);
3139
3140         /* Create scrolled window */
3141         scroll = gtk_scrolled_window_new (NULL, NULL);
3142         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3143                                          GTK_POLICY_AUTOMATIC,
3144                                          GTK_POLICY_AUTOMATIC);
3145
3146         /* Create folder view */
3147         *tree_view = modest_platform_create_folder_view (NULL);
3148
3149         /* It could happen that we're trying to move a message from a
3150            window (msg window for example) after the main window was
3151            closed, so we can not just get the model of the folder
3152            view */
3153         if (MODEST_IS_FOLDER_VIEW (folder_view))
3154                 gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
3155                                          gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
3156         else
3157                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
3158                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3159
3160         modest_folder_view_show_non_move_folders(MODEST_FOLDER_VIEW (*tree_view), FALSE);
3161         
3162         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3163
3164         /* Add scroll to dialog */
3165         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
3166                             scroll, FALSE, FALSE, 0);
3167
3168         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3169
3170         /* Select INBOX or local account */
3171         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (*tree_view));
3172
3173         return dialog;
3174 }
3175
3176 /*
3177  * Returns TRUE if at least one of the headers of the list belongs to
3178  * a message that has been fully retrieved.
3179  */
3180 static gboolean
3181 has_retrieved_msgs (TnyList *list)
3182 {
3183         TnyIterator *iter;
3184         gboolean found = FALSE;
3185
3186         iter = tny_list_create_iterator (list);
3187         while (tny_iterator_is_done (iter) && !found) {
3188                 TnyHeader *header;
3189                 TnyHeaderFlags flags;
3190
3191                 header = TNY_HEADER (tny_iterator_get_current (iter));
3192                 flags = tny_header_get_flags (header);
3193                 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
3194                         found = TRUE;
3195
3196                 if (!found)
3197                         tny_iterator_next (iter);
3198         }
3199         g_object_unref (iter);
3200
3201         return found;
3202 }
3203
3204 /*
3205  * Shows a confirmation dialog to the user when we're moving messages
3206  * from a remote server to the local storage. Returns the dialog
3207  * response. If it's other kind of movement the it always returns
3208  * GTK_RESPONSE_OK
3209  */
3210 static gint
3211 msgs_move_to_confirmation (GtkWindow *win,
3212                            TnyFolder *dest_folder,
3213                            TnyList *headers)
3214 {
3215         gint response = GTK_RESPONSE_OK;
3216
3217         /* If the destination is a local folder */
3218         if (modest_tny_folder_is_local_folder (dest_folder)) {
3219                 TnyFolder *src_folder;
3220                 TnyIterator *iter;
3221                 TnyHeader *header;
3222
3223                 /* Get source folder */
3224                 iter = tny_list_create_iterator (headers);
3225                 header = TNY_HEADER (tny_iterator_get_current (iter));
3226                 src_folder = tny_header_get_folder (header);
3227                 g_object_unref (header);
3228                 g_object_unref (iter);
3229
3230                 /* if no src_folder, message may be an attahcment */
3231                 if (src_folder == NULL) 
3232                         return GTK_RESPONSE_CANCEL;
3233
3234                 /* If the source is a remote folder */
3235                 if (!modest_tny_folder_is_local_folder (src_folder)) {
3236                         const gchar *message;
3237                         
3238                         if (has_retrieved_msgs (headers))
3239                                 message = ngettext ("mcen_nc_move_retrieve", "mcen_nc_move_retrieves",
3240                                                     tny_list_get_length (headers));
3241                         else 
3242                                 message = ngettext ("mcen_nc_move_header", "mcen_nc_move_headers",
3243                                                     tny_list_get_length (headers));
3244
3245                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
3246                                                                             (const gchar *) message);
3247                 }
3248                 g_object_unref (src_folder);
3249         }
3250         return response;
3251 }
3252
3253
3254
3255 static void
3256 transfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
3257 {
3258         ModestMsgViewWindow *self = NULL;
3259         gboolean last, first;
3260
3261         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
3262         self = MODEST_MSG_VIEW_WINDOW (object);
3263         
3264         last = modest_msg_view_window_last_message_selected (self);
3265         first = modest_msg_view_window_first_message_selected (self);   
3266         if (last & first) {
3267                 /* No more messages to view, so close this window */
3268 /*              gboolean ret_value; */
3269 /*              g_signal_emit_by_name (G_OBJECT (self), "delete-event", NULL, &ret_value); */
3270                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
3271         } else if (last)
3272                 modest_msg_view_window_select_previous_message (self);
3273         else 
3274                 modest_msg_view_window_select_next_message (self);
3275 }
3276
3277 void
3278 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
3279                                              gpointer user_data)
3280 {
3281         GObject *win = modest_mail_operation_get_source (mail_op);
3282         const GError *error = NULL;
3283         const gchar *message = NULL;
3284         
3285         /* Get error message */
3286         error = modest_mail_operation_get_error (mail_op);
3287         if (error != NULL && error->message != NULL) {
3288                 message = error->message;
3289         } else {
3290                 message = _("mail_in_ui_folder_move_target_error");
3291         }
3292         
3293         /* Show notification dialog */
3294         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
3295         g_object_unref (win);
3296 }
3297
3298 void
3299 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
3300                                               gpointer user_data)
3301 {
3302         GObject *win = modest_mail_operation_get_source (mail_op);
3303         const GError *error = modest_mail_operation_get_error (mail_op);
3304
3305         g_return_if_fail (error != NULL);
3306         if (error->message != NULL)             
3307                 g_printerr ("modest: %s\n", error->message);
3308         else
3309                 g_printerr ("modest: unkonw error on send&receive operation");
3310
3311         /* Show error message */
3312 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
3313 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3314 /*                                                      _CS("sfil_ib_unable_to_receive")); */
3315 /*      else  */
3316 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3317 /*                                                      _CS("sfil_ib_unable_to_send")); */
3318         g_object_unref (win);
3319 }
3320
3321 static void
3322 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
3323                        TnyHeader *header, 
3324                        TnyMsg *msg, 
3325                        gpointer user_data)
3326 {
3327         TnyList *parts;
3328         TnyIterator *iter;
3329         gint pending_purges = 0;
3330         gboolean some_purged = FALSE;
3331         ModestWindow *win = MODEST_WINDOW (user_data);
3332
3333         /* If there was any error */
3334         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
3335                 return;
3336
3337         /* Once the message has been retrieved for purging, we check if
3338          * it's all ok for purging */
3339
3340         parts = tny_simple_list_new ();
3341         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
3342         iter = tny_list_create_iterator (parts);
3343
3344         while (!tny_iterator_is_done (iter)) {
3345                 TnyMimePart *part;
3346                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3347                 if (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)) {
3348                         if (tny_mime_part_is_purged (part))
3349                                 some_purged = TRUE;
3350                         else
3351                                 pending_purges++;
3352                 }
3353                 tny_iterator_next (iter);
3354         }
3355
3356         if (pending_purges>0) {
3357                 gint response;
3358                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
3359
3360                 if (response == GTK_RESPONSE_OK) {
3361                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
3362                         tny_iterator_first (iter);
3363                         while (!tny_iterator_is_done (iter)) {
3364                                 TnyMimePart *part;
3365                                 
3366                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3367                                 if (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))
3368                                         tny_mime_part_set_purged (part);
3369                                 tny_iterator_next (iter);
3370                         }
3371                         
3372                         tny_msg_rewrite_cache (msg);
3373                 }
3374         } else {
3375                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
3376         }
3377
3378         /* remove attachments */
3379         tny_iterator_first (iter);
3380         while (!tny_iterator_is_done (iter)) {
3381                 TnyMimePart *part;
3382                         
3383                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3384                 g_object_unref (part);
3385                 tny_iterator_next (iter);
3386         }
3387
3388         g_object_unref (iter);
3389         g_object_unref (parts);
3390 }
3391
3392 static void
3393 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
3394                                                      ModestMainWindow *win)
3395 {
3396         GtkWidget *header_view;
3397         TnyList *header_list;
3398         TnyIterator *iter;
3399         TnyHeader *header;
3400         TnyHeaderFlags flags;
3401         ModestWindow *msg_view_window =  NULL;
3402         gboolean found;
3403
3404         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3405
3406         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3407                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3408
3409         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
3410
3411         if (tny_list_get_length (header_list) == 1) {
3412                 iter = tny_list_create_iterator (header_list);
3413                 header = TNY_HEADER (tny_iterator_get_current (iter));
3414                 g_object_unref (iter);
3415         } else {
3416                 return;
3417         }
3418
3419         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
3420                                                           header, &msg_view_window);
3421         flags = tny_header_get_flags (header);
3422         if (!(flags & TNY_HEADER_FLAG_CACHED))
3423                 return;
3424         if (found) {
3425                 if (msg_view_window != NULL) 
3426                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
3427                 else {
3428                         /* do nothing; uid was registered before, so window is probably on it's way */
3429                         g_warning ("debug: header %p has already been registered", header);
3430                 }
3431         } else {
3432                 ModestMailOperation *mail_op = NULL;
3433                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header);
3434                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
3435                                                                          G_OBJECT (win),
3436                                                                          modest_ui_actions_get_msgs_full_error_handler,
3437                                                                          NULL);
3438                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3439                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
3440                 
3441                 g_object_unref (mail_op);
3442         }
3443         if (header)
3444                 g_object_unref (header);
3445         if (header_list)
3446                 g_object_unref (header_list);
3447 }
3448
3449 /*
3450  * UI handler for the "Move to" action when invoked from the
3451  * ModestMainWindow
3452  */
3453 static void 
3454 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
3455                                           ModestMainWindow *win)
3456 {
3457         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
3458         GtkWidget *header_view = NULL;
3459         gint result = 0;
3460         TnyFolderStore *folder_store = NULL;
3461         ModestMailOperation *mail_op = NULL;
3462
3463         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3464
3465         /* Get the folder view */
3466         folder_view = modest_main_window_get_child_widget (win,
3467                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
3468                                                            
3469         TnyFolderStore *src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3470         
3471         /* Offer the connection dialog if necessary, if the source folder is in a networked account: */
3472         if (!modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), src_folder)) {
3473                 if (src_folder) {
3474                         g_object_unref (src_folder);
3475                 }
3476                 
3477                 return;
3478         }
3479
3480         /* Get header view */
3481         header_view = modest_main_window_get_child_widget (win,
3482                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3483
3484         /* Create and run the dialog */
3485         dialog = create_move_to_dialog (GTK_WINDOW(win), folder_view, &tree_view);
3486         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
3487         result = gtk_dialog_run (GTK_DIALOG(dialog));
3488         modest_folder_view_show_non_move_folders(MODEST_FOLDER_VIEW (tree_view), TRUE);
3489         g_object_ref (tree_view);
3490
3491         /* We do this to save an indentation level ;-) */
3492         if (result != GTK_RESPONSE_ACCEPT)
3493                 goto end;
3494
3495         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
3496
3497         if (TNY_IS_ACCOUNT (folder_store) && 
3498             !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (folder_store))
3499                 goto end;
3500
3501         /* Offer the connection dialog if necessary: */
3502         if (!modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), folder_store)) {
3503                         goto end;
3504         }
3505
3506         /* Get folder or messages to transfer */
3507         if (gtk_widget_is_focus (folder_view)) {
3508                 
3509                 /* Clean folder on header view before moving it */
3510                 modest_header_view_clear (MODEST_HEADER_VIEW (header_view)); 
3511
3512                 if (TNY_IS_FOLDER (src_folder)) {
3513                         mail_op = 
3514                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3515                                                                        G_OBJECT(win),
3516                                                                        modest_ui_actions_move_folder_error_handler,
3517                                                                        NULL);
3518                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3519
3520                         modest_mail_operation_xfer_folder (mail_op, 
3521                                                            TNY_FOLDER (src_folder),
3522                                                            folder_store,
3523                                                            TRUE, NULL, NULL);
3524                         /* Unref mail operation */
3525                         g_object_unref (G_OBJECT (mail_op));
3526                 } else {
3527                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);       
3528                 }
3529         } else {
3530                 if (gtk_widget_is_focus (header_view)) {
3531                         TnyList *headers = NULL;
3532                         gint response = 0;
3533
3534                         /* TODO: Check for connection if the headers are on a network account. */
3535                         headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
3536
3537                         /* Ask for user confirmation */
3538                         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
3539                                                               TNY_FOLDER (folder_store), 
3540                                                               headers);
3541
3542                         /* Transfer messages */
3543                         if (response == GTK_RESPONSE_OK) {
3544                                 mail_op = 
3545                                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3546                                                                                        G_OBJECT(win),
3547                                                                                        modest_ui_actions_move_folder_error_handler,
3548                                                                                        NULL);
3549                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3550                                                                  mail_op);
3551
3552                                 modest_mail_operation_xfer_msgs (mail_op, 
3553                                                                  headers,
3554                                                                  TNY_FOLDER (folder_store),
3555                                                                  TRUE,
3556                                                                  NULL,
3557                                                                  NULL);
3558
3559                                 g_object_unref (G_OBJECT (mail_op));
3560                         }
3561                         g_object_unref (headers);
3562                 }
3563         }
3564         
3565  end:
3566     if (src_folder)
3567         g_object_unref (src_folder);
3568                         
3569         if (folder_store)
3570                 g_object_unref (folder_store);
3571
3572         gtk_widget_destroy (dialog);
3573 }
3574
3575
3576 /*
3577  * UI handler for the "Move to" action when invoked from the
3578  * ModestMsgViewWindow
3579  */
3580 static void 
3581 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
3582                                               ModestMsgViewWindow *win)
3583 {
3584         GtkWidget *dialog, *folder_view, *tree_view = NULL;
3585         gint result = 0;
3586         ModestMainWindow *main_window = NULL;
3587         TnyHeader *header = NULL;
3588         TnyList *headers = NULL;
3589
3590         /* Get the folder view */
3591         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
3592         if (main_window)
3593                 folder_view = modest_main_window_get_child_widget (main_window,
3594                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
3595         else
3596                 folder_view = NULL;
3597
3598         /* Create and run the dialog */
3599         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);     
3600         result = gtk_dialog_run (GTK_DIALOG(dialog));
3601         modest_folder_view_show_non_move_folders(MODEST_FOLDER_VIEW (tree_view), TRUE);
3602
3603         if (result == GTK_RESPONSE_ACCEPT) {
3604                 TnyFolderStore *folder_store;
3605                 gint response;
3606
3607                 /* Create header list */
3608                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
3609                 g_return_if_fail (header != NULL);
3610
3611                 /* Offer the connection dialog if necessary: */
3612                 /* TODO: What's the extra g_object_ref() for? Isn't this leaking a ref? */
3613                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (g_object_ref (tree_view)));
3614                 TnyFolder *header_folder = tny_header_get_folder(header);
3615                 if (modest_platform_connect_and_wait_if_network_folderstore (NULL, folder_store) &&
3616                     modest_platform_connect_and_wait_if_network_folderstore (NULL, TNY_FOLDER_STORE (header_folder))) {
3617                         
3618                         headers = tny_simple_list_new ();
3619                         tny_list_prepend (headers, G_OBJECT (header));
3620                         g_object_unref (header);
3621
3622                         /* Ask user for confirmation. MSG-NOT404 */
3623                         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
3624                                                       TNY_FOLDER (folder_store), 
3625                                                       headers);
3626
3627                         /* Transfer current msg */
3628                         if (response == GTK_RESPONSE_OK) {
3629                                 ModestMailOperation *mail_op;
3630
3631                                 /* Create mail op */
3632                                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
3633                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3634                                                          mail_op);
3635                         
3636                                 /* Transfer messages */
3637                                 modest_mail_operation_xfer_msgs (mail_op, 
3638                                                          headers,
3639                                                          TNY_FOLDER (folder_store),
3640                                                          TRUE,
3641                                                          transfer_msgs_from_viewer_cb,
3642                                                          NULL);
3643                                 g_object_unref (G_OBJECT (mail_op));
3644                         }
3645                 }
3646                 
3647                 if (header_folder)
3648                         g_object_unref (header_folder);
3649
3650                 if (headers)
3651                         g_object_unref (headers);
3652                         
3653                 if (folder_store)
3654                         g_object_unref (folder_store);
3655         }
3656         
3657         gtk_widget_destroy (dialog);
3658 }
3659
3660 void 
3661 modest_ui_actions_on_move_to (GtkAction *action, 
3662                               ModestWindow *win)
3663 {
3664         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
3665                           MODEST_IS_MSG_VIEW_WINDOW (win));
3666
3667         if (MODEST_IS_MAIN_WINDOW (win)) 
3668                 modest_ui_actions_on_main_window_move_to (action, 
3669                                                           MODEST_MAIN_WINDOW (win));
3670         else
3671                 modest_ui_actions_on_msg_view_window_move_to (action, 
3672                                                               MODEST_MSG_VIEW_WINDOW (win));
3673 }
3674
3675 /*
3676  * Calls #HeadersFunc for each header already selected in the main
3677  * window or the message currently being shown in the msg view window
3678  */
3679 static void
3680 do_headers_action (ModestWindow *win, 
3681                    HeadersFunc func,
3682                    gpointer user_data)
3683 {
3684         TnyList *headers_list;
3685         TnyIterator *iter;
3686         TnyHeader *header;
3687         TnyFolder *folder;
3688
3689         /* Get headers */
3690         headers_list = get_selected_headers (win);
3691         if (!headers_list)
3692                 return;
3693
3694         /* Get the folder */
3695         iter = tny_list_create_iterator (headers_list);
3696         header = TNY_HEADER (tny_iterator_get_current (iter));
3697         folder = tny_header_get_folder (header);
3698         g_object_unref (header);
3699
3700         /* Call the function for each header */
3701         while (!tny_iterator_is_done (iter)) {
3702                 header = TNY_HEADER (tny_iterator_get_current (iter));
3703                 func (header, win, user_data);
3704                 g_object_unref (header);
3705                 tny_iterator_next (iter);
3706         }
3707
3708         /* Trick: do a poke status in order to speed up the signaling
3709            of observers */
3710         tny_folder_poke_status (folder);
3711
3712         /* Frees */
3713         g_object_unref (folder);
3714         g_object_unref (iter);
3715         g_object_unref (headers_list);
3716 }
3717
3718 void 
3719 modest_ui_actions_view_attachment (GtkAction *action,
3720                                    ModestWindow *window)
3721 {
3722         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3723                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
3724         } else {
3725                 /* not supported window for this action */
3726                 g_return_if_reached ();
3727         }
3728 }
3729
3730 void
3731 modest_ui_actions_save_attachments (GtkAction *action,
3732                                     ModestWindow *window)
3733 {
3734         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3735                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
3736         } else {
3737                 /* not supported window for this action */
3738                 g_return_if_reached ();
3739         }
3740 }
3741
3742 void
3743 modest_ui_actions_remove_attachments (GtkAction *action,
3744                                       ModestWindow *window)
3745 {
3746         if (MODEST_IS_MAIN_WINDOW (window)) {
3747                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
3748         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3749                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
3750         } else {
3751                 /* not supported window for this action */
3752                 g_return_if_reached ();
3753         }
3754 }
3755
3756 void 
3757 modest_ui_actions_on_settings (GtkAction *action, 
3758                                ModestWindow *win)
3759 {
3760         GtkWidget *dialog;
3761
3762         dialog = modest_platform_get_global_settings_dialog ();
3763         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
3764         gtk_widget_show_all (dialog);
3765
3766         gtk_dialog_run (GTK_DIALOG (dialog));
3767
3768         gtk_widget_destroy (dialog);
3769 }
3770
3771 void 
3772 modest_ui_actions_on_help (GtkAction *action, 
3773                            ModestWindow *win)
3774 {
3775         const gchar *help_id = NULL;
3776
3777         if (MODEST_IS_MAIN_WINDOW (win)) {
3778                 const gchar *action_name;
3779                 action_name = gtk_action_get_name (action);
3780
3781                 if (!strcmp (action_name, "FolderViewCSMHelp") ||
3782                     !strcmp (action_name, "HeaderViewCSMHelp")) {
3783                         GtkWidget *folder_view;
3784                         TnyFolderStore *folder_store;
3785                         /* Get selected folder */
3786                         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3787                                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
3788                         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3789
3790                         /* Switch help_id */
3791                         if (TNY_IS_FOLDER (folder_store)) {
3792                                 switch (tny_folder_get_folder_type (TNY_FOLDER (folder_store))) {
3793                                 case TNY_FOLDER_TYPE_NORMAL:
3794                                         help_id = "applications_email_userfolder";
3795                                         break;
3796                                 case TNY_FOLDER_TYPE_INBOX:
3797                                         help_id = "applications_email_inbox";
3798                                         break;
3799                                 case TNY_FOLDER_TYPE_OUTBOX:
3800                                         help_id = "applications_email_outbox";
3801                                         break;
3802                                 case TNY_FOLDER_TYPE_SENT:
3803                                         help_id = "applications_email_sent";
3804                                         break;
3805                                 case TNY_FOLDER_TYPE_DRAFTS:
3806                                         help_id = "applications_email_drafts";
3807                                         break;
3808                                 case TNY_FOLDER_TYPE_ARCHIVE:
3809                                         help_id = "applications_email_archive";
3810                                         break;
3811                                 default:
3812                                         help_id = "applications_email_mainview";
3813                                 }
3814                         } else {
3815                                 help_id = "applications_email_mainview";        
3816                         }
3817                         g_object_unref (folder_store);
3818                 } else {
3819                         help_id = "applications_email_mainview";        
3820                 }
3821         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3822                 help_id = "applications_email_viewer";
3823         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
3824                 help_id = "applications_email_editor";
3825
3826         modest_platform_show_help (GTK_WINDOW (win), help_id);
3827 }
3828
3829 void 
3830 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
3831                                             ModestWindow *window)
3832 {
3833         ModestMailOperation *mail_op;
3834         TnyList *headers;
3835
3836         /* Get headers */
3837         headers = get_selected_headers (window);
3838         if (!headers)
3839                 return;
3840
3841         /* Create mail operation */
3842         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3843                                                                  G_OBJECT (window),
3844                                                                  modest_ui_actions_get_msgs_full_error_handler, 
3845                                                                  NULL);
3846         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3847         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
3848
3849         /* Frees */
3850         g_object_unref (headers);
3851         g_object_unref (mail_op);
3852 }
3853
3854 void
3855 modest_ui_actions_on_email_menu_activated (GtkAction *action,
3856                                           ModestWindow *window)
3857 {
3858         g_return_if_fail (MODEST_IS_WINDOW (window));
3859
3860         /* Update dimmed */     
3861         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3862 }
3863
3864 void
3865 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
3866                                           ModestWindow *window)
3867 {
3868         g_return_if_fail (MODEST_IS_WINDOW (window));
3869
3870         /* Update dimmed */     
3871         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3872 }
3873
3874 void
3875 modest_ui_actions_on_view_menu_activated (GtkAction *action,
3876                                           ModestWindow *window)
3877 {
3878         g_return_if_fail (MODEST_IS_WINDOW (window));
3879
3880         /* Update dimmed */     
3881         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3882 }
3883
3884 void
3885 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
3886                                           ModestWindow *window)
3887 {
3888         g_return_if_fail (MODEST_IS_WINDOW (window));
3889
3890         /* Update dimmed */     
3891         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3892 }
3893
3894 void
3895 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
3896                                           ModestWindow *window)
3897 {
3898         g_return_if_fail (MODEST_IS_WINDOW (window));
3899
3900         /* Update dimmed */     
3901         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3902 }
3903
3904 void
3905 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
3906                                                  ModestWindow *window)
3907 {
3908         g_return_if_fail (MODEST_IS_WINDOW (window));
3909
3910         /* Update dimmed */     
3911         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3912 }
3913
3914 void
3915 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
3916                                                      ModestWindow *window)
3917 {
3918         g_return_if_fail (MODEST_IS_WINDOW (window));
3919
3920         /* Update dimmed */     
3921         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3922 }
3923
3924 void
3925 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
3926                                                      ModestWindow *window)
3927 {
3928         g_return_if_fail (MODEST_IS_WINDOW (window));
3929
3930         /* Update dimmed */     
3931         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3932 }
3933
3934 void
3935 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
3936 {
3937         g_return_if_fail (MODEST_IS_WINDOW (window));
3938
3939         /* Update dimmed */     
3940         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
3941 }
3942
3943 void
3944 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
3945 {
3946         g_return_if_fail (MODEST_IS_WINDOW (window));
3947
3948         modest_platform_show_search_messages (GTK_WINDOW (window));
3949 }
3950
3951 void     
3952 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
3953 {
3954         g_return_if_fail (MODEST_IS_WINDOW (win));
3955         modest_platform_show_addressbook (GTK_WINDOW (win));
3956 }
3957
3958
3959 void
3960 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
3961                                           ModestWindow *window)
3962 {
3963         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3964
3965         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
3966 }
3967
3968 static void 
3969 _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
3970                                    ModestMailOperationState *state,
3971                                    gpointer user_data)
3972 {
3973         g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
3974
3975         /* Set send/receive operation finished */       
3976         if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3977                 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));
3978         
3979 }
3980
3981