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