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