* Set focus on next row after delete selected headers
[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 {
1108         TnyIterator *iter;
1109         gboolean retval;
1110         gint uncached_messages = 0;
1111
1112         iter = tny_list_create_iterator (header_list);
1113         while (!tny_iterator_is_done (iter)) {
1114                 TnyHeader *header;
1115                 TnyHeaderFlags flags;
1116
1117                 header = TNY_HEADER (tny_iterator_get_current (iter));
1118                 flags = tny_header_get_flags (header);
1119                 /* TODO: is this the right flag?, it seems that some
1120                    headers that have been previously downloaded do not
1121                    come with it */
1122                 if (! (flags & TNY_HEADER_FLAG_CACHED))
1123                         uncached_messages ++;
1124                 g_object_unref (header);
1125                 tny_iterator_next (iter);
1126         }
1127         g_object_unref (iter);
1128
1129         /* Ask for user permission to download the messages */
1130         retval = TRUE;
1131         if (uncached_messages > 0) {
1132                 GtkResponseType response;
1133                 response = 
1134                         modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1135                                                                  ngettext("mcen_nc_get_msg",
1136                                                                           "mcen_nc_get_msgs",
1137                                                                          uncached_messages));
1138                 if (response == GTK_RESPONSE_CANCEL)
1139                         retval = FALSE;
1140                 else {
1141                         /* If a download will be necessary, make sure that we have a connection: */
1142                         retval = modest_platform_connect_and_wait(win); 
1143                 }
1144         }
1145         return retval;
1146 }
1147
1148
1149 /*
1150  * Common code for the reply and forward actions
1151  */
1152 static void
1153 reply_forward (ReplyForwardAction action, ModestWindow *win)
1154 {
1155         ModestMailOperation *mail_op = NULL;
1156         TnyList *header_list = NULL;
1157         ReplyForwardHelper *rf_helper = NULL;
1158         guint reply_forward_type;
1159         gboolean continue_download;
1160         
1161         g_return_if_fail (MODEST_IS_WINDOW(win));
1162
1163         /* we need an account when editing */
1164         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1165                 run_account_setup_wizard (win);
1166                 return;
1167         }
1168         
1169         header_list = get_selected_headers (win);
1170         if (!header_list)
1171                 return;
1172
1173         /* Check that the messages have been previously downloaded */
1174         continue_download = download_uncached_messages (header_list, GTK_WINDOW (win));
1175         if (!continue_download) {
1176                 g_object_unref (header_list);
1177                 return;
1178         }
1179         
1180         reply_forward_type = 
1181                 modest_conf_get_int (modest_runtime_get_conf (),
1182                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1183                                      NULL);
1184         /* We assume that we can only select messages of the
1185            same folder and that we reply all of them from the
1186            same account. In fact the interface currently only
1187            allows single selection */
1188         
1189         /* Fill helpers */
1190         rf_helper = g_slice_new0 (ReplyForwardHelper);
1191         rf_helper->reply_forward_type = reply_forward_type;
1192         rf_helper->action = action;
1193         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1194         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1195                 rf_helper->parent_window = GTK_WIDGET (win);
1196         if (!rf_helper->account_name)
1197                 rf_helper->account_name =
1198                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1199
1200         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1201                 TnyMsg *msg;
1202                 TnyHeader *header;
1203                 /* Get header and message. Do not free them here, the
1204                    reply_forward_cb must do it */
1205                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1206                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1207                 if (!msg || !header) {
1208                         if (msg)
1209                                 g_object_unref (msg);
1210                         if (header)
1211                                 g_object_unref (header);
1212                         g_printerr ("modest: no message found\n");
1213                         return;
1214                 } else {
1215                         reply_forward_cb (NULL, header, msg, rf_helper);
1216                 }
1217         } else {
1218                 TnyHeader *header;
1219                 TnyIterator *iter;
1220
1221                 /* Retrieve messages */
1222                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
1223                                                                          G_OBJECT(win),
1224                                                                          modest_ui_actions_get_msgs_full_error_handler, 
1225                                                                          NULL);
1226                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1227
1228                 /* Only reply/forward to one message */
1229                 iter = tny_list_create_iterator (header_list);
1230                 header = TNY_HEADER (tny_iterator_get_current (iter));
1231                 g_object_unref (iter);
1232
1233                 modest_mail_operation_get_msg (mail_op,
1234                                                header,
1235                                                reply_forward_cb,
1236                                                rf_helper);
1237
1238 /*              modest_mail_operation_get_msgs_full (mail_op,  */
1239 /*                                                   header_list,  */
1240 /*                                                   reply_forward_cb,  */
1241 /*                                                   rf_helper,  */
1242 /*                                                   free_reply_forward_helper); */
1243
1244                 /* Clean */
1245                 g_object_unref(mail_op);
1246         }
1247
1248         /* Free */
1249         g_object_unref (header_list);
1250 }
1251
1252 void
1253 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1254 {
1255         g_return_if_fail (MODEST_IS_WINDOW(win));
1256
1257         reply_forward (ACTION_REPLY, win);
1258 }
1259
1260 void
1261 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1262 {
1263         g_return_if_fail (MODEST_IS_WINDOW(win));
1264
1265         reply_forward (ACTION_FORWARD, win);
1266 }
1267
1268 void
1269 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1270 {
1271         g_return_if_fail (MODEST_IS_WINDOW(win));
1272
1273         reply_forward (ACTION_REPLY_TO_ALL, win);
1274 }
1275
1276 void 
1277 modest_ui_actions_on_next (GtkAction *action, 
1278                            ModestWindow *window)
1279 {
1280         if (MODEST_IS_MAIN_WINDOW (window)) {
1281                 GtkWidget *header_view;
1282
1283                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1284                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1285                 if (!header_view)
1286                         return;
1287         
1288                 modest_header_view_select_next (MODEST_HEADER_VIEW(header_view)); 
1289         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1290                 modest_msg_view_window_select_next_message (MODEST_MSG_VIEW_WINDOW (window));
1291         } else {
1292                 g_return_if_reached ();
1293         }
1294 }
1295
1296 void 
1297 modest_ui_actions_on_prev (GtkAction *action, 
1298                            ModestWindow *window)
1299 {
1300         g_return_if_fail (MODEST_IS_WINDOW(window));
1301
1302         if (MODEST_IS_MAIN_WINDOW (window)) {
1303                 GtkWidget *header_view;
1304                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1305                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1306                 if (!header_view)
1307                         return;
1308                 
1309                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1310         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1311                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1312         } else {
1313                 g_return_if_reached ();
1314         }
1315 }
1316
1317 void 
1318 modest_ui_actions_on_sort (GtkAction *action, 
1319                            ModestWindow *window)
1320 {
1321         g_return_if_fail (MODEST_IS_WINDOW(window));
1322
1323         if (MODEST_IS_MAIN_WINDOW (window)) {
1324                 GtkWidget *header_view;
1325                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1326                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1327                 if (!header_view)
1328                         return;
1329
1330                 /* Show sorting dialog */
1331                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1332         }
1333 }
1334
1335 static void
1336 new_messages_arrived (ModestMailOperation *self, 
1337                       gint new_messages,
1338                       gpointer user_data)
1339 {
1340         if (new_messages == 0)
1341                 return;
1342
1343         modest_platform_on_new_msg ();
1344 }
1345
1346 /*
1347  * This function performs the send & receive required actions. The
1348  * window is used to create the mail operation. Typically it should
1349  * always be the main window, but we pass it as argument in order to
1350  * be more flexible.
1351  */
1352 void
1353 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
1354 {
1355         gchar *acc_name = NULL;
1356         ModestMailOperation *mail_op;
1357
1358         /* If no account name was provided then get the current account, and if
1359            there is no current account then pick the default one: */
1360         if (!account_name) {
1361                 acc_name = g_strdup (modest_window_get_active_account(win));
1362                 if (!acc_name)
1363                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1364                 if (!acc_name) {
1365                         g_printerr ("modest: cannot get default account\n");
1366                         return;
1367                 }
1368         } else {
1369                 acc_name = g_strdup (account_name);
1370         }
1371
1372         /* Set send/receive operation in progress */    
1373         modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW(win));
1374
1375         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
1376                                                                  G_OBJECT (win),
1377                                                                  modest_ui_actions_send_receive_error_handler,
1378                                                                  NULL);
1379
1380         g_signal_connect (G_OBJECT(mail_op), "progress-changed", 
1381                           G_CALLBACK (_on_send_receive_progress_changed), 
1382                           win);
1383
1384         /* Send & receive. */
1385         /* TODO: The spec wants us to first do any pending deletions, before receiving. */
1386         /* Receive and then send. The operation is tagged initially as
1387            a receive operation because the account update performs a
1388            receive and then a send. The operation changes its type
1389            internally, so the progress objects will receive the proper
1390            progress information */
1391         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1392         modest_mail_operation_update_account (mail_op, acc_name, new_messages_arrived, NULL);
1393         g_object_unref (G_OBJECT (mail_op));
1394         
1395         /* Free */
1396         g_free (acc_name);
1397 }
1398
1399
1400 static void
1401 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1402                                   ModestWindow *win)
1403 {
1404         TnyTransportAccount *transport_account;
1405         TnySendQueue *send_queue = NULL;
1406         GError *error = NULL;
1407
1408         /* Get transport account */
1409         transport_account =
1410                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1411                                       (modest_runtime_get_account_store(),
1412                                        account_name,
1413                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1414         if (!transport_account) {
1415                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1416                 goto frees;
1417         }
1418
1419         /* Get send queue*/
1420         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1421         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1422                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1423                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1424                              "modest: could not find send queue for account\n");
1425         } else {
1426                 /* Keeep messages in outbox folder */
1427                 tny_send_queue_cancel (send_queue, FALSE, &error);
1428         }       
1429
1430  frees:
1431         if (transport_account != NULL) 
1432                 g_object_unref (G_OBJECT (transport_account));
1433 }
1434
1435 static void
1436 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1437 {
1438         GSList *account_names, *iter;
1439
1440         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1441                                                           TRUE);
1442
1443         iter = account_names;
1444         while (iter) {                  
1445                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1446                 iter = g_slist_next (iter);
1447         }
1448
1449         modest_account_mgr_free_account_names (account_names);
1450         account_names = NULL;
1451 }
1452
1453 void
1454 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1455
1456 {
1457         /* Check if accounts exist */
1458         gboolean accounts_exist = 
1459                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1460         
1461         /* If not, allow the user to create an account before trying to send/receive. */
1462         if (!accounts_exist)
1463                 modest_ui_actions_on_accounts (NULL, win);
1464         
1465         /* Cancel all sending operaitons */     
1466         modest_ui_actions_cancel_send_all (win);
1467 }
1468
1469 /*
1470  * Refreshes all accounts. This function will be used by automatic
1471  * updates
1472  */
1473 void
1474 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1475 {
1476         GSList *account_names, *iter;
1477
1478         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1479                                                           TRUE);
1480
1481         iter = account_names;
1482         while (iter) {                  
1483                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1484                 iter = g_slist_next (iter);
1485         }
1486
1487         modest_account_mgr_free_account_names (account_names);
1488         account_names = NULL;
1489 }
1490
1491 /*
1492  * Handler of the click on Send&Receive button in the main toolbar
1493  */
1494 void
1495 modest_ui_actions_on_send_receive (GtkAction *action,  ModestWindow *win)
1496 {
1497         /* Check if accounts exist */
1498         gboolean accounts_exist = 
1499                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1500         
1501         /* If not, allow the user to create an account before trying to send/receive. */
1502         if (!accounts_exist)
1503                 modest_ui_actions_on_accounts (NULL, win);
1504
1505         /* Refresh currently selected folder. Note that if we only
1506            want to retrive the headers, then the refresh only will
1507            invoke a poke_status over all folders, i.e., only the
1508            total/unread count will be updated */
1509         if (MODEST_IS_MAIN_WINDOW (win)) {
1510                 GtkWidget *header_view, *folder_view;
1511                 TnyFolderStore *folder_store;
1512
1513                 /* Get folder and header view */
1514                 folder_view = 
1515                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1516                                                              MODEST_WIDGET_TYPE_FOLDER_VIEW);
1517
1518                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1519
1520                 if (folder_store && TNY_IS_FOLDER (folder_store)) {
1521                         header_view = 
1522                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1523                                                                      MODEST_WIDGET_TYPE_HEADER_VIEW);
1524                 
1525                         /* We do not need to set the contents style
1526                            because it hasn't changed. We also do not
1527                            need to save the widget status. Just force
1528                            a refresh */
1529                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1530                                                        TNY_FOLDER (folder_store),
1531                                                        folder_refreshed_cb,
1532                                                        MODEST_MAIN_WINDOW (win));
1533                 }
1534                 
1535                 if (folder_store)
1536                         g_object_unref (folder_store);
1537         }
1538         
1539         /* Refresh the active account */
1540         modest_ui_actions_do_send_receive (NULL, win);
1541 }
1542
1543
1544 void
1545 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1546 {
1547         ModestConf *conf;
1548         GtkWidget *header_view;
1549         
1550         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1551
1552         header_view = modest_main_window_get_child_widget (main_window,
1553                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1554         if (!header_view)
1555                 return;
1556
1557         conf = modest_runtime_get_conf ();
1558         
1559         /* what is saved/restored is depending on the style; thus; we save with
1560          * old style, then update the style, and restore for this new style
1561          */
1562         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1563         
1564         if (modest_header_view_get_style
1565             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1566                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1567                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1568         else
1569                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1570                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1571
1572         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1573                                       MODEST_CONF_HEADER_VIEW_KEY);
1574 }
1575
1576
1577 void 
1578 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1579                                       TnyHeader *header,
1580                                       ModestMainWindow *main_window)
1581 {
1582         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1583         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1584         
1585         /* If no header has been selected then exit */
1586         if (!header)
1587                 return;
1588
1589         /* Update focus */
1590         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1591             gtk_widget_grab_focus (GTK_WIDGET(header_view));
1592
1593         /* Update Main window title */
1594         if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
1595                 const gchar *subject = tny_header_get_subject (header);
1596                 if (subject && strlen(subject) > 0)
1597                         gtk_window_set_title (GTK_WINDOW (main_window), subject);
1598                 else
1599                         gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
1600         }
1601
1602         /* Update toolbar dimming state */
1603         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1604 }
1605
1606 void
1607 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1608                                        TnyHeader *header,
1609                                        ModestMainWindow *main_window)
1610 {
1611         TnyList *headers;
1612
1613         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1614         
1615         if (!header)
1616                 return;
1617
1618         headers = tny_simple_list_new ();
1619         tny_list_prepend (headers, G_OBJECT (header));
1620
1621         _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1622
1623         g_object_unref (headers);
1624 }
1625
1626 static void
1627 set_active_account_from_tny_account (TnyAccount *account,
1628                                      ModestWindow *window)
1629 {
1630         const gchar *server_acc_name = tny_account_get_id (account);
1631         
1632         /* We need the TnyAccount provided by the
1633            account store because that is the one that
1634            knows the name of the Modest account */
1635         TnyAccount *modest_server_account = modest_server_account = 
1636                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
1637                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
1638                                                              server_acc_name);
1639         
1640         const gchar *modest_acc_name = 
1641                 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1642         modest_window_set_active_account (window, modest_acc_name);
1643         g_object_unref (modest_server_account);
1644 }
1645
1646
1647 static void
1648 folder_refreshed_cb (ModestMailOperation *mail_op, 
1649                      TnyFolder *folder, 
1650                      gpointer user_data)
1651 {
1652         ModestMainWindow *win = NULL;
1653         GtkWidget *header_view;
1654
1655         g_return_if_fail (TNY_IS_FOLDER (folder));
1656
1657         win = MODEST_MAIN_WINDOW (user_data);
1658         header_view = 
1659                 modest_main_window_get_child_widget(win, MODEST_WIDGET_TYPE_HEADER_VIEW);
1660
1661         /* Check if folder is empty and set headers view contents style */
1662         if (tny_folder_get_all_count (folder) == 0) {
1663         printf ("DEBUG: %s: tny_folder_get_all_count() returned 0.\n", __FUNCTION__);
1664                 modest_main_window_set_contents_style (win,
1665                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1666         } else {
1667                 printf ("DEBUG: %s: tny_folder_get_all_count() returned >0.\n", __FUNCTION__);
1668         }
1669 }
1670
1671 void 
1672 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1673                                                TnyFolderStore *folder_store, 
1674                                                gboolean selected,
1675                                                ModestMainWindow *main_window)
1676 {
1677         ModestConf *conf;
1678         GtkWidget *header_view;
1679
1680         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1681
1682         header_view = modest_main_window_get_child_widget(main_window,
1683                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
1684         if (!header_view)
1685                 return;
1686         
1687         conf = modest_runtime_get_conf ();
1688
1689         if (TNY_IS_ACCOUNT (folder_store)) {
1690                 if (selected) {
1691                         /* Update active account */
1692                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1693                         /* Show account details */
1694                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1695                 }
1696         } else {
1697                 if (TNY_IS_FOLDER (folder_store) && selected) {
1698                         
1699                         /* Update the active account */
1700                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
1701                         if (account) {
1702                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1703                                 g_object_unref (account);
1704                                 account = NULL;
1705                         }
1706
1707                         /* Set the header style by default, it could
1708                            be changed later by the refresh callback to
1709                            empty */
1710                         modest_main_window_set_contents_style (main_window, 
1711                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1712
1713                         /* Set folder on header view. This function
1714                            will call tny_folder_refresh_async so we
1715                            pass a callback that will be called when
1716                            finished. We use that callback to set the
1717                            empty view if there are no messages */
1718                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1719                                                        TNY_FOLDER (folder_store),
1720                                                        folder_refreshed_cb,
1721                                                        main_window);
1722                         
1723                         /* Restore configuration. We need to do this
1724                            *after* the set_folder because the widget
1725                            memory asks the header view about its
1726                            folder  */
1727                         modest_widget_memory_restore (modest_runtime_get_conf (), 
1728                                                       G_OBJECT(header_view),
1729                                                       MODEST_CONF_HEADER_VIEW_KEY);
1730                 } else {
1731                         /* Update the active account */
1732                         modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
1733                         /* Save only if we're seeing headers */
1734                         if (modest_main_window_get_contents_style (main_window) ==
1735                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1736                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
1737                                                            MODEST_CONF_HEADER_VIEW_KEY);
1738                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
1739                 }
1740         }
1741
1742         /* Update toolbar dimming state */
1743         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1744 }
1745
1746 void 
1747 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1748                                      ModestWindow *win)
1749 {
1750         GtkWidget *dialog;
1751         gchar *txt, *item;
1752         gboolean online;
1753
1754         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1755         
1756         online = tny_device_is_online (modest_runtime_get_device());
1757
1758         if (online) {
1759                 /* already online -- the item is simply not there... */
1760                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1761                                                  GTK_DIALOG_MODAL,
1762                                                  GTK_MESSAGE_WARNING,
1763                                                  GTK_BUTTONS_OK,
1764                                                  _("The %s you selected cannot be found"),
1765                                                  item);
1766                 gtk_dialog_run (GTK_DIALOG(dialog));
1767         } else {
1768                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1769                                                       GTK_WINDOW (win),
1770                                                       GTK_DIALOG_MODAL,
1771                                                       GTK_STOCK_CANCEL,
1772                                                       GTK_RESPONSE_REJECT,
1773                                                       GTK_STOCK_OK,
1774                                                       GTK_RESPONSE_ACCEPT,
1775                                                       NULL);
1776                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1777                                          "Do you want to get online?"), item);
1778                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1779                                     gtk_label_new (txt), FALSE, FALSE, 0);
1780                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1781                 g_free (txt);
1782
1783                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1784                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1785 //                      modest_platform_connect_and_wait ();
1786                 }
1787         }
1788         gtk_widget_destroy (dialog);
1789 }
1790
1791 void
1792 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1793                                      ModestWindow *win)
1794 {
1795         /* g_message ("%s %s", __FUNCTION__, link); */
1796 }       
1797
1798
1799 void
1800 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1801                                         ModestWindow *win)
1802 {
1803         modest_platform_activate_uri (link);
1804 }
1805
1806 void
1807 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1808                                           ModestWindow *win)
1809 {
1810         modest_platform_show_uri_popup (link);
1811 }
1812
1813 void
1814 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1815                                              ModestWindow *win)
1816 {
1817         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
1818 }
1819
1820 void
1821 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1822                                           const gchar *address,
1823                                           ModestWindow *win)
1824 {
1825         /* g_message ("%s %s", __FUNCTION__, address); */
1826 }
1827
1828 void
1829 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1830 {
1831         TnyTransportAccount *transport_account;
1832         ModestMailOperation *mail_operation;
1833         MsgData *data;
1834         gchar *account_name, *from;
1835         ModestAccountMgr *account_mgr;
1836         gchar *info_text = NULL;
1837         TnyMsg *new_draft = NULL;
1838
1839         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1840         
1841         data = modest_msg_edit_window_get_msg_data (edit_window);
1842
1843         account_mgr = modest_runtime_get_account_mgr();
1844         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1845         if (!account_name) 
1846                 account_name = modest_account_mgr_get_default_account (account_mgr);
1847         if (!account_name) {
1848                 g_printerr ("modest: no account found\n");
1849                 modest_msg_edit_window_free_msg_data (edit_window, data);
1850                 return;
1851         }
1852
1853         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1854                 account_name = g_strdup (data->account_name);
1855         }
1856
1857         transport_account =
1858                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1859                                       (modest_runtime_get_account_store(),
1860                                        account_name,
1861                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1862         if (!transport_account) {
1863                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1864                 g_free (account_name);
1865                 modest_msg_edit_window_free_msg_data (edit_window, data);
1866                 return;
1867         }
1868         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1869
1870         /* Create the mail operation */         
1871         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
1872         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1873
1874         new_draft = modest_mail_operation_save_to_drafts (mail_operation,
1875                                                           transport_account,
1876                                                           data->draft_msg,
1877                                                           from,
1878                                                           data->to, 
1879                                                           data->cc, 
1880                                                           data->bcc,
1881                                                           data->subject, 
1882                                                           data->plain_body, 
1883                                                           data->html_body,
1884                                                           data->attachments,
1885                                                           data->priority_flags);
1886         /* Frees */
1887         g_free (from);
1888         g_free (account_name);
1889         g_object_unref (G_OBJECT (transport_account));
1890         g_object_unref (G_OBJECT (mail_operation));
1891
1892         modest_msg_edit_window_free_msg_data (edit_window, data);
1893
1894         modest_msg_edit_window_set_draft (edit_window, new_draft);
1895         if (new_draft != NULL)
1896                 g_object_unref (new_draft);
1897
1898         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
1899         modest_platform_information_banner (NULL, NULL, info_text);
1900         g_free (info_text);
1901 }
1902
1903 /* For instance, when clicking the Send toolbar button when editing a message: */
1904 void
1905 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1906 {
1907         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1908
1909         if (!modest_msg_edit_window_check_names (edit_window))
1910                 return;
1911         
1912         /* Offer the connection dialog, if necessary: */        
1913         if (!modest_platform_connect_and_wait (GTK_WINDOW (edit_window)))
1914                 return;
1915         
1916         /* FIXME: Code added just for testing. The final version will
1917            use the send queue provided by tinymail and some
1918            classifier */
1919         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
1920         gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1921         if (!account_name) 
1922                 account_name = modest_account_mgr_get_default_account (account_mgr);
1923                 
1924         if (!account_name) {
1925                 g_printerr ("modest: no account found\n");
1926                 return;
1927         }
1928         
1929         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
1930
1931         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1932                 account_name = g_strdup (data->account_name);
1933         }
1934         
1935         /* Get the currently-active transport account for this modest account: */
1936         TnyTransportAccount *transport_account =
1937                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
1938                                       (modest_runtime_get_account_store(),
1939                                        account_name));
1940         if (!transport_account) {
1941                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1942                 g_free (account_name);
1943                 modest_msg_edit_window_free_msg_data (edit_window, data);
1944                 return;
1945         }
1946         
1947         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
1948
1949         /* mail content checks and dialogs */
1950         if (data->subject == NULL || data->subject[0] == '\0') {
1951                 GtkResponseType response;
1952                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1953                                                                     _("mcen_nc_subject_is_empty_send"));
1954                 if (response == GTK_RESPONSE_CANCEL) {
1955                         g_free (account_name);
1956                         return;
1957                 }
1958         }
1959
1960         if (data->plain_body == NULL || data->plain_body[0] == '\0') {
1961                 GtkResponseType response;
1962                 gchar *note_message;
1963                 gchar *note_subject = data->subject;
1964                 if (note_subject == NULL || note_subject[0] == '\0')
1965                         note_subject = _("mail_va_no_subject");
1966                 note_message = g_strdup_printf (_("emev_ni_ui_smtp_message_null"), note_subject);
1967                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1968                                                                     note_message);
1969                 g_free (note_message);
1970                 if (response == GTK_RESPONSE_CANCEL) {
1971                         g_free (account_name);
1972                         return;
1973                 }
1974         }
1975
1976         modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
1977
1978         /* Create the mail operation */
1979         ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
1980         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1981
1982         modest_mail_operation_send_new_mail (mail_operation,
1983                                              transport_account,
1984                                              data->draft_msg,
1985                                              from,
1986                                              data->to, 
1987                                              data->cc, 
1988                                              data->bcc,
1989                                              data->subject, 
1990                                              data->plain_body, 
1991                                              data->html_body,
1992                                              data->attachments,
1993                                              data->priority_flags);
1994                                              
1995         /* Free data: */
1996         g_free (from);
1997         g_free (account_name);
1998         g_object_unref (G_OBJECT (transport_account));
1999         g_object_unref (G_OBJECT (mail_operation));
2000
2001         modest_msg_edit_window_free_msg_data (edit_window, data);
2002         modest_msg_edit_window_set_sent (edit_window, TRUE);
2003
2004         /* Save settings and close the window: */
2005         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2006 }
2007
2008 void 
2009 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2010                                   ModestMsgEditWindow *window)
2011 {
2012         ModestMsgEditFormatState *format_state = NULL;
2013
2014         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2015         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2016
2017         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2018                 return;
2019
2020         format_state = modest_msg_edit_window_get_format_state (window);
2021         g_return_if_fail (format_state != NULL);
2022
2023         format_state->bold = gtk_toggle_action_get_active (action);
2024         modest_msg_edit_window_set_format_state (window, format_state);
2025         g_free (format_state);
2026         
2027 }
2028
2029 void 
2030 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2031                                      ModestMsgEditWindow *window)
2032 {
2033         ModestMsgEditFormatState *format_state = NULL;
2034
2035         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2036         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2037
2038         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2039                 return;
2040
2041         format_state = modest_msg_edit_window_get_format_state (window);
2042         g_return_if_fail (format_state != NULL);
2043
2044         format_state->italics = gtk_toggle_action_get_active (action);
2045         modest_msg_edit_window_set_format_state (window, format_state);
2046         g_free (format_state);
2047         
2048 }
2049
2050 void 
2051 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2052                                      ModestMsgEditWindow *window)
2053 {
2054         ModestMsgEditFormatState *format_state = NULL;
2055
2056         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2057         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2058
2059         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2060                 return;
2061
2062         format_state = modest_msg_edit_window_get_format_state (window);
2063         g_return_if_fail (format_state != NULL);
2064
2065         format_state->bullet = gtk_toggle_action_get_active (action);
2066         modest_msg_edit_window_set_format_state (window, format_state);
2067         g_free (format_state);
2068         
2069 }
2070
2071 void 
2072 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2073                                      GtkRadioAction *selected,
2074                                      ModestMsgEditWindow *window)
2075 {
2076         ModestMsgEditFormatState *format_state = NULL;
2077         GtkJustification value;
2078
2079         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2080
2081         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2082                 return;
2083
2084         value = gtk_radio_action_get_current_value (selected);
2085
2086         format_state = modest_msg_edit_window_get_format_state (window);
2087         g_return_if_fail (format_state != NULL);
2088
2089         format_state->justification = value;
2090         modest_msg_edit_window_set_format_state (window, format_state);
2091         g_free (format_state);
2092 }
2093
2094 void 
2095 modest_ui_actions_on_select_editor_color (GtkAction *action,
2096                                           ModestMsgEditWindow *window)
2097 {
2098         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2099         g_return_if_fail (GTK_IS_ACTION (action));
2100
2101         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2102                 return;
2103
2104         modest_msg_edit_window_select_color (window);
2105 }
2106
2107 void 
2108 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2109                                                      ModestMsgEditWindow *window)
2110 {
2111         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2112         g_return_if_fail (GTK_IS_ACTION (action));
2113
2114         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2115                 return;
2116
2117         modest_msg_edit_window_select_background_color (window);
2118 }
2119
2120 void 
2121 modest_ui_actions_on_insert_image (GtkAction *action,
2122                                    ModestMsgEditWindow *window)
2123 {
2124         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2125         g_return_if_fail (GTK_IS_ACTION (action));
2126
2127         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2128                 return;
2129
2130         modest_msg_edit_window_insert_image (window);
2131 }
2132
2133 void 
2134 modest_ui_actions_on_attach_file (GtkAction *action,
2135                                   ModestMsgEditWindow *window)
2136 {
2137         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2138         g_return_if_fail (GTK_IS_ACTION (action));
2139
2140         modest_msg_edit_window_attach_file (window);
2141 }
2142
2143 void 
2144 modest_ui_actions_on_remove_attachments (GtkAction *action,
2145                                          ModestMsgEditWindow *window)
2146 {
2147         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2148         g_return_if_fail (GTK_IS_ACTION (action));
2149
2150         modest_msg_edit_window_remove_attachments (window, NULL);
2151 }
2152
2153 static void
2154 modest_ui_actions_new_folder_error_handler (ModestMailOperation *mail_op,
2155                                             gpointer user_data)
2156 {
2157         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2158
2159         /* TODO: Note that folder creation might go wrong due to other
2160          * failures such as when the parent folder is non-writable. We can
2161          * query a GError* with modest_mail_operation_get_error(), but the
2162          * the error code (from tinymail) does not give us a clue about what
2163          * has gone wrong. We might use the error->message but it might come
2164          * from camel and not be suitable to show to the user directly. */
2165         modest_platform_information_banner (GTK_WIDGET (window), NULL,
2166                                             _CS("ckdg_ib_folder_already_exists"));
2167
2168 /*      modest_platform_information_banner (GTK_WIDGET (window), NULL,
2169                                             modest_mail_operation_get_error (mail_op)->message);*/
2170 }
2171
2172 void 
2173 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2174 {
2175         TnyFolderStore *parent_folder;
2176         GtkWidget *folder_view;
2177         
2178         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2179
2180         folder_view = modest_main_window_get_child_widget (main_window,
2181                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2182         if (!folder_view)
2183                 return;
2184
2185         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2186         
2187         if (parent_folder) {
2188                 gboolean finished = FALSE;
2189                 gint result;
2190                 gchar *folder_name = NULL, *suggested_name = NULL;
2191
2192                 /* Run the new folder dialog */
2193                 while (!finished) {
2194                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (main_window),
2195                                                                         parent_folder,
2196                                                                         suggested_name,
2197                                                                         &folder_name);
2198
2199                         g_free (suggested_name);
2200                         suggested_name = NULL;
2201
2202                         if (result == GTK_RESPONSE_REJECT) {
2203                                 finished = TRUE;
2204                         } else {
2205                                 ModestMailOperation *mail_op;
2206                                 TnyFolder *new_folder = NULL;
2207
2208                                 mail_op  = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2209                                                                                           G_OBJECT(main_window),
2210                                                                                           modest_ui_actions_new_folder_error_handler,
2211                                                                                           main_window);
2212
2213                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2214                                                                  mail_op);
2215                                 new_folder = modest_mail_operation_create_folder (mail_op,
2216                                                                                   parent_folder,
2217                                                                                   (const gchar *) folder_name);
2218                                 if (new_folder) {
2219                                         g_object_unref (new_folder);
2220                                         finished = TRUE;
2221                                 }
2222                                 g_object_unref (mail_op);
2223                         }
2224
2225                         suggested_name = folder_name;
2226                         folder_name = NULL;
2227                 }
2228
2229                 g_object_unref (parent_folder);
2230         }
2231 }
2232
2233 static void
2234 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2235                                                gpointer user_data)
2236 {
2237         GObject *win = modest_mail_operation_get_source (mail_op);
2238         const GError *error = NULL;
2239         const gchar *message = NULL;
2240         
2241         /* Get error message */
2242         error = modest_mail_operation_get_error (mail_op);
2243         if (error != NULL && error->message != NULL) {
2244                 message = error->message;
2245         } else {
2246                 message = _("!!! FIXME: Unable to rename");
2247         }
2248         
2249         /* Show notification dialog */
2250         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
2251         g_object_unref (win);
2252 }
2253
2254 void 
2255 modest_ui_actions_on_rename_folder (GtkAction *action,
2256                                      ModestMainWindow *main_window)
2257 {
2258         TnyFolderStore *folder;
2259         GtkWidget *folder_view;
2260         GtkWidget *header_view; 
2261
2262         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2263
2264         folder_view = modest_main_window_get_child_widget (main_window,
2265                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2266         if (!folder_view)
2267                 return;
2268
2269         header_view = modest_main_window_get_child_widget (main_window,
2270                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2271         
2272         if (!header_view)
2273                 return;
2274
2275         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2276
2277         /* Offer the connection dialog if necessary: */
2278         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2279                 g_object_unref (G_OBJECT (folder));
2280                 return;
2281         }
2282
2283         
2284         if (folder && TNY_IS_FOLDER (folder)) {
2285                 gchar *folder_name;
2286                 gint response;
2287                 const gchar *current_name;
2288
2289                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2290                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), NULL,
2291                                                                      current_name, &folder_name);
2292
2293                 if (response == GTK_RESPONSE_ACCEPT && strlen (folder_name) > 0) {
2294                         ModestMailOperation *mail_op;
2295
2296                         mail_op = 
2297                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO, 
2298                                                                                G_OBJECT(main_window),
2299                                                                                modest_ui_actions_rename_folder_error_handler,
2300                                                                                NULL);
2301
2302
2303                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2304                                                          mail_op);
2305
2306                         modest_header_view_clear (MODEST_HEADER_VIEW (header_view));
2307
2308                         modest_mail_operation_rename_folder (mail_op,
2309                                                              TNY_FOLDER (folder),
2310                                                              (const gchar *) folder_name);
2311
2312                         g_object_unref (mail_op);
2313                         g_free (folder_name);
2314                 }
2315                 g_object_unref (folder);
2316         }
2317 }
2318
2319 static void
2320 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2321                                                gpointer user_data)
2322 {
2323         GObject *win = modest_mail_operation_get_source (mail_op);
2324
2325         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2326                                                 _("mail_in_ui_folder_delete_error"));
2327         g_object_unref (win);
2328 }
2329
2330 static void
2331 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2332 {
2333         TnyFolderStore *folder;
2334         GtkWidget *folder_view;
2335         gint response;
2336         gchar *message;
2337         
2338         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2339
2340         folder_view = modest_main_window_get_child_widget (main_window,
2341                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2342         if (!folder_view)
2343                 return;
2344
2345         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2346
2347         /* Show an error if it's an account */
2348         if (!TNY_IS_FOLDER (folder)) {
2349                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2350                                                         _("mail_in_ui_folder_delete_error"));
2351                 g_object_unref (G_OBJECT (folder));
2352                 return ;
2353         }
2354
2355         /* Offer the connection dialog if necessary: */
2356         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2357                 g_object_unref (G_OBJECT (folder));
2358                 return;
2359         }
2360
2361         /* Ask the user */      
2362         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2363                                     tny_folder_get_name (TNY_FOLDER (folder)));
2364         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2365                                                             (const gchar *) message);
2366         g_free (message);
2367
2368         if (response == GTK_RESPONSE_OK) {
2369                 ModestMailOperation *mail_op = 
2370                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
2371                                                                        G_OBJECT(main_window),
2372                                                                        modest_ui_actions_delete_folder_error_handler,
2373                                                                        NULL);
2374
2375                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2376                                                  mail_op);
2377                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2378                 g_object_unref (G_OBJECT (mail_op));
2379         }
2380
2381         g_object_unref (G_OBJECT (folder));
2382 }
2383
2384 void 
2385 modest_ui_actions_on_delete_folder (GtkAction *action,
2386                                      ModestMainWindow *main_window)
2387 {
2388         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2389
2390         delete_folder (main_window, FALSE);
2391 }
2392
2393 void 
2394 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2395 {
2396         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2397         
2398         delete_folder (main_window, TRUE);
2399 }
2400
2401 void
2402 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2403                                          const gchar* server_account_name,
2404                                          gchar **username,
2405                                          gchar **password, 
2406                                          gboolean *cancel, 
2407                                          gboolean *remember,
2408                                          ModestMainWindow *main_window)
2409 {
2410         g_return_if_fail(server_account_name);
2411         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2412         
2413         /* Initalize output parameters: */
2414         if (cancel)
2415                 *cancel = FALSE;
2416                 
2417         if (remember)
2418                 *remember = TRUE;
2419                 
2420 #ifdef MODEST_PLATFORM_MAEMO
2421         /* Maemo uses a different (awkward) button order,
2422          * It should probably just use gtk_alternative_dialog_button_order ().
2423          */
2424         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2425                                               NULL,
2426                                               GTK_DIALOG_MODAL,
2427                                               GTK_STOCK_OK,
2428                                               GTK_RESPONSE_ACCEPT,
2429                                               GTK_STOCK_CANCEL,
2430                                               GTK_RESPONSE_REJECT,
2431                                               NULL);
2432 #else
2433         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2434                                               NULL,
2435                                               GTK_DIALOG_MODAL,
2436                                               GTK_STOCK_CANCEL,
2437                                               GTK_RESPONSE_REJECT,
2438                                               GTK_STOCK_OK,
2439                                               GTK_RESPONSE_ACCEPT,
2440                                               NULL);
2441 #endif /* MODEST_PLATFORM_MAEMO */
2442
2443         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2444         
2445         gchar *server_name = modest_server_account_get_hostname (
2446                 modest_runtime_get_account_mgr(), server_account_name);
2447         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2448                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2449                 *cancel = TRUE;
2450                 return;
2451         }
2452         
2453         /* This causes a warning because the logical ID has no %s in it, 
2454          * though the translation does, but there is not much we can do about that: */
2455         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2456         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2457                             FALSE, FALSE, 0);
2458         g_free (txt);
2459         g_free (server_name);
2460         server_name = NULL;
2461
2462         /* username: */
2463         gchar *initial_username = modest_server_account_get_username (
2464                 modest_runtime_get_account_mgr(), server_account_name);
2465         
2466         GtkWidget *entry_username = gtk_entry_new ();
2467         if (initial_username)
2468                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2469         /* Dim this if a connection has ever succeeded with this username,
2470          * as per the UI spec: */
2471         const gboolean username_known = 
2472                 modest_server_account_get_username_has_succeeded(
2473                         modest_runtime_get_account_mgr(), server_account_name);
2474         gtk_widget_set_sensitive (entry_username, !username_known);
2475         
2476 #ifdef MODEST_PLATFORM_MAEMO
2477         /* Auto-capitalization is the default, so let's turn it off: */
2478         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2479         
2480         /* Create a size group to be used by all captions.
2481          * Note that HildonCaption does not create a default size group if we do not specify one.
2482          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2483         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2484         
2485         GtkWidget *caption = hildon_caption_new (sizegroup, 
2486                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2487         gtk_widget_show (entry_username);
2488         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2489                 FALSE, FALSE, MODEST_MARGIN_HALF);
2490         gtk_widget_show (caption);
2491 #else 
2492         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2493                             TRUE, FALSE, 0);
2494 #endif /* MODEST_PLATFORM_MAEMO */      
2495                             
2496         /* password: */
2497         GtkWidget *entry_password = gtk_entry_new ();
2498         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2499         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2500         
2501 #ifdef MODEST_PLATFORM_MAEMO
2502         /* Auto-capitalization is the default, so let's turn it off: */
2503         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2504                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2505         
2506         caption = hildon_caption_new (sizegroup, 
2507                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2508         gtk_widget_show (entry_password);
2509         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2510                 FALSE, FALSE, MODEST_MARGIN_HALF);
2511         gtk_widget_show (caption);
2512         g_object_unref (sizegroup);
2513 #else 
2514         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2515                             TRUE, FALSE, 0);
2516 #endif /* MODEST_PLATFORM_MAEMO */      
2517                                 
2518 /* This is not in the Maemo UI spec:
2519         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2520         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2521                             TRUE, FALSE, 0);
2522 */
2523
2524         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2525         
2526         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2527                 if (username) {
2528                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2529                         
2530                         modest_server_account_set_username (
2531                                  modest_runtime_get_account_mgr(), server_account_name, 
2532                                  *username);
2533                                  
2534                         const gboolean username_was_changed = 
2535                                 (strcmp (*username, initial_username) != 0);
2536                         if (username_was_changed) {
2537                                 g_warning ("%s: tinymail does not yet support changing the "
2538                                         "username in the get_password() callback.\n", __FUNCTION__);
2539                         }
2540                 }
2541                         
2542                 if (password) {
2543                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2544                         
2545                         /* We do not save the password in the configuration, 
2546                          * because this function is only called for passwords that should 
2547                          * not be remembered:
2548                         modest_server_account_set_password (
2549                                  modest_runtime_get_account_mgr(), server_account_name, 
2550                                  *password);
2551                         */
2552                 }
2553                 
2554                 if (cancel)
2555                         *cancel   = FALSE;
2556                         
2557         } else {
2558                 if (username)
2559                         *username = NULL;
2560                         
2561                 if (password)
2562                         *password = NULL;
2563                         
2564                 if (cancel)
2565                         *cancel   = TRUE;
2566         }
2567
2568 /* This is not in the Maemo UI spec:
2569         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2570                 *remember = TRUE;
2571         else
2572                 *remember = FALSE;
2573 */
2574
2575         gtk_widget_destroy (dialog);
2576         
2577         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2578 }
2579
2580 void
2581 modest_ui_actions_on_cut (GtkAction *action,
2582                           ModestWindow *window)
2583 {
2584         GtkWidget *focused_widget;
2585
2586         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2587         if (GTK_IS_EDITABLE (focused_widget)) {
2588                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2589         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2590                 GtkTextBuffer *buffer;
2591                 GtkClipboard *clipboard;
2592
2593                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2594                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2595                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2596                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2597         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2598                 modest_header_view_cut_selection (MODEST_HEADER_VIEW (focused_widget));
2599         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2600                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2601         }
2602 }
2603
2604 void
2605 modest_ui_actions_on_copy (GtkAction *action,
2606                            ModestWindow *window)
2607 {
2608         GtkClipboard *clipboard;
2609         GtkWidget *focused_widget;
2610
2611         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2612         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2613
2614         if (GTK_IS_LABEL (focused_widget)) {
2615                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2616         } else if (GTK_IS_EDITABLE (focused_widget)) {
2617                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2618         } else if (GTK_IS_HTML (focused_widget)) {
2619                 gtk_html_copy (GTK_HTML (focused_widget));
2620         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2621                 GtkTextBuffer *buffer;
2622                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2623                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2624                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2625         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2626                 TnyList *header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (focused_widget));
2627                 TnyIterator *iter = tny_list_create_iterator (header_list);
2628                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2629                 TnyFolder *folder = tny_header_get_folder (header);
2630                 TnyAccount *account = tny_folder_get_account (folder);
2631                 const gchar *proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2632                 /* If it's POP then ask */
2633                 gboolean ask = (modest_protocol_info_get_transport_store_protocol (proto_str) == 
2634                        MODEST_PROTOCOL_STORE_POP) ? TRUE : FALSE;
2635                 g_object_unref (account);
2636                 g_object_unref (folder);
2637                 g_object_unref (header);
2638                 g_object_unref (iter);
2639                 
2640                 /* Check that the messages have been previously downloaded */
2641                 gboolean continue_download = TRUE;
2642                 if (ask)
2643                         continue_download = download_uncached_messages (header_list, GTK_WINDOW (window));
2644                 if (continue_download)
2645                         modest_header_view_copy_selection (MODEST_HEADER_VIEW (focused_widget));
2646                 g_object_unref (header_list);
2647         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2648                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
2649         }    
2650
2651         /* Show information banner */
2652         modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
2653         
2654 }
2655
2656 void
2657 modest_ui_actions_on_undo (GtkAction *action,
2658                            ModestWindow *window)
2659 {
2660         ModestEmailClipboard *clipboard = NULL;
2661
2662         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2663                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2664         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2665                 /* Clear clipboard source */
2666                 clipboard = modest_runtime_get_email_clipboard ();
2667                 modest_email_clipboard_clear (clipboard);               
2668         }
2669         else {
2670                 g_return_if_reached ();
2671         }
2672 }
2673
2674 void
2675 modest_ui_actions_on_redo (GtkAction *action,
2676                            ModestWindow *window)
2677 {
2678         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2679                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
2680         }
2681         else {
2682                 g_return_if_reached ();
2683         }
2684 }
2685
2686
2687 static void
2688 paste_msgs_cb (const GObject *object, gpointer user_data)
2689 {
2690         g_return_if_fail (MODEST_IS_MAIN_WINDOW (object));
2691         g_return_if_fail (GTK_IS_WIDGET (user_data));
2692         
2693         /* destroy information note */
2694         gtk_widget_destroy (GTK_WIDGET(user_data));
2695 }
2696
2697 void
2698 modest_ui_actions_on_paste (GtkAction *action,
2699                             ModestWindow *window)
2700 {
2701         GtkWidget *focused_widget = NULL;
2702         GtkWidget *inf_note = NULL;
2703         ModestMailOperation *mail_op = NULL;
2704
2705         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2706         if (GTK_IS_EDITABLE (focused_widget)) {
2707                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
2708         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2709                 GtkTextBuffer *buffer;
2710                 GtkClipboard *clipboard;
2711
2712                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2713                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2714                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
2715         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2716                 ModestEmailClipboard *clipboard = NULL;
2717                 TnyFolder *src_folder = NULL;
2718                 TnyFolderStore *folder_store = NULL;
2719                 TnyList *data = NULL;           
2720                 gboolean delete = FALSE;
2721                 
2722                 /* Check clipboard source */
2723                 clipboard = modest_runtime_get_email_clipboard ();
2724                 if (modest_email_clipboard_cleared (clipboard)) 
2725                         return;
2726                 
2727                 /* Get elements to paste */
2728                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
2729
2730                 /* Create a new mail operation */
2731                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
2732                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2733                                                  mail_op);
2734                 
2735                 /* Get destination folder */
2736                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
2737
2738                 /* Launch notification */
2739                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
2740                                                              _CS("ckct_nw_pasting"));
2741                 if (inf_note != NULL)  {
2742                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
2743                         gtk_widget_show (GTK_WIDGET(inf_note));
2744                 }
2745
2746                 /* transfer messages  */
2747                 if (data != NULL) {
2748                         modest_mail_operation_xfer_msgs (mail_op, 
2749                                                          data,
2750                                                          TNY_FOLDER (folder_store),
2751                                                          delete,
2752                                                          paste_msgs_cb,
2753                                                          inf_note);
2754                         
2755                 } else if (src_folder != NULL) {                        
2756                         modest_mail_operation_xfer_folder (mail_op, 
2757                                                            src_folder,
2758                                                            folder_store,
2759                                                            delete,
2760                                                            paste_msgs_cb,
2761                                                            inf_note);
2762                 }
2763
2764                 /* Free */
2765                 if (data != NULL) 
2766                         g_object_unref (data);
2767                 if (src_folder != NULL) 
2768                         g_object_unref (src_folder);
2769                 if (folder_store != NULL) 
2770                         g_object_unref (folder_store);
2771         }
2772 }
2773
2774
2775 void
2776 modest_ui_actions_on_select_all (GtkAction *action,
2777                                  ModestWindow *window)
2778 {
2779         GtkWidget *focused_widget;
2780
2781         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2782         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
2783                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
2784         } else if (GTK_IS_LABEL (focused_widget)) {
2785                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
2786         } else if (GTK_IS_EDITABLE (focused_widget)) {
2787                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
2788         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2789                 GtkTextBuffer *buffer;
2790                 GtkTextIter start, end;
2791
2792                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2793                 gtk_text_buffer_get_start_iter (buffer, &start);
2794                 gtk_text_buffer_get_end_iter (buffer, &end);
2795                 gtk_text_buffer_select_range (buffer, &start, &end);
2796         } else if (GTK_IS_HTML (focused_widget)) {
2797                 gtk_html_select_all (GTK_HTML (focused_widget));
2798         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2799                 GtkWidget *header_view = focused_widget;
2800                 GtkTreeSelection *selection = NULL;
2801                 
2802                 if (!(MODEST_IS_HEADER_VIEW (focused_widget)))
2803                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
2804                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2805                                 
2806                 /* Select all messages */
2807                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
2808                 gtk_tree_selection_select_all (selection);
2809
2810                 /* Set focuse on header view */
2811                 gtk_widget_grab_focus (header_view);
2812         }
2813
2814 }
2815
2816 void
2817 modest_ui_actions_on_mark_as_read (GtkAction *action,
2818                                    ModestWindow *window)
2819 {       
2820         g_return_if_fail (MODEST_IS_WINDOW(window));
2821                 
2822         /* Mark each header as read */
2823         do_headers_action (window, headers_action_mark_as_read, NULL);
2824 }
2825
2826 void
2827 modest_ui_actions_on_mark_as_unread (GtkAction *action,
2828                                      ModestWindow *window)
2829 {       
2830         g_return_if_fail (MODEST_IS_WINDOW(window));
2831                 
2832         /* Mark each header as read */
2833         do_headers_action (window, headers_action_mark_as_unread, NULL);
2834 }
2835
2836 void
2837 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
2838                                   GtkRadioAction *selected,
2839                                   ModestWindow *window)
2840 {
2841         gint value;
2842
2843         value = gtk_radio_action_get_current_value (selected);
2844         if (MODEST_IS_WINDOW (window)) {
2845                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
2846         }
2847 }
2848
2849 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
2850                                                         GtkRadioAction *selected,
2851                                                         ModestWindow *window)
2852 {
2853         TnyHeaderFlags flags;
2854         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2855
2856         flags = gtk_radio_action_get_current_value (selected);
2857         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
2858 }
2859
2860 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
2861                                                            GtkRadioAction *selected,
2862                                                            ModestWindow *window)
2863 {
2864         gint file_format;
2865
2866         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2867
2868         file_format = gtk_radio_action_get_current_value (selected);
2869         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
2870 }
2871
2872
2873 void     
2874 modest_ui_actions_on_zoom_plus (GtkAction *action,
2875                                 ModestWindow *window)
2876 {
2877         g_return_if_fail (MODEST_IS_WINDOW (window));
2878
2879         modest_window_zoom_plus (MODEST_WINDOW (window));
2880 }
2881
2882 void     
2883 modest_ui_actions_on_zoom_minus (GtkAction *action,
2884                                  ModestWindow *window)
2885 {
2886         g_return_if_fail (MODEST_IS_WINDOW (window));
2887
2888         modest_window_zoom_minus (MODEST_WINDOW (window));
2889 }
2890
2891 void     
2892 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
2893                                            ModestWindow *window)
2894 {
2895         ModestWindowMgr *mgr;
2896         gboolean fullscreen, active;
2897         g_return_if_fail (MODEST_IS_WINDOW (window));
2898
2899         mgr = modest_runtime_get_window_mgr ();
2900
2901         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
2902         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2903
2904         if (active != fullscreen) {
2905                 modest_window_mgr_set_fullscreen_mode (mgr, active);
2906                 gtk_window_present (GTK_WINDOW (window));
2907         }
2908 }
2909
2910 void
2911 modest_ui_actions_on_change_fullscreen (GtkAction *action,
2912                                         ModestWindow *window)
2913 {
2914         ModestWindowMgr *mgr;
2915         gboolean fullscreen;
2916
2917         g_return_if_fail (MODEST_IS_WINDOW (window));
2918
2919         mgr = modest_runtime_get_window_mgr ();
2920         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2921         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
2922
2923         gtk_window_present (GTK_WINDOW (window));
2924 }
2925
2926 /* 
2927  * Used by modest_ui_actions_on_details to call do_headers_action 
2928  */
2929 static void
2930 headers_action_show_details (TnyHeader *header, 
2931                              ModestWindow *window,
2932                              gpointer user_data)
2933
2934 {
2935         GtkWidget *dialog;
2936         
2937         /* Create dialog */
2938         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
2939
2940         /* Run dialog */
2941         gtk_widget_show_all (dialog);
2942         gtk_dialog_run (GTK_DIALOG (dialog));
2943
2944         gtk_widget_destroy (dialog);
2945 }
2946
2947 /*
2948  * Show the folder details in a ModestDetailsDialog widget
2949  */
2950 static void
2951 show_folder_details (TnyFolder *folder, 
2952                      GtkWindow *window)
2953 {
2954         GtkWidget *dialog;
2955         
2956         /* Create dialog */
2957         dialog = modest_details_dialog_new_with_folder (window, folder);
2958
2959         /* Run dialog */
2960         gtk_widget_show_all (dialog);
2961         gtk_dialog_run (GTK_DIALOG (dialog));
2962
2963         gtk_widget_destroy (dialog);
2964 }
2965
2966 /*
2967  * Show the header details in a ModestDetailsDialog widget
2968  */
2969 void     
2970 modest_ui_actions_on_details (GtkAction *action, 
2971                               ModestWindow *win)
2972 {
2973         TnyList * headers_list;
2974         TnyIterator *iter;
2975         TnyHeader *header;              
2976
2977         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
2978                 TnyMsg *msg;
2979
2980                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
2981                 if (!msg)
2982                         return;
2983                 g_object_unref (msg);           
2984
2985                 headers_list = get_selected_headers (win);
2986                 if (!headers_list)
2987                         return;
2988
2989                 iter = tny_list_create_iterator (headers_list);
2990
2991                 header = TNY_HEADER (tny_iterator_get_current (iter));
2992                 headers_action_show_details (header, win, NULL);
2993                 g_object_unref (header);
2994
2995                 g_object_unref (iter);
2996                 g_object_unref (headers_list);
2997
2998         } else if (MODEST_IS_MAIN_WINDOW (win)) {
2999                 GtkWidget *folder_view, *header_view;
3000
3001                 /* Check which widget has the focus */
3002                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3003                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
3004                 if (gtk_widget_is_focus (folder_view)) {
3005                         TnyFolderStore *folder_store
3006                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3007                         if (!folder_store) {
3008                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3009                                 return; 
3010                         }
3011                         /* Show only when it's a folder */
3012                         /* This function should not be called for account items, 
3013                          * because we dim the menu item for them. */
3014                         if (TNY_IS_FOLDER (folder_store)) {
3015                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3016                         }
3017
3018                         g_object_unref (folder_store);
3019
3020                 } else {
3021                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3022                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3023                         /* Show details of each header */
3024                         do_headers_action (win, headers_action_show_details, header_view);
3025                 }
3026         }
3027 }
3028
3029 void     
3030 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3031                                      ModestMsgEditWindow *window)
3032 {
3033         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3034
3035         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3036 }
3037
3038 void     
3039 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3040                                       ModestMsgEditWindow *window)
3041 {
3042         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3043
3044         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3045 }
3046
3047 void
3048 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3049                                        ModestMainWindow *main_window)
3050 {
3051         ModestConf *conf;
3052         
3053         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3054
3055         conf = modest_runtime_get_conf ();
3056         
3057         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
3058                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3059         else
3060                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3061 }
3062
3063 void 
3064 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3065                                      ModestWindow *window)
3066 {
3067         gboolean active, fullscreen = FALSE;
3068         ModestWindowMgr *mgr;
3069
3070         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3071
3072         /* Check if we want to toggle the toolbar vuew in fullscreen
3073            or normal mode */
3074         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3075                      "ViewShowToolbarFullScreen")) {
3076                 fullscreen = TRUE;
3077         }
3078
3079         /* Toggle toolbar */
3080         mgr = modest_runtime_get_window_mgr ();
3081         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
3082 }
3083
3084 void     
3085 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3086                                            ModestMsgEditWindow *window)
3087 {
3088         modest_msg_edit_window_select_font (window);
3089 }
3090
3091 void
3092 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3093                                                   const gchar *display_name,
3094                                                   GtkWindow *window)
3095 {
3096         /* Do not change the application name if the widget has not
3097            the focus. This callback could be called even if the folder
3098            view has not the focus, because the handled signal could be
3099            emitted when the folder view is redrawn */
3100         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3101                 if (display_name)
3102                         gtk_window_set_title (window, display_name);
3103                 else
3104                         gtk_window_set_title (window, " ");
3105         }
3106 }
3107
3108 void
3109 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3110 {
3111         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3112         modest_msg_edit_window_select_contacts (window);
3113 }
3114
3115 void
3116 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3117 {
3118         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3119         modest_msg_edit_window_check_names (window);
3120 }
3121
3122
3123 static GtkWidget*
3124 create_move_to_dialog (ModestWindow *win,
3125                        GtkWidget *folder_view,
3126                        GtkWidget **tree_view)
3127 {
3128         GtkWidget *dialog, *scroll;
3129
3130         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3131                                               GTK_WINDOW (win),
3132                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3133                                               GTK_STOCK_OK,
3134                                               GTK_RESPONSE_ACCEPT,
3135                                               GTK_STOCK_CANCEL,
3136                                               GTK_RESPONSE_REJECT,
3137                                               NULL);
3138
3139         /* Create scrolled window */
3140         scroll = gtk_scrolled_window_new (NULL, NULL);
3141         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3142                                          GTK_POLICY_AUTOMATIC,
3143                                          GTK_POLICY_AUTOMATIC);
3144
3145         /* Create folder view */
3146         *tree_view = modest_platform_create_folder_view (NULL);
3147
3148         /* It could happen that we're trying to move a message from a
3149            window (msg window for example) after the main window was
3150            closed, so we can not just get the model of the folder
3151            view */
3152         if (MODEST_IS_FOLDER_VIEW (folder_view))
3153                 gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
3154                                          gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
3155         else
3156                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
3157                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3158
3159         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3160
3161         /* Add scroll to dialog */
3162         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
3163                             scroll, FALSE, FALSE, 0);
3164
3165         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3166
3167         /* Select INBOX or local account */
3168         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (*tree_view));
3169
3170         return dialog;
3171 }
3172
3173 /*
3174  * Returns TRUE if at least one of the headers of the list belongs to
3175  * a message that has been fully retrieved.
3176  */
3177 static gboolean
3178 has_retrieved_msgs (TnyList *list)
3179 {
3180         TnyIterator *iter;
3181         gboolean found = FALSE;
3182
3183         iter = tny_list_create_iterator (list);
3184         while (tny_iterator_is_done (iter) && !found) {
3185                 TnyHeader *header;
3186                 TnyHeaderFlags flags;
3187
3188                 header = TNY_HEADER (tny_iterator_get_current (iter));
3189                 flags = tny_header_get_flags (header);
3190                 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
3191                         found = TRUE;
3192
3193                 if (!found)
3194                         tny_iterator_next (iter);
3195         }
3196         g_object_unref (iter);
3197
3198         return found;
3199 }
3200
3201 /*
3202  * Shows a confirmation dialog to the user when we're moving messages
3203  * from a remote server to the local storage. Returns the dialog
3204  * response. If it's other kind of movement the it always returns
3205  * GTK_RESPONSE_OK
3206  */
3207 static gint
3208 msgs_move_to_confirmation (GtkWindow *win,
3209                            TnyFolder *dest_folder,
3210                            TnyList *headers)
3211 {
3212         gint response = GTK_RESPONSE_OK;
3213
3214         /* If the destination is a local folder */
3215         if (modest_tny_folder_is_local_folder (dest_folder)) {
3216                 TnyFolder *src_folder;
3217                 TnyIterator *iter;
3218                 TnyHeader *header;
3219
3220                 /* Get source folder */
3221                 iter = tny_list_create_iterator (headers);
3222                 header = TNY_HEADER (tny_iterator_get_current (iter));
3223                 src_folder = tny_header_get_folder (header);
3224                 g_object_unref (header);
3225                 g_object_unref (iter);
3226
3227                 /* if no src_folder, message may be an attahcment */
3228                 if (src_folder == NULL) 
3229                         return GTK_RESPONSE_CANCEL;
3230
3231                 /* If the source is a remote folder */
3232                 if (!modest_tny_folder_is_local_folder (src_folder)) {
3233                         const gchar *message;
3234                         
3235                         if (has_retrieved_msgs (headers))
3236                                 message = ngettext ("mcen_nc_move_retrieve", "mcen_nc_move_retrieves",
3237                                                     tny_list_get_length (headers));
3238                         else 
3239                                 message = ngettext ("mcen_nc_move_header", "mcen_nc_move_headers",
3240                                                     tny_list_get_length (headers));
3241
3242                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
3243                                                                             (const gchar *) message);
3244                 }
3245                 g_object_unref (src_folder);
3246         }
3247         return response;
3248 }
3249
3250
3251
3252 static void
3253 transfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
3254 {
3255         ModestMsgViewWindow *self = NULL;
3256         gboolean last, first;
3257
3258         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
3259         self = MODEST_MSG_VIEW_WINDOW (object);
3260         
3261         last = modest_msg_view_window_last_message_selected (self);
3262         first = modest_msg_view_window_first_message_selected (self);   
3263         if (last & first) {
3264                 /* No more messages to view, so close this window */
3265 /*              gboolean ret_value; */
3266 /*              g_signal_emit_by_name (G_OBJECT (self), "delete-event", NULL, &ret_value); */
3267                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
3268         } else if (last)
3269                 modest_msg_view_window_select_previous_message (self);
3270         else 
3271                 modest_msg_view_window_select_next_message (self);
3272 }
3273
3274 void
3275 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
3276                                              gpointer user_data)
3277 {
3278         GObject *win = modest_mail_operation_get_source (mail_op);
3279         const GError *error = NULL;
3280         const gchar *message = NULL;
3281         
3282         /* Get error message */
3283         error = modest_mail_operation_get_error (mail_op);
3284         if (error != NULL && error->message != NULL) {
3285                 message = error->message;
3286         } else {
3287                 message = _("mail_in_ui_folder_move_target_error");
3288         }
3289         
3290         /* Show notification dialog */
3291         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
3292         g_object_unref (win);
3293 }
3294
3295 void
3296 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
3297                                               gpointer user_data)
3298 {
3299         GObject *win = modest_mail_operation_get_source (mail_op);
3300         const GError *error = modest_mail_operation_get_error (mail_op);
3301
3302         g_return_if_fail (error != NULL);
3303         if (error->message != NULL)             
3304                 g_printerr ("modest: %s\n", error->message);
3305         else
3306                 g_printerr ("modest: unkonw error on send&receive operation");
3307
3308         /* Show error message */
3309 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
3310 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3311 /*                                                      _CS("sfil_ib_unable_to_receive")); */
3312 /*      else  */
3313 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3314 /*                                                      _CS("sfil_ib_unable_to_send")); */
3315         g_object_unref (win);
3316 }
3317
3318 static void
3319 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
3320                        TnyHeader *header, 
3321                        TnyMsg *msg, 
3322                        gpointer user_data)
3323 {
3324         TnyList *parts;
3325         TnyIterator *iter;
3326         gint pending_purges = 0;
3327         gboolean some_purged = FALSE;
3328         ModestWindow *win = MODEST_WINDOW (user_data);
3329
3330         /* If there was any error */
3331         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
3332                 return;
3333
3334         /* Once the message has been retrieved for purging, we check if
3335          * it's all ok for purging */
3336
3337         parts = tny_simple_list_new ();
3338         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
3339         iter = tny_list_create_iterator (parts);
3340
3341         while (!tny_iterator_is_done (iter)) {
3342                 TnyMimePart *part;
3343                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3344                 if (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)) {
3345                         if (tny_mime_part_is_purged (part))
3346                                 some_purged = TRUE;
3347                         else
3348                                 pending_purges++;
3349                 }
3350                 tny_iterator_next (iter);
3351         }
3352
3353         if (pending_purges>0) {
3354                 gint response;
3355                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
3356
3357                 if (response == GTK_RESPONSE_OK) {
3358                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
3359                         tny_iterator_first (iter);
3360                         while (!tny_iterator_is_done (iter)) {
3361                                 TnyMimePart *part;
3362                                 
3363                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3364                                 if (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))
3365                                         tny_mime_part_set_purged (part);
3366                                 tny_iterator_next (iter);
3367                         }
3368                         
3369                         tny_msg_rewrite_cache (msg);
3370                 }
3371         } else {
3372                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
3373         }
3374
3375         /* remove attachments */
3376         tny_iterator_first (iter);
3377         while (!tny_iterator_is_done (iter)) {
3378                 TnyMimePart *part;
3379                         
3380                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3381                 g_object_unref (part);
3382                 tny_iterator_next (iter);
3383         }
3384
3385         g_object_unref (iter);
3386         g_object_unref (parts);
3387 }
3388
3389 static void
3390 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
3391                                                      ModestMainWindow *win)
3392 {
3393         GtkWidget *header_view;
3394         TnyList *header_list;
3395         TnyIterator *iter;
3396         TnyHeader *header;
3397         TnyHeaderFlags flags;
3398         ModestWindow *msg_view_window =  NULL;
3399         gboolean found;
3400
3401         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3402
3403         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3404                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3405
3406         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
3407
3408         if (tny_list_get_length (header_list) == 1) {
3409                 iter = tny_list_create_iterator (header_list);
3410                 header = TNY_HEADER (tny_iterator_get_current (iter));
3411                 g_object_unref (iter);
3412         } else {
3413                 return;
3414         }
3415
3416         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
3417                                                           header, &msg_view_window);
3418         flags = tny_header_get_flags (header);
3419         if (!(flags & TNY_HEADER_FLAG_CACHED))
3420                 return;
3421         if (found) {
3422                 if (msg_view_window != NULL) 
3423                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
3424                 else {
3425                         /* do nothing; uid was registered before, so window is probably on it's way */
3426                         g_warning ("debug: header %p has already been registered", header);
3427                 }
3428         } else {
3429                 ModestMailOperation *mail_op = NULL;
3430                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header);
3431                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
3432                                                                          G_OBJECT (win),
3433                                                                          modest_ui_actions_get_msgs_full_error_handler,
3434                                                                          NULL);
3435                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3436                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
3437                 
3438                 g_object_unref (mail_op);
3439         }
3440         if (header)
3441                 g_object_unref (header);
3442         if (header_list)
3443                 g_object_unref (header_list);
3444 }
3445
3446 /*
3447  * UI handler for the "Move to" action when invoked from the
3448  * ModestMainWindow
3449  */
3450 static void 
3451 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
3452                                           ModestMainWindow *win)
3453 {
3454         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
3455         GtkWidget *header_view = NULL;
3456         gint result = 0;
3457         TnyFolderStore *folder_store = NULL;
3458         ModestMailOperation *mail_op = NULL;
3459
3460         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3461
3462         /* Get the folder view */
3463         folder_view = modest_main_window_get_child_widget (win,
3464                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
3465                                                            
3466         TnyFolderStore *src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3467         
3468         /* Offer the connection dialog if necessary, if the source folder is in a networked account: */
3469         if (!modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), src_folder)) {
3470                 if (src_folder) {
3471                         g_object_unref (src_folder);
3472                 }
3473                 
3474                 return;
3475         }
3476
3477         /* Get header view */
3478         header_view = modest_main_window_get_child_widget (win,
3479                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3480
3481         /* Create and run the dialog */
3482         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);
3483         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
3484         result = gtk_dialog_run (GTK_DIALOG(dialog));
3485         g_object_ref (tree_view);
3486
3487         /* We do this to save an indentation level ;-) */
3488         if (result != GTK_RESPONSE_ACCEPT)
3489                 goto end;
3490
3491         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
3492
3493         if (TNY_IS_ACCOUNT (folder_store) && 
3494             !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (folder_store))
3495                 goto end;
3496
3497         /* Offer the connection dialog if necessary: */
3498         if (!modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), folder_store)) {
3499                         goto end;
3500         }
3501
3502         /* Get folder or messages to transfer */
3503         if (gtk_widget_is_focus (folder_view)) {
3504                 
3505                 /* Clean folder on header view before moving it */
3506                 modest_header_view_clear (MODEST_HEADER_VIEW (header_view)); 
3507
3508                 if (TNY_IS_FOLDER (src_folder)) {
3509                         mail_op = 
3510                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3511                                                                        G_OBJECT(win),
3512                                                                        modest_ui_actions_move_folder_error_handler,
3513                                                                        NULL);
3514                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3515
3516                         modest_mail_operation_xfer_folder (mail_op, 
3517                                                            TNY_FOLDER (src_folder),
3518                                                            folder_store,
3519                                                            TRUE, NULL, NULL);
3520                         /* Unref mail operation */
3521                         g_object_unref (G_OBJECT (mail_op));
3522                 } else {
3523                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);       
3524                 }
3525         } else {
3526                 if (gtk_widget_is_focus (header_view)) {
3527                         TnyList *headers = NULL;
3528                         gint response = 0;
3529
3530                         /* TODO: Check for connection if the headers are on a network account. */
3531                         headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
3532
3533                         /* Ask for user confirmation */
3534                         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
3535                                                               TNY_FOLDER (folder_store), 
3536                                                               headers);
3537
3538                         /* Transfer messages */
3539                         if (response == GTK_RESPONSE_OK) {
3540                                 mail_op = 
3541                                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3542                                                                                        G_OBJECT(win),
3543                                                                                        modest_ui_actions_move_folder_error_handler,
3544                                                                                        NULL);
3545                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3546                                                                  mail_op);
3547
3548                                 modest_mail_operation_xfer_msgs (mail_op, 
3549                                                                  headers,
3550                                                                  TNY_FOLDER (folder_store),
3551                                                                  TRUE,
3552                                                                  NULL,
3553                                                                  NULL);
3554
3555                                 g_object_unref (G_OBJECT (mail_op));
3556                         }
3557                         g_object_unref (headers);
3558                 }
3559         }
3560         
3561  end:
3562     if (src_folder)
3563         g_object_unref (src_folder);
3564                         
3565         if (folder_store)
3566                 g_object_unref (folder_store);
3567
3568         gtk_widget_destroy (dialog);
3569 }
3570
3571
3572 /*
3573  * UI handler for the "Move to" action when invoked from the
3574  * ModestMsgViewWindow
3575  */
3576 static void 
3577 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
3578                                               ModestMsgViewWindow *win)
3579 {
3580         GtkWidget *dialog, *folder_view, *tree_view = NULL;
3581         gint result = 0;
3582         ModestMainWindow *main_window = NULL;
3583         TnyHeader *header = NULL;
3584         TnyList *headers = NULL;
3585
3586         /* Get the folder view */
3587         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
3588         if (main_window)
3589                 folder_view = modest_main_window_get_child_widget (main_window,
3590                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
3591         else
3592                 folder_view = NULL;
3593
3594         /* Create and run the dialog */
3595         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);  
3596         result = gtk_dialog_run (GTK_DIALOG(dialog));
3597
3598         if (result == GTK_RESPONSE_ACCEPT) {
3599                 TnyFolderStore *folder_store;
3600                 gint response;
3601
3602                 /* Create header list */
3603                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
3604                 g_return_if_fail (header != NULL);
3605
3606                 /* Offer the connection dialog if necessary: */
3607                 /* TODO: What's the extra g_object_ref() for? Isn't this leaking a ref? */
3608                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (g_object_ref (tree_view)));
3609                 TnyFolder *header_folder = tny_header_get_folder(header);
3610                 if (modest_platform_connect_and_wait_if_network_folderstore (NULL, folder_store) &&
3611                     modest_platform_connect_and_wait_if_network_folderstore (NULL, TNY_FOLDER_STORE (header_folder))) {
3612                         
3613                         headers = tny_simple_list_new ();
3614                         tny_list_prepend (headers, G_OBJECT (header));
3615                         g_object_unref (header);
3616
3617                         /* Ask user for confirmation. MSG-NOT404 */
3618                         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
3619                                                       TNY_FOLDER (folder_store), 
3620                                                       headers);
3621
3622                         /* Transfer current msg */
3623                         if (response == GTK_RESPONSE_OK) {
3624                                 ModestMailOperation *mail_op;
3625
3626                                 /* Create mail op */
3627                                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
3628                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3629                                                          mail_op);
3630                         
3631                                 /* Transfer messages */
3632                                 modest_mail_operation_xfer_msgs (mail_op, 
3633                                                          headers,
3634                                                          TNY_FOLDER (folder_store),
3635                                                          TRUE,
3636                                                          transfer_msgs_from_viewer_cb,
3637                                                          NULL);
3638                                 g_object_unref (G_OBJECT (mail_op));
3639                         }
3640                 }
3641                 
3642                 if (header_folder)
3643                         g_object_unref (header_folder);
3644
3645                 if (headers)
3646                         g_object_unref (headers);
3647                         
3648                 if (folder_store)
3649                         g_object_unref (folder_store);
3650         }
3651         
3652         gtk_widget_destroy (dialog);
3653 }
3654
3655 void 
3656 modest_ui_actions_on_move_to (GtkAction *action, 
3657                               ModestWindow *win)
3658 {
3659         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
3660                           MODEST_IS_MSG_VIEW_WINDOW (win));
3661
3662         if (MODEST_IS_MAIN_WINDOW (win)) 
3663                 modest_ui_actions_on_main_window_move_to (action, 
3664                                                           MODEST_MAIN_WINDOW (win));
3665         else
3666                 modest_ui_actions_on_msg_view_window_move_to (action, 
3667                                                               MODEST_MSG_VIEW_WINDOW (win));
3668 }
3669
3670 /*
3671  * Calls #HeadersFunc for each header already selected in the main
3672  * window or the message currently being shown in the msg view window
3673  */
3674 static void
3675 do_headers_action (ModestWindow *win, 
3676                    HeadersFunc func,
3677                    gpointer user_data)
3678 {
3679         TnyList *headers_list;
3680         TnyIterator *iter;
3681         TnyHeader *header;
3682         TnyFolder *folder;
3683
3684         /* Get headers */
3685         headers_list = get_selected_headers (win);
3686         if (!headers_list)
3687                 return;
3688
3689         /* Get the folder */
3690         iter = tny_list_create_iterator (headers_list);
3691         header = TNY_HEADER (tny_iterator_get_current (iter));
3692         folder = tny_header_get_folder (header);
3693         g_object_unref (header);
3694
3695         /* Call the function for each header */
3696         while (!tny_iterator_is_done (iter)) {
3697                 header = TNY_HEADER (tny_iterator_get_current (iter));
3698                 func (header, win, user_data);
3699                 g_object_unref (header);
3700                 tny_iterator_next (iter);
3701         }
3702
3703         /* Trick: do a poke status in order to speed up the signaling
3704            of observers */
3705         tny_folder_poke_status (folder);
3706
3707         /* Frees */
3708         g_object_unref (folder);
3709         g_object_unref (iter);
3710         g_object_unref (headers_list);
3711 }
3712
3713 void 
3714 modest_ui_actions_view_attachment (GtkAction *action,
3715                                    ModestWindow *window)
3716 {
3717         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3718                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
3719         } else {
3720                 /* not supported window for this action */
3721                 g_return_if_reached ();
3722         }
3723 }
3724
3725 void
3726 modest_ui_actions_save_attachments (GtkAction *action,
3727                                     ModestWindow *window)
3728 {
3729         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3730                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
3731         } else {
3732                 /* not supported window for this action */
3733                 g_return_if_reached ();
3734         }
3735 }
3736
3737 void
3738 modest_ui_actions_remove_attachments (GtkAction *action,
3739                                       ModestWindow *window)
3740 {
3741         if (MODEST_IS_MAIN_WINDOW (window)) {
3742                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
3743         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3744                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
3745         } else {
3746                 /* not supported window for this action */
3747                 g_return_if_reached ();
3748         }
3749 }
3750
3751 void 
3752 modest_ui_actions_on_settings (GtkAction *action, 
3753                                ModestWindow *win)
3754 {
3755         GtkWidget *dialog;
3756
3757         dialog = modest_platform_get_global_settings_dialog ();
3758         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
3759         gtk_widget_show_all (dialog);
3760
3761         gtk_dialog_run (GTK_DIALOG (dialog));
3762
3763         gtk_widget_destroy (dialog);
3764 }
3765
3766 void 
3767 modest_ui_actions_on_help (GtkAction *action, 
3768                            ModestWindow *win)
3769 {
3770         const gchar *help_id = NULL;
3771
3772         if (MODEST_IS_MAIN_WINDOW (win)) {
3773                 const gchar *action_name;
3774                 action_name = gtk_action_get_name (action);
3775
3776                 if (!strcmp (action_name, "FolderViewCSMHelp") ||
3777                     !strcmp (action_name, "HeaderViewCSMHelp")) {
3778                         GtkWidget *folder_view;
3779                         TnyFolderStore *folder_store;
3780                         /* Get selected folder */
3781                         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3782                                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
3783                         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3784
3785                         /* Switch help_id */
3786                         if (TNY_IS_FOLDER (folder_store)) {
3787                                 switch (tny_folder_get_folder_type (TNY_FOLDER (folder_store))) {
3788                                 case TNY_FOLDER_TYPE_NORMAL:
3789                                         help_id = "applications_email_userfolder";
3790                                         break;
3791                                 case TNY_FOLDER_TYPE_INBOX:
3792                                         help_id = "applications_email_inbox";
3793                                         break;
3794                                 case TNY_FOLDER_TYPE_OUTBOX:
3795                                         help_id = "applications_email_outbox";
3796                                         break;
3797                                 case TNY_FOLDER_TYPE_SENT:
3798                                         help_id = "applications_email_sent";
3799                                         break;
3800                                 case TNY_FOLDER_TYPE_DRAFTS:
3801                                         help_id = "applications_email_drafts";
3802                                         break;
3803                                 case TNY_FOLDER_TYPE_ARCHIVE:
3804                                         help_id = "applications_email_archive";
3805                                         break;
3806                                 default:
3807                                         help_id = "applications_email_mainview";
3808                                 }
3809                         } else {
3810                                 help_id = "applications_email_mainview";        
3811                         }
3812                         g_object_unref (folder_store);
3813                 } else {
3814                         help_id = "applications_email_mainview";        
3815                 }
3816         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3817                 help_id = "applications_email_viewer";
3818         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
3819                 help_id = "applications_email_editor";
3820
3821         modest_platform_show_help (GTK_WINDOW (win), help_id);
3822 }
3823
3824 void 
3825 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
3826                                             ModestWindow *window)
3827 {
3828         ModestMailOperation *mail_op;
3829         TnyList *headers;
3830
3831         /* Get headers */
3832         headers = get_selected_headers (window);
3833         if (!headers)
3834                 return;
3835
3836         /* Create mail operation */
3837         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3838                                                                  G_OBJECT (window),
3839                                                                  modest_ui_actions_get_msgs_full_error_handler, 
3840                                                                  NULL);
3841         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3842         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
3843
3844         /* Frees */
3845         g_object_unref (headers);
3846         g_object_unref (mail_op);
3847 }
3848
3849 void
3850 modest_ui_actions_on_email_menu_activated (GtkAction *action,
3851                                           ModestWindow *window)
3852 {
3853         g_return_if_fail (MODEST_IS_WINDOW (window));
3854
3855         /* Update dimmed */     
3856         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3857 }
3858
3859 void
3860 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
3861                                           ModestWindow *window)
3862 {
3863         g_return_if_fail (MODEST_IS_WINDOW (window));
3864
3865         /* Update dimmed */     
3866         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3867 }
3868
3869 void
3870 modest_ui_actions_on_view_menu_activated (GtkAction *action,
3871                                           ModestWindow *window)
3872 {
3873         g_return_if_fail (MODEST_IS_WINDOW (window));
3874
3875         /* Update dimmed */     
3876         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3877 }
3878
3879 void
3880 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
3881                                           ModestWindow *window)
3882 {
3883         g_return_if_fail (MODEST_IS_WINDOW (window));
3884
3885         /* Update dimmed */     
3886         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3887 }
3888
3889 void
3890 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
3891                                           ModestWindow *window)
3892 {
3893         g_return_if_fail (MODEST_IS_WINDOW (window));
3894
3895         /* Update dimmed */     
3896         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3897 }
3898
3899 void
3900 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
3901                                                  ModestWindow *window)
3902 {
3903         g_return_if_fail (MODEST_IS_WINDOW (window));
3904
3905         /* Update dimmed */     
3906         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3907 }
3908
3909 void
3910 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
3911                                                      ModestWindow *window)
3912 {
3913         g_return_if_fail (MODEST_IS_WINDOW (window));
3914
3915         /* Update dimmed */     
3916         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3917 }
3918
3919 void
3920 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
3921                                                      ModestWindow *window)
3922 {
3923         g_return_if_fail (MODEST_IS_WINDOW (window));
3924
3925         /* Update dimmed */     
3926         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3927 }
3928
3929 void
3930 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
3931 {
3932         g_return_if_fail (MODEST_IS_WINDOW (window));
3933
3934         /* Update dimmed */     
3935         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
3936 }
3937
3938 void
3939 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
3940 {
3941         g_return_if_fail (MODEST_IS_WINDOW (window));
3942
3943         modest_platform_show_search_messages (GTK_WINDOW (window));
3944 }
3945
3946 void     
3947 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
3948 {
3949         g_return_if_fail (MODEST_IS_WINDOW (win));
3950         modest_platform_show_addressbook (GTK_WINDOW (win));
3951 }
3952
3953
3954 void
3955 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
3956                                           ModestWindow *window)
3957 {
3958         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3959
3960         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
3961 }
3962
3963 static void 
3964 _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
3965                                    ModestMailOperationState *state,
3966                                    gpointer user_data)
3967 {
3968         g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
3969
3970         /* Set send/receive operation finished */       
3971         if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3972                 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));
3973         
3974 }
3975
3976