bfd986d2133ad4fac236a1b0003540a4383b6822
[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                 return;
705         }
706
707         parent_win = (ModestWindow *) modest_mail_operation_get_source (mail_op);
708         folder = tny_header_get_folder (header);
709
710         /* Mark header as read */
711         headers_action_mark_as_read (header, MODEST_WINDOW(parent_win), NULL);
712
713         /* Get account */
714         account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
715         if (!account)
716                 account =  g_strdup (modest_window_get_active_account (MODEST_WINDOW (parent_win)));
717         
718         /* Gets folder type (OUTBOX headers will be opened in edit window */
719         if (modest_tny_folder_is_local_folder (folder))
720                 folder_type = modest_tny_folder_get_local_folder_type (folder);
721
722         /* If the header is in the drafts folder then open the editor,
723            else the message view window */
724         if (folder_type == TNY_FOLDER_TYPE_DRAFTS) {
725                 /* we cannot edit without a valid account... */
726                 if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
727                         run_account_setup_wizard(parent_win);
728                         goto cleanup;
729                 }
730                 win = modest_msg_edit_window_new (msg, account);
731         } else {
732                 gchar *uid = modest_tny_folder_get_header_unique_id (header);
733                 
734                 if (MODEST_IS_MAIN_WINDOW (parent_win)) {
735                         GtkWidget *header_view;
736                         GtkTreeSelection *sel;
737                         GList *sel_list = NULL;
738                         GtkTreeModel *model;
739                         
740                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(parent_win),
741                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
742
743                         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
744                         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
745
746                         if (sel_list != NULL) {
747                                 GtkTreeRowReference *row_reference;
748
749                                 row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
750                                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
751                                 g_list_free (sel_list);
752                                 
753                                 win = modest_msg_view_window_new_with_header_model (msg, 
754                                                                                     account,
755                                                                                     (const gchar*) uid,
756                                                                                     model, 
757                                                                                     row_reference);
758                                 gtk_tree_row_reference_free (row_reference);
759                         } else {
760                                 win = modest_msg_view_window_new (msg, account, (const gchar*) uid);
761                         }
762                 } else {
763                         win = modest_msg_view_window_new (msg, account, (const gchar*) uid);
764                 }
765                 g_free (uid);
766         }
767         
768         /* Register and show new window */
769         if (win != NULL) {
770                 mgr = modest_runtime_get_window_mgr ();
771                 modest_window_mgr_register_window (mgr, win);
772                 g_object_unref (win);
773                 gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent_win));
774                 gtk_widget_show_all (GTK_WIDGET(win));
775         }
776
777         /* Update toolbar dimming state */
778         if (MODEST_IS_MAIN_WINDOW (parent_win)) {
779                 modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (parent_win));
780         }
781
782 cleanup:
783         /* Free */
784         g_free(account);
785         g_object_unref (parent_win);
786         g_object_unref (folder);
787 }
788
789 void
790 modest_ui_actions_get_msgs_full_error_handler (ModestMailOperation *mail_op,
791                                                gpointer user_data)
792 {
793         const GError *error;
794         GObject *win = modest_mail_operation_get_source (mail_op);
795
796         error = modest_mail_operation_get_error (mail_op);
797         printf ("DEBUG: %s: Error: code=%d, text=%s\n", __FUNCTION__, error->code, error->message);
798  
799         if (error->code == MODEST_MAIL_OPERATION_ERROR_MESSAGE_SIZE_LIMIT) {
800
801                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
802                                                         error->message);
803         } else {
804                 modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
805                                                         _("mail_ni_ui_folder_get_msg_folder_error"));
806         }
807
808         if (win)
809                 g_object_unref (win);
810 }
811
812 /*
813  * This function is used by both modest_ui_actions_on_open and
814  * modest_ui_actions_on_header_activated. This way we always do the
815  * same when trying to open messages.
816  */
817 static void
818 _modest_ui_actions_open (TnyList *headers, ModestWindow *win)
819 {
820         ModestWindowMgr *mgr = NULL;
821         TnyIterator *iter = NULL;
822         ModestMailOperation *mail_op1 = NULL;
823         ModestMailOperation *mail_op2 = NULL;
824         TnyList *not_opened_headers = NULL;
825         TnyList *not_opened_cached_headers = NULL;
826         TnyHeaderFlags flags;
827                 
828         /* Look if we already have a message view for each header. If
829            true, then remove the header from the list of headers to
830            open */
831         mgr = modest_runtime_get_window_mgr ();
832         iter = tny_list_create_iterator (headers);
833         not_opened_headers = tny_simple_list_new ();
834         not_opened_cached_headers = tny_simple_list_new ();
835         while (!tny_iterator_is_done (iter)) {
836
837                 ModestWindow *window;
838                 TnyHeader *header;
839                 gboolean found;
840                 
841                 header = TNY_HEADER (tny_iterator_get_current (iter));
842                 flags = tny_header_get_flags (header);
843
844                 window = NULL;
845                 found = modest_window_mgr_find_registered_header (mgr, header, &window);
846                 
847                 /* Do not open again the message and present the
848                    window to the user */
849                 if (found) {
850                         if (window)
851                                 gtk_window_present (GTK_WINDOW (window));
852                         else
853                                 /* the header has been registered already, we don't do
854                                  * anything but wait for the window to come up*/
855                                 g_warning ("debug: header %p already registered, waiting for window",
856                                            header);
857                 } else {
858                         if (!(flags & TNY_HEADER_FLAG_CACHED))
859                                 tny_list_append (not_opened_headers, G_OBJECT (header));
860                         /* Check if msg has already been retreived */
861                         else
862                                 tny_list_append (not_opened_cached_headers, G_OBJECT (header));
863                 }
864                 g_object_unref (header);
865                 tny_iterator_next (iter);
866         }
867         g_object_unref (iter);
868         iter = NULL;
869         
870         /* If some messages would have to be downloaded, ask the user to 
871          * make a connection. It's generally easier to do this here (in the mainloop) 
872          * than later in a thread:
873          */
874         if (tny_list_get_length (not_opened_cached_headers) > 0) {
875                 gboolean connected = modest_platform_connect_and_wait (GTK_WINDOW (win));
876                 
877                 /* Don't go further if a connection would be necessary but none is available: */
878                 if (!connected) {
879                         g_object_unref (not_opened_headers);
880                         g_object_unref (not_opened_cached_headers);
881                         return;
882                 }
883         }
884         
885         /* Register the headers before actually creating the windows: */
886         TnyIterator *iter_not_opened = tny_list_create_iterator (not_opened_headers);
887         while (!tny_iterator_is_done (iter_not_opened)) {
888                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_not_opened));
889                 modest_window_mgr_register_header (mgr, header);
890                 g_object_unref (header);
891                 
892                 tny_iterator_next (iter_not_opened);
893         }
894         g_object_unref (iter_not_opened);
895         iter_not_opened = NULL;
896         
897         TnyIterator *iter_cached = tny_list_create_iterator (not_opened_cached_headers);
898         while (!tny_iterator_is_done (iter_cached)) {
899                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter_cached));
900                 modest_window_mgr_register_header (mgr, header);
901                 g_object_unref (header);
902                 
903                 tny_iterator_next (iter_cached);
904         }
905         g_object_unref (iter_cached);
906         iter_cached = NULL;
907         
908         
909         /* Open each uncached message */
910         if (tny_list_get_length (not_opened_headers) > 0) {
911                 mail_op1 = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
912                                                                          G_OBJECT (win), 
913                                                                          modest_ui_actions_get_msgs_full_error_handler, 
914                                                                          NULL);
915                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op1);
916                 if (tny_list_get_length (not_opened_headers) > 1) {
917                         modest_mail_operation_get_msgs_full (mail_op1, 
918                                                              not_opened_headers, 
919                                                              open_msg_cb, 
920                                                              NULL, 
921                                                              NULL);
922                 } else {
923                         TnyIterator *iter = tny_list_create_iterator (not_opened_headers);
924                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
925                         modest_mail_operation_get_msg (mail_op1, header, open_msg_cb, NULL);
926                         g_object_unref (header);
927                         g_object_unref (iter);
928                 }
929         }
930
931         /* Open each cached message */
932         if (tny_list_get_length (not_opened_cached_headers) > 0) {
933                 mail_op2 = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
934                                                                          G_OBJECT (win), 
935                                                                          modest_ui_actions_get_msgs_full_error_handler, 
936                                                                          NULL);
937                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op2);
938                 if (tny_list_get_length (not_opened_cached_headers) > 1) {
939                         modest_mail_operation_get_msgs_full (mail_op2, 
940                                                              not_opened_headers, 
941                                                              open_msg_cb, 
942                                                              NULL, 
943                                                              NULL);
944                 } else {
945                         TnyIterator *iter = tny_list_create_iterator (not_opened_cached_headers);
946                         TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
947                         modest_mail_operation_get_msg (mail_op2, header, open_msg_cb, NULL);
948                         g_object_unref (header);
949                         g_object_unref (iter);
950                 }
951         }
952
953         /* Clean */
954         if (not_opened_headers != NULL)
955                 g_object_unref (not_opened_headers);
956         if (not_opened_cached_headers != NULL)
957                 g_object_unref (not_opened_cached_headers);
958         if (iter != NULL) 
959                 g_object_unref (iter);
960         if (mail_op1 != NULL)
961                 g_object_unref (mail_op1);
962         if (mail_op2 != NULL) 
963                 g_object_unref (mail_op2);
964 }
965
966 void
967 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
968 {
969         TnyList *headers;
970
971         /* Get headers */
972         headers = get_selected_headers (win);
973         if (!headers)
974                 return;
975
976         /* Open them */
977         _modest_ui_actions_open (headers, win);
978
979         g_object_unref(headers);
980 }
981
982
983 static void
984 free_reply_forward_helper (gpointer data)
985 {
986         ReplyForwardHelper *helper;
987
988         helper = (ReplyForwardHelper *) data;
989         g_free (helper->account_name);
990         g_slice_free (ReplyForwardHelper, helper);
991 }
992
993 static void
994 reply_forward_cb (ModestMailOperation *mail_op, 
995                   TnyHeader *header, 
996                   TnyMsg *msg,
997                   gpointer user_data)
998 {
999         TnyMsg *new_msg;
1000         ReplyForwardHelper *rf_helper;
1001         ModestWindow *msg_win = NULL;
1002         ModestEditType edit_type;
1003         gchar *from = NULL;
1004         TnyAccount *account = NULL;
1005         ModestWindowMgr *mgr = NULL;
1006         gchar *signature = NULL;
1007
1008         /* If there was any error. The mail operation could be NULL,
1009            this means that we already have the message downloaded and
1010            that we didn't do a mail operation to retrieve it */
1011         if (mail_op && !modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
1012                 return;
1013                         
1014         g_return_if_fail (user_data != NULL);
1015         rf_helper = (ReplyForwardHelper *) user_data;
1016
1017         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
1018                                                    rf_helper->account_name);
1019         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
1020                                          rf_helper->account_name,
1021                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
1022                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
1023                                                            rf_helper->account_name,
1024                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
1025         }
1026
1027         /* Create reply mail */
1028         switch (rf_helper->action) {
1029         case ACTION_REPLY:
1030                 new_msg = 
1031                         modest_tny_msg_create_reply_msg (msg,  from, signature,
1032                                                          rf_helper->reply_forward_type,
1033                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
1034                 break;
1035         case ACTION_REPLY_TO_ALL:
1036                 new_msg = 
1037                         modest_tny_msg_create_reply_msg (msg, from, signature, rf_helper->reply_forward_type,
1038                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
1039                 edit_type = MODEST_EDIT_TYPE_REPLY;
1040                 break;
1041         case ACTION_FORWARD:
1042                 new_msg = 
1043                         modest_tny_msg_create_forward_msg (msg, from, signature, rf_helper->reply_forward_type);
1044                 edit_type = MODEST_EDIT_TYPE_FORWARD;
1045                 break;
1046         default:
1047                 g_return_if_reached ();
1048                 return;
1049         }
1050
1051         g_free (signature);
1052
1053         if (!new_msg) {
1054                 g_printerr ("modest: failed to create message\n");
1055                 goto cleanup;
1056         }
1057
1058         account = modest_tny_account_store_get_server_account (modest_runtime_get_account_store(),
1059                                                                        rf_helper->account_name,
1060                                                                        TNY_ACCOUNT_TYPE_STORE);
1061         if (!account) {
1062                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
1063                 goto cleanup;
1064         }
1065
1066         /* Create and register the windows */
1067         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
1068         mgr = modest_runtime_get_window_mgr ();
1069         modest_window_mgr_register_window (mgr, msg_win);
1070
1071         if (rf_helper->parent_window != NULL) {
1072                 gdouble parent_zoom;
1073
1074                 parent_zoom = modest_window_get_zoom (MODEST_WINDOW (rf_helper->parent_window));
1075                 modest_window_set_zoom (msg_win, parent_zoom);
1076         }
1077
1078         /* Show edit window */
1079         gtk_widget_show_all (GTK_WIDGET (msg_win));
1080
1081 cleanup:
1082         if (msg_win)
1083                 g_object_unref (msg_win);
1084         if (new_msg)
1085                 g_object_unref (G_OBJECT (new_msg));
1086         if (account)
1087                 g_object_unref (G_OBJECT (account));
1088 /*      g_object_unref (msg); */
1089         g_object_unref (header);
1090         free_reply_forward_helper (rf_helper);
1091 }
1092
1093 /*
1094  * Checks a list of headers. If any of them are not currently
1095  * downloaded (CACHED) then it asks the user for permission to
1096  * download them.
1097  *
1098  * Returns FALSE if the user does not want to download the
1099  * messages. Returns TRUE if the user allowed the download or if all
1100  * of them are currently downloaded
1101  */
1102 static gboolean
1103 download_uncached_messages (TnyList *header_list, GtkWindow *win,
1104                             gboolean reply_fwd)
1105 {
1106         TnyIterator *iter;
1107         gboolean retval;
1108         gint uncached_messages = 0;
1109
1110         iter = tny_list_create_iterator (header_list);
1111         while (!tny_iterator_is_done (iter)) {
1112                 TnyHeader *header;
1113                 TnyHeaderFlags flags;
1114
1115                 header = TNY_HEADER (tny_iterator_get_current (iter));
1116                 flags = tny_header_get_flags (header);
1117                 /* TODO: is this the right flag?, it seems that some
1118                    headers that have been previously downloaded do not
1119                    come with it */
1120                 if (! (flags & TNY_HEADER_FLAG_CACHED))
1121                         uncached_messages ++;
1122                 g_object_unref (header);
1123                 tny_iterator_next (iter);
1124         }
1125         g_object_unref (iter);
1126
1127         /* Ask for user permission to download the messages */
1128         retval = TRUE;
1129         if (uncached_messages > 0) {
1130                 GtkResponseType response;
1131                 if (reply_fwd)
1132                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1133                                                                             _("emev_nc_include_original"));
1134                 else
1135                         response =
1136                                 modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
1137                                                                          ngettext("mcen_nc_get_msg",
1138                                                                                   "mcen_nc_get_msgs",
1139                                                                                   uncached_messages));
1140                 if (response == GTK_RESPONSE_CANCEL)
1141                         retval = FALSE;
1142                 else {
1143                         /* If a download will be necessary, make sure that we have a connection: */
1144                         retval = modest_platform_connect_and_wait(win); 
1145                 }
1146         }
1147         return retval;
1148 }
1149
1150
1151 /*
1152  * Common code for the reply and forward actions
1153  */
1154 static void
1155 reply_forward (ReplyForwardAction action, ModestWindow *win)
1156 {
1157         ModestMailOperation *mail_op = NULL;
1158         TnyList *header_list = NULL;
1159         ReplyForwardHelper *rf_helper = NULL;
1160         guint reply_forward_type;
1161         gboolean continue_download;
1162         
1163         g_return_if_fail (MODEST_IS_WINDOW(win));
1164
1165         /* we need an account when editing */
1166         if (!modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE)) {
1167                 run_account_setup_wizard (win);
1168                 return;
1169         }
1170         
1171         header_list = get_selected_headers (win);
1172         if (!header_list)
1173                 return;
1174
1175         /* Check that the messages have been previously downloaded */
1176         continue_download = download_uncached_messages (header_list, GTK_WINDOW (win), TRUE);
1177         if (!continue_download) {
1178                 g_object_unref (header_list);
1179                 return;
1180         }
1181         
1182         reply_forward_type = 
1183                 modest_conf_get_int (modest_runtime_get_conf (),
1184                                      (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
1185                                      NULL);
1186         /* We assume that we can only select messages of the
1187            same folder and that we reply all of them from the
1188            same account. In fact the interface currently only
1189            allows single selection */
1190         
1191         /* Fill helpers */
1192         rf_helper = g_slice_new0 (ReplyForwardHelper);
1193         rf_helper->reply_forward_type = reply_forward_type;
1194         rf_helper->action = action;
1195         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
1196         if ((win != NULL) && (MODEST_IS_WINDOW (win)))
1197                 rf_helper->parent_window = GTK_WIDGET (win);
1198         if (!rf_helper->account_name)
1199                 rf_helper->account_name =
1200                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1201
1202         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
1203                 TnyMsg *msg;
1204                 TnyHeader *header;
1205                 /* Get header and message. Do not free them here, the
1206                    reply_forward_cb must do it */
1207                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
1208                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW(win));
1209                 if (!msg || !header) {
1210                         if (msg)
1211                                 g_object_unref (msg);
1212                         if (header)
1213                                 g_object_unref (header);
1214                         g_printerr ("modest: no message found\n");
1215                         return;
1216                 } else {
1217                         reply_forward_cb (NULL, header, msg, rf_helper);
1218                 }
1219         } else {
1220                 TnyHeader *header;
1221                 TnyIterator *iter;
1222
1223                 /* Retrieve messages */
1224                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
1225                                                                          G_OBJECT(win),
1226                                                                          modest_ui_actions_get_msgs_full_error_handler, 
1227                                                                          NULL);
1228                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1229
1230                 /* Only reply/forward to one message */
1231                 iter = tny_list_create_iterator (header_list);
1232                 header = TNY_HEADER (tny_iterator_get_current (iter));
1233                 g_object_unref (iter);
1234
1235                 modest_mail_operation_get_msg (mail_op,
1236                                                header,
1237                                                reply_forward_cb,
1238                                                rf_helper);
1239
1240 /*              modest_mail_operation_get_msgs_full (mail_op,  */
1241 /*                                                   header_list,  */
1242 /*                                                   reply_forward_cb,  */
1243 /*                                                   rf_helper,  */
1244 /*                                                   free_reply_forward_helper); */
1245
1246                 /* Clean */
1247                 g_object_unref(mail_op);
1248         }
1249
1250         /* Free */
1251         g_object_unref (header_list);
1252 }
1253
1254 void
1255 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
1256 {
1257         g_return_if_fail (MODEST_IS_WINDOW(win));
1258
1259         reply_forward (ACTION_REPLY, win);
1260 }
1261
1262 void
1263 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
1264 {
1265         g_return_if_fail (MODEST_IS_WINDOW(win));
1266
1267         reply_forward (ACTION_FORWARD, win);
1268 }
1269
1270 void
1271 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
1272 {
1273         g_return_if_fail (MODEST_IS_WINDOW(win));
1274
1275         reply_forward (ACTION_REPLY_TO_ALL, win);
1276 }
1277
1278 void 
1279 modest_ui_actions_on_next (GtkAction *action, 
1280                            ModestWindow *window)
1281 {
1282         if (MODEST_IS_MAIN_WINDOW (window)) {
1283                 GtkWidget *header_view;
1284
1285                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1286                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1287                 if (!header_view)
1288                         return;
1289         
1290                 modest_header_view_select_next (MODEST_HEADER_VIEW(header_view)); 
1291         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1292                 modest_msg_view_window_select_next_message (MODEST_MSG_VIEW_WINDOW (window));
1293         } else {
1294                 g_return_if_reached ();
1295         }
1296 }
1297
1298 void 
1299 modest_ui_actions_on_prev (GtkAction *action, 
1300                            ModestWindow *window)
1301 {
1302         g_return_if_fail (MODEST_IS_WINDOW(window));
1303
1304         if (MODEST_IS_MAIN_WINDOW (window)) {
1305                 GtkWidget *header_view;
1306                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1307                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1308                 if (!header_view)
1309                         return;
1310                 
1311                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
1312         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
1313                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
1314         } else {
1315                 g_return_if_reached ();
1316         }
1317 }
1318
1319 void 
1320 modest_ui_actions_on_sort (GtkAction *action, 
1321                            ModestWindow *window)
1322 {
1323         g_return_if_fail (MODEST_IS_WINDOW(window));
1324
1325         if (MODEST_IS_MAIN_WINDOW (window)) {
1326                 GtkWidget *header_view;
1327                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
1328                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
1329                 if (!header_view)
1330                         return;
1331
1332                 /* Show sorting dialog */
1333                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
1334         }
1335 }
1336
1337 static void
1338 new_messages_arrived (ModestMailOperation *self, 
1339                       gint new_messages,
1340                       gpointer user_data)
1341 {
1342         if (new_messages == 0)
1343                 return;
1344
1345         modest_platform_on_new_msg ();
1346 }
1347
1348 /*
1349  * This function performs the send & receive required actions. The
1350  * window is used to create the mail operation. Typically it should
1351  * always be the main window, but we pass it as argument in order to
1352  * be more flexible.
1353  */
1354 void
1355 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
1356 {
1357         gchar *acc_name = NULL;
1358         ModestMailOperation *mail_op;
1359
1360         /* If no account name was provided then get the current account, and if
1361            there is no current account then pick the default one: */
1362         if (!account_name) {
1363                 acc_name = g_strdup (modest_window_get_active_account(win));
1364                 if (!acc_name)
1365                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
1366                 if (!acc_name) {
1367                         g_printerr ("modest: cannot get default account\n");
1368                         return;
1369                 }
1370         } else {
1371                 acc_name = g_strdup (account_name);
1372         }
1373
1374         /* Set send/receive operation in progress */    
1375         modest_main_window_notify_send_receive_initied (MODEST_MAIN_WINDOW(win));
1376
1377         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
1378                                                                  G_OBJECT (win),
1379                                                                  modest_ui_actions_send_receive_error_handler,
1380                                                                  NULL);
1381
1382         g_signal_connect (G_OBJECT(mail_op), "progress-changed", 
1383                           G_CALLBACK (_on_send_receive_progress_changed), 
1384                           win);
1385
1386         /* Send & receive. */
1387         /* TODO: The spec wants us to first do any pending deletions, before receiving. */
1388         /* Receive and then send. The operation is tagged initially as
1389            a receive operation because the account update performs a
1390            receive and then a send. The operation changes its type
1391            internally, so the progress objects will receive the proper
1392            progress information */
1393         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1394         modest_mail_operation_update_account (mail_op, acc_name, new_messages_arrived, NULL);
1395         g_object_unref (G_OBJECT (mail_op));
1396         
1397         /* Free */
1398         g_free (acc_name);
1399 }
1400
1401
1402 static void
1403 modest_ui_actions_do_cancel_send (const gchar *account_name,  
1404                                   ModestWindow *win)
1405 {
1406         TnyTransportAccount *transport_account;
1407         TnySendQueue *send_queue = NULL;
1408         GError *error = NULL;
1409
1410         /* Get transport account */
1411         transport_account =
1412                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1413                                       (modest_runtime_get_account_store(),
1414                                        account_name,
1415                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1416         if (!transport_account) {
1417                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1418                 goto frees;
1419         }
1420
1421         /* Get send queue*/
1422         send_queue = TNY_SEND_QUEUE (modest_runtime_get_send_queue (transport_account));
1423         if (!TNY_IS_SEND_QUEUE(send_queue)) {
1424                 g_set_error (&error, MODEST_MAIL_OPERATION_ERROR,
1425                              MODEST_MAIL_OPERATION_ERROR_ITEM_NOT_FOUND,
1426                              "modest: could not find send queue for account\n");
1427         } else {
1428                 /* Keeep messages in outbox folder */
1429                 tny_send_queue_cancel (send_queue, FALSE, &error);
1430         }       
1431
1432  frees:
1433         if (transport_account != NULL) 
1434                 g_object_unref (G_OBJECT (transport_account));
1435 }
1436
1437 static void
1438 modest_ui_actions_cancel_send_all (ModestWindow *win) 
1439 {
1440         GSList *account_names, *iter;
1441
1442         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1443                                                           TRUE);
1444
1445         iter = account_names;
1446         while (iter) {                  
1447                 modest_ui_actions_do_cancel_send ((const char*) iter->data, win);
1448                 iter = g_slist_next (iter);
1449         }
1450
1451         modest_account_mgr_free_account_names (account_names);
1452         account_names = NULL;
1453 }
1454
1455 void
1456 modest_ui_actions_cancel_send (GtkAction *action,  ModestWindow *win)
1457
1458 {
1459         /* Check if accounts exist */
1460         gboolean accounts_exist = 
1461                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1462         
1463         /* If not, allow the user to create an account before trying to send/receive. */
1464         if (!accounts_exist)
1465                 modest_ui_actions_on_accounts (NULL, win);
1466         
1467         /* Cancel all sending operaitons */     
1468         modest_ui_actions_cancel_send_all (win);
1469 }
1470
1471 /*
1472  * Refreshes all accounts. This function will be used by automatic
1473  * updates
1474  */
1475 void
1476 modest_ui_actions_do_send_receive_all (ModestWindow *win)
1477 {
1478         GSList *account_names, *iter;
1479
1480         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
1481                                                           TRUE);
1482
1483         iter = account_names;
1484         while (iter) {                  
1485                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
1486                 iter = g_slist_next (iter);
1487         }
1488
1489         modest_account_mgr_free_account_names (account_names);
1490         account_names = NULL;
1491 }
1492
1493 /*
1494  * Handler of the click on Send&Receive button in the main toolbar
1495  */
1496 void
1497 modest_ui_actions_on_send_receive (GtkAction *action,  ModestWindow *win)
1498 {
1499         /* Check if accounts exist */
1500         gboolean accounts_exist = 
1501                 modest_account_mgr_has_accounts(modest_runtime_get_account_mgr(), TRUE);
1502         
1503         /* If not, allow the user to create an account before trying to send/receive. */
1504         if (!accounts_exist)
1505                 modest_ui_actions_on_accounts (NULL, win);
1506
1507         /* Refresh currently selected folder. Note that if we only
1508            want to retrive the headers, then the refresh only will
1509            invoke a poke_status over all folders, i.e., only the
1510            total/unread count will be updated */
1511         if (MODEST_IS_MAIN_WINDOW (win)) {
1512                 GtkWidget *header_view, *folder_view;
1513                 TnyFolderStore *folder_store;
1514
1515                 /* Get folder and header view */
1516                 folder_view = 
1517                         modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win), 
1518                                                              MODEST_WIDGET_TYPE_FOLDER_VIEW);
1519
1520                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1521
1522                 if (folder_store && TNY_IS_FOLDER (folder_store)) {
1523                         header_view = 
1524                                 modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1525                                                                      MODEST_WIDGET_TYPE_HEADER_VIEW);
1526                 
1527                         /* We do not need to set the contents style
1528                            because it hasn't changed. We also do not
1529                            need to save the widget status. Just force
1530                            a refresh */
1531                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1532                                                        TNY_FOLDER (folder_store),
1533                                                        folder_refreshed_cb,
1534                                                        MODEST_MAIN_WINDOW (win));
1535                 }
1536                 
1537                 if (folder_store)
1538                         g_object_unref (folder_store);
1539         }
1540         
1541         /* Refresh the active account */
1542         modest_ui_actions_do_send_receive (NULL, win);
1543 }
1544
1545
1546 void
1547 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1548 {
1549         ModestConf *conf;
1550         GtkWidget *header_view;
1551         
1552         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1553
1554         header_view = modest_main_window_get_child_widget (main_window,
1555                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1556         if (!header_view)
1557                 return;
1558
1559         conf = modest_runtime_get_conf ();
1560         
1561         /* what is saved/restored is depending on the style; thus; we save with
1562          * old style, then update the style, and restore for this new style
1563          */
1564         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1565         
1566         if (modest_header_view_get_style
1567             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1568                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1569                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1570         else
1571                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1572                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1573
1574         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1575                                       MODEST_CONF_HEADER_VIEW_KEY);
1576 }
1577
1578
1579 void 
1580 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1581                                       TnyHeader *header,
1582                                       ModestMainWindow *main_window)
1583 {
1584         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1585         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1586         
1587         /* If no header has been selected then exit */
1588         if (!header)
1589                 return;
1590
1591         /* Update focus */
1592         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1593             gtk_widget_grab_focus (GTK_WIDGET(header_view));
1594
1595         /* Update Main window title */
1596         if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
1597                 const gchar *subject = tny_header_get_subject (header);
1598                 if (subject && strlen(subject) > 0)
1599                         gtk_window_set_title (GTK_WINDOW (main_window), subject);
1600                 else
1601                         gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
1602         }
1603
1604         /* Update toolbar dimming state */
1605         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1606 }
1607
1608 void
1609 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1610                                        TnyHeader *header,
1611                                        ModestMainWindow *main_window)
1612 {
1613         TnyList *headers;
1614
1615         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1616         
1617         if (!header)
1618                 return;
1619
1620         headers = tny_simple_list_new ();
1621         tny_list_prepend (headers, G_OBJECT (header));
1622
1623         _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1624
1625         g_object_unref (headers);
1626 }
1627
1628 static void
1629 set_active_account_from_tny_account (TnyAccount *account,
1630                                      ModestWindow *window)
1631 {
1632         const gchar *server_acc_name = tny_account_get_id (account);
1633         
1634         /* We need the TnyAccount provided by the
1635            account store because that is the one that
1636            knows the name of the Modest account */
1637         TnyAccount *modest_server_account = modest_server_account = 
1638                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
1639                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
1640                                                              server_acc_name);
1641         
1642         const gchar *modest_acc_name = 
1643                 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1644         modest_window_set_active_account (window, modest_acc_name);
1645         g_object_unref (modest_server_account);
1646 }
1647
1648
1649 static void
1650 folder_refreshed_cb (ModestMailOperation *mail_op, 
1651                      TnyFolder *folder, 
1652                      gpointer user_data)
1653 {
1654         ModestMainWindow *win = NULL;
1655         GtkWidget *header_view;
1656
1657         g_return_if_fail (TNY_IS_FOLDER (folder));
1658
1659         win = MODEST_MAIN_WINDOW (user_data);
1660         header_view = 
1661                 modest_main_window_get_child_widget(win, MODEST_WIDGET_TYPE_HEADER_VIEW);
1662
1663         /* Check if folder is empty and set headers view contents style */
1664         if (tny_folder_get_all_count (folder) == 0) {
1665         printf ("DEBUG: %s: tny_folder_get_all_count() returned 0.\n", __FUNCTION__);
1666                 modest_main_window_set_contents_style (win,
1667                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1668         } else {
1669                 printf ("DEBUG: %s: tny_folder_get_all_count() returned >0.\n", __FUNCTION__);
1670         }
1671 }
1672
1673 void 
1674 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1675                                                TnyFolderStore *folder_store, 
1676                                                gboolean selected,
1677                                                ModestMainWindow *main_window)
1678 {
1679         ModestConf *conf;
1680         GtkWidget *header_view;
1681
1682         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1683
1684         header_view = modest_main_window_get_child_widget(main_window,
1685                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
1686         if (!header_view)
1687                 return;
1688         
1689         conf = modest_runtime_get_conf ();
1690
1691         if (TNY_IS_ACCOUNT (folder_store)) {
1692                 if (selected) {
1693                         /* Update active account */
1694                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1695                         /* Show account details */
1696                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1697                 }
1698         } else {
1699                 if (TNY_IS_FOLDER (folder_store) && selected) {
1700                         
1701                         /* Update the active account */
1702                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
1703                         if (account) {
1704                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1705                                 g_object_unref (account);
1706                                 account = NULL;
1707                         }
1708
1709                         /* Set the header style by default, it could
1710                            be changed later by the refresh callback to
1711                            empty */
1712                         modest_main_window_set_contents_style (main_window, 
1713                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1714
1715                         /* Set folder on header view. This function
1716                            will call tny_folder_refresh_async so we
1717                            pass a callback that will be called when
1718                            finished. We use that callback to set the
1719                            empty view if there are no messages */
1720                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1721                                                        TNY_FOLDER (folder_store),
1722                                                        folder_refreshed_cb,
1723                                                        main_window);
1724                         
1725                         /* Restore configuration. We need to do this
1726                            *after* the set_folder because the widget
1727                            memory asks the header view about its
1728                            folder  */
1729                         modest_widget_memory_restore (modest_runtime_get_conf (), 
1730                                                       G_OBJECT(header_view),
1731                                                       MODEST_CONF_HEADER_VIEW_KEY);
1732                 } else {
1733                         /* Update the active account */
1734                         modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
1735                         /* Save only if we're seeing headers */
1736                         if (modest_main_window_get_contents_style (main_window) ==
1737                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1738                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
1739                                                            MODEST_CONF_HEADER_VIEW_KEY);
1740                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
1741                 }
1742         }
1743
1744         /* Update toolbar dimming state */
1745         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1746 }
1747
1748 void 
1749 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1750                                      ModestWindow *win)
1751 {
1752         GtkWidget *dialog;
1753         gchar *txt, *item;
1754         gboolean online;
1755
1756         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1757         
1758         online = tny_device_is_online (modest_runtime_get_device());
1759
1760         if (online) {
1761                 /* already online -- the item is simply not there... */
1762                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1763                                                  GTK_DIALOG_MODAL,
1764                                                  GTK_MESSAGE_WARNING,
1765                                                  GTK_BUTTONS_OK,
1766                                                  _("The %s you selected cannot be found"),
1767                                                  item);
1768                 gtk_dialog_run (GTK_DIALOG(dialog));
1769         } else {
1770                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1771                                                       GTK_WINDOW (win),
1772                                                       GTK_DIALOG_MODAL,
1773                                                       GTK_STOCK_CANCEL,
1774                                                       GTK_RESPONSE_REJECT,
1775                                                       GTK_STOCK_OK,
1776                                                       GTK_RESPONSE_ACCEPT,
1777                                                       NULL);
1778                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1779                                          "Do you want to get online?"), item);
1780                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1781                                     gtk_label_new (txt), FALSE, FALSE, 0);
1782                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1783                 g_free (txt);
1784
1785                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1786                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1787 //                      modest_platform_connect_and_wait ();
1788                 }
1789         }
1790         gtk_widget_destroy (dialog);
1791 }
1792
1793 void
1794 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1795                                      ModestWindow *win)
1796 {
1797         /* g_message ("%s %s", __FUNCTION__, link); */
1798 }       
1799
1800
1801 void
1802 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1803                                         ModestWindow *win)
1804 {
1805         modest_platform_activate_uri (link);
1806 }
1807
1808 void
1809 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1810                                           ModestWindow *win)
1811 {
1812         modest_platform_show_uri_popup (link);
1813 }
1814
1815 void
1816 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1817                                              ModestWindow *win)
1818 {
1819         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
1820 }
1821
1822 void
1823 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1824                                           const gchar *address,
1825                                           ModestWindow *win)
1826 {
1827         /* g_message ("%s %s", __FUNCTION__, address); */
1828 }
1829
1830 void
1831 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1832 {
1833         TnyTransportAccount *transport_account;
1834         ModestMailOperation *mail_operation;
1835         MsgData *data;
1836         gchar *account_name, *from;
1837         ModestAccountMgr *account_mgr;
1838         gchar *info_text = NULL;
1839
1840         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1841         
1842         data = modest_msg_edit_window_get_msg_data (edit_window);
1843
1844         account_mgr = modest_runtime_get_account_mgr();
1845         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1846         if (!account_name) 
1847                 account_name = modest_account_mgr_get_default_account (account_mgr);
1848         if (!account_name) {
1849                 g_printerr ("modest: no account found\n");
1850                 modest_msg_edit_window_free_msg_data (edit_window, data);
1851                 return;
1852         }
1853
1854         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1855                 account_name = g_strdup (data->account_name);
1856         }
1857
1858         transport_account =
1859                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1860                                       (modest_runtime_get_account_store(),
1861                                        account_name,
1862                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1863         if (!transport_account) {
1864                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1865                 g_free (account_name);
1866                 modest_msg_edit_window_free_msg_data (edit_window, data);
1867                 return;
1868         }
1869         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1870
1871         /* Create the mail operation */         
1872         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
1873         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1874
1875         modest_mail_operation_save_to_drafts (mail_operation,
1876                                               transport_account,
1877                                               data->draft_msg,
1878                                               edit_window,
1879                                               from,
1880                                               data->to, 
1881                                               data->cc, 
1882                                               data->bcc,
1883                                               data->subject, 
1884                                               data->plain_body, 
1885                                               data->html_body,
1886                                               data->attachments,
1887                                               data->priority_flags);
1888         /* Frees */
1889         g_free (from);
1890         g_free (account_name);
1891         g_object_unref (G_OBJECT (transport_account));
1892         g_object_unref (G_OBJECT (mail_operation));
1893
1894         modest_msg_edit_window_free_msg_data (edit_window, data);
1895
1896         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
1897         modest_platform_information_banner (NULL, NULL, info_text);
1898         g_free (info_text);
1899 }
1900
1901 /* For instance, when clicking the Send toolbar button when editing a message: */
1902 void
1903 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1904 {
1905         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1906
1907         if (!modest_msg_edit_window_check_names (edit_window))
1908                 return;
1909         
1910         /* Offer the connection dialog, if necessary: */        
1911         if (!modest_platform_connect_and_wait (GTK_WINDOW (edit_window)))
1912                 return;
1913         
1914         /* FIXME: Code added just for testing. The final version will
1915            use the send queue provided by tinymail and some
1916            classifier */
1917         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
1918         gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1919         if (!account_name) 
1920                 account_name = modest_account_mgr_get_default_account (account_mgr);
1921                 
1922         if (!account_name) {
1923                 g_printerr ("modest: no account found\n");
1924                 return;
1925         }
1926         
1927         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
1928
1929         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1930                 account_name = g_strdup (data->account_name);
1931         }
1932         
1933         /* Get the currently-active transport account for this modest account: */
1934         TnyTransportAccount *transport_account =
1935                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
1936                                       (modest_runtime_get_account_store(),
1937                                        account_name));
1938         if (!transport_account) {
1939                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1940                 g_free (account_name);
1941                 modest_msg_edit_window_free_msg_data (edit_window, data);
1942                 return;
1943         }
1944         
1945         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
1946
1947         /* mail content checks and dialogs */
1948         if (data->subject == NULL || data->subject[0] == '\0') {
1949                 GtkResponseType response;
1950                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1951                                                                     _("mcen_nc_subject_is_empty_send"));
1952                 if (response == GTK_RESPONSE_CANCEL) {
1953                         g_free (account_name);
1954                         return;
1955                 }
1956         }
1957
1958         if (data->plain_body == NULL || data->plain_body[0] == '\0') {
1959                 GtkResponseType response;
1960                 gchar *note_message;
1961                 gchar *note_subject = data->subject;
1962                 if (note_subject == NULL || note_subject[0] == '\0')
1963                         note_subject = _("mail_va_no_subject");
1964                 note_message = g_strdup_printf (_("emev_ni_ui_smtp_message_null"), note_subject);
1965                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1966                                                                     note_message);
1967                 g_free (note_message);
1968                 if (response == GTK_RESPONSE_CANCEL) {
1969                         g_free (account_name);
1970                         return;
1971                 }
1972         }
1973
1974         modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
1975
1976         /* Create the mail operation */
1977         ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
1978         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1979
1980         modest_mail_operation_send_new_mail (mail_operation,
1981                                              transport_account,
1982                                              data->draft_msg,
1983                                              from,
1984                                              data->to, 
1985                                              data->cc, 
1986                                              data->bcc,
1987                                              data->subject, 
1988                                              data->plain_body, 
1989                                              data->html_body,
1990                                              data->attachments,
1991                                              data->priority_flags);
1992                                              
1993         /* Free data: */
1994         g_free (from);
1995         g_free (account_name);
1996         g_object_unref (G_OBJECT (transport_account));
1997         g_object_unref (G_OBJECT (mail_operation));
1998
1999         modest_msg_edit_window_free_msg_data (edit_window, data);
2000         modest_msg_edit_window_set_sent (edit_window, TRUE);
2001
2002         /* Save settings and close the window: */
2003         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2004 }
2005
2006 void 
2007 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2008                                   ModestMsgEditWindow *window)
2009 {
2010         ModestMsgEditFormatState *format_state = NULL;
2011
2012         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2013         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2014
2015         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2016                 return;
2017
2018         format_state = modest_msg_edit_window_get_format_state (window);
2019         g_return_if_fail (format_state != NULL);
2020
2021         format_state->bold = gtk_toggle_action_get_active (action);
2022         modest_msg_edit_window_set_format_state (window, format_state);
2023         g_free (format_state);
2024         
2025 }
2026
2027 void 
2028 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2029                                      ModestMsgEditWindow *window)
2030 {
2031         ModestMsgEditFormatState *format_state = NULL;
2032
2033         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2034         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2035
2036         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2037                 return;
2038
2039         format_state = modest_msg_edit_window_get_format_state (window);
2040         g_return_if_fail (format_state != NULL);
2041
2042         format_state->italics = gtk_toggle_action_get_active (action);
2043         modest_msg_edit_window_set_format_state (window, format_state);
2044         g_free (format_state);
2045         
2046 }
2047
2048 void 
2049 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2050                                      ModestMsgEditWindow *window)
2051 {
2052         ModestMsgEditFormatState *format_state = NULL;
2053
2054         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2055         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2056
2057         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2058                 return;
2059
2060         format_state = modest_msg_edit_window_get_format_state (window);
2061         g_return_if_fail (format_state != NULL);
2062
2063         format_state->bullet = gtk_toggle_action_get_active (action);
2064         modest_msg_edit_window_set_format_state (window, format_state);
2065         g_free (format_state);
2066         
2067 }
2068
2069 void 
2070 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2071                                      GtkRadioAction *selected,
2072                                      ModestMsgEditWindow *window)
2073 {
2074         ModestMsgEditFormatState *format_state = NULL;
2075         GtkJustification value;
2076
2077         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2078
2079         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2080                 return;
2081
2082         value = gtk_radio_action_get_current_value (selected);
2083
2084         format_state = modest_msg_edit_window_get_format_state (window);
2085         g_return_if_fail (format_state != NULL);
2086
2087         format_state->justification = value;
2088         modest_msg_edit_window_set_format_state (window, format_state);
2089         g_free (format_state);
2090 }
2091
2092 void 
2093 modest_ui_actions_on_select_editor_color (GtkAction *action,
2094                                           ModestMsgEditWindow *window)
2095 {
2096         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2097         g_return_if_fail (GTK_IS_ACTION (action));
2098
2099         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2100                 return;
2101
2102         modest_msg_edit_window_select_color (window);
2103 }
2104
2105 void 
2106 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2107                                                      ModestMsgEditWindow *window)
2108 {
2109         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2110         g_return_if_fail (GTK_IS_ACTION (action));
2111
2112         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2113                 return;
2114
2115         modest_msg_edit_window_select_background_color (window);
2116 }
2117
2118 void 
2119 modest_ui_actions_on_insert_image (GtkAction *action,
2120                                    ModestMsgEditWindow *window)
2121 {
2122         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2123         g_return_if_fail (GTK_IS_ACTION (action));
2124
2125         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2126                 return;
2127
2128         modest_msg_edit_window_insert_image (window);
2129 }
2130
2131 void 
2132 modest_ui_actions_on_attach_file (GtkAction *action,
2133                                   ModestMsgEditWindow *window)
2134 {
2135         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2136         g_return_if_fail (GTK_IS_ACTION (action));
2137
2138         modest_msg_edit_window_attach_file (window);
2139 }
2140
2141 void 
2142 modest_ui_actions_on_remove_attachments (GtkAction *action,
2143                                          ModestMsgEditWindow *window)
2144 {
2145         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2146         g_return_if_fail (GTK_IS_ACTION (action));
2147
2148         modest_msg_edit_window_remove_attachments (window, NULL);
2149 }
2150
2151 static void
2152 modest_ui_actions_new_folder_error_handler (ModestMailOperation *mail_op,
2153                                             gpointer user_data)
2154 {
2155         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2156
2157         /* TODO: Note that folder creation might go wrong due to other
2158          * failures such as when the parent folder is non-writable. We can
2159          * query a GError* with modest_mail_operation_get_error(), but the
2160          * the error code (from tinymail) does not give us a clue about what
2161          * has gone wrong. We might use the error->message but it might come
2162          * from camel and not be suitable to show to the user directly. */
2163         modest_platform_information_banner (GTK_WIDGET (window), NULL,
2164                                             _CS("ckdg_ib_folder_already_exists"));
2165
2166 /*      modest_platform_information_banner (GTK_WIDGET (window), NULL,
2167                                             modest_mail_operation_get_error (mail_op)->message);*/
2168 }
2169
2170
2171 void 
2172 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2173 {
2174         TnyFolderStore *parent_folder;
2175         GtkWidget *folder_view;
2176         
2177         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2178
2179         folder_view = modest_main_window_get_child_widget (main_window,
2180                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2181         if (!folder_view)
2182                 return;
2183
2184         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2185         
2186         if (parent_folder) {
2187                 gboolean finished = FALSE;
2188                 gint result;
2189                 gchar *folder_name = NULL, *suggested_name = NULL;
2190
2191                 /* Run the new folder dialog */
2192                 while (!finished) {
2193                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (main_window),
2194                                                                         parent_folder,
2195                                                                         suggested_name,
2196                                                                         &folder_name);
2197
2198                         g_free (suggested_name);
2199                         suggested_name = NULL;
2200
2201                         if (result == GTK_RESPONSE_REJECT) {
2202                                 finished = TRUE;
2203                         } else {
2204                                 ModestMailOperation *mail_op;
2205                                 TnyFolder *new_folder = NULL;
2206
2207                                 mail_op  = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2208                                                                                           G_OBJECT(main_window),
2209                                                                                           modest_ui_actions_new_folder_error_handler,
2210                                                                                           main_window);
2211
2212                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2213                                                                  mail_op);
2214                                 new_folder = modest_mail_operation_create_folder (mail_op,
2215                                                                                   parent_folder,
2216                                                                                   (const gchar *) folder_name);
2217                                 if (new_folder) {
2218                                         if (main_window) {
2219                                                 folder_view = modest_main_window_get_child_widget (main_window,
2220                                                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
2221                                                 if (folder_view)
2222                                                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), 
2223                                                                                           new_folder, TRUE);
2224                                         }
2225
2226                                         g_object_unref (new_folder);
2227                                         finished = TRUE;
2228                                 }
2229                                 g_object_unref (mail_op);
2230                         }
2231
2232                         suggested_name = folder_name;
2233                         folder_name = NULL;
2234                 }
2235
2236                 g_object_unref (parent_folder);
2237         }
2238 }
2239
2240 static void
2241 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2242                                                gpointer user_data)
2243 {
2244         GObject *win = modest_mail_operation_get_source (mail_op);
2245         const GError *error = NULL;
2246         const gchar *message = NULL;
2247         
2248         /* Get error message */
2249         error = modest_mail_operation_get_error (mail_op);
2250         if (error != NULL && error->message != NULL) {
2251                 message = error->message;
2252         } else {
2253                 message = _("!!! FIXME: Unable to rename");
2254         }
2255         
2256         /* Show notification dialog */
2257         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
2258         g_object_unref (win);
2259 }
2260
2261 void 
2262 modest_ui_actions_on_rename_folder (GtkAction *action,
2263                                      ModestMainWindow *main_window)
2264 {
2265         TnyFolderStore *folder;
2266         GtkWidget *folder_view;
2267         GtkWidget *header_view; 
2268
2269         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2270
2271         folder_view = modest_main_window_get_child_widget (main_window,
2272                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2273         if (!folder_view)
2274                 return;
2275
2276         header_view = modest_main_window_get_child_widget (main_window,
2277                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2278         
2279         if (!header_view)
2280                 return;
2281
2282         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2283
2284         /* Offer the connection dialog if necessary: */
2285         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2286                 g_object_unref (G_OBJECT (folder));
2287                 return;
2288         }
2289
2290         
2291         if (folder && TNY_IS_FOLDER (folder)) {
2292                 gchar *folder_name;
2293                 gint response;
2294                 const gchar *current_name;
2295
2296                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2297                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), NULL,
2298                                                                      current_name, &folder_name);
2299
2300                 if (response == GTK_RESPONSE_ACCEPT && strlen (folder_name) > 0) {
2301                         ModestMailOperation *mail_op;
2302
2303                         mail_op = 
2304                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO, 
2305                                                                                G_OBJECT(main_window),
2306                                                                                modest_ui_actions_rename_folder_error_handler,
2307                                                                                NULL);
2308
2309
2310                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2311                                                          mail_op);
2312
2313                         modest_header_view_clear (MODEST_HEADER_VIEW (header_view));
2314                         
2315                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2316                                                           TNY_FOLDER(folder), TRUE);
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         return dialog;
3176 }
3177
3178 /*
3179  * Returns TRUE if at least one of the headers of the list belongs to
3180  * a message that has been fully retrieved.
3181  */
3182 static gboolean
3183 has_retrieved_msgs (TnyList *list)
3184 {
3185         TnyIterator *iter;
3186         gboolean found = FALSE;
3187
3188         iter = tny_list_create_iterator (list);
3189         while (tny_iterator_is_done (iter) && !found) {
3190                 TnyHeader *header;
3191                 TnyHeaderFlags flags;
3192
3193                 header = TNY_HEADER (tny_iterator_get_current (iter));
3194                 flags = tny_header_get_flags (header);
3195                 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
3196                         found = TRUE;
3197
3198                 if (!found)
3199                         tny_iterator_next (iter);
3200         }
3201         g_object_unref (iter);
3202
3203         return found;
3204 }
3205
3206 /*
3207  * Shows a confirmation dialog to the user when we're moving messages
3208  * from a remote server to the local storage. Returns the dialog
3209  * response. If it's other kind of movement the it always returns
3210  * GTK_RESPONSE_OK
3211  */
3212 static gint
3213 msgs_move_to_confirmation (GtkWindow *win,
3214                            TnyFolder *dest_folder,
3215                            TnyList *headers)
3216 {
3217         gint response = GTK_RESPONSE_OK;
3218
3219         /* If the destination is a local folder */
3220         if (modest_tny_folder_is_local_folder (dest_folder)) {
3221                 TnyFolder *src_folder;
3222                 TnyIterator *iter;
3223                 TnyHeader *header;
3224
3225                 /* Get source folder */
3226                 iter = tny_list_create_iterator (headers);
3227                 header = TNY_HEADER (tny_iterator_get_current (iter));
3228                 src_folder = tny_header_get_folder (header);
3229                 g_object_unref (header);
3230                 g_object_unref (iter);
3231
3232                 /* if no src_folder, message may be an attahcment */
3233                 if (src_folder == NULL) 
3234                         return GTK_RESPONSE_CANCEL;
3235
3236                 /* If the source is a remote folder */
3237                 if (!modest_tny_folder_is_local_folder (src_folder)) {
3238                         const gchar *message;
3239                         
3240                         if (has_retrieved_msgs (headers))
3241                                 message = ngettext ("mcen_nc_move_retrieve", "mcen_nc_move_retrieves",
3242                                                     tny_list_get_length (headers));
3243                         else 
3244                                 message = ngettext ("mcen_nc_move_header", "mcen_nc_move_headers",
3245                                                     tny_list_get_length (headers));
3246
3247                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
3248                                                                             (const gchar *) message);
3249                 }
3250                 g_object_unref (src_folder);
3251         }
3252         return response;
3253 }
3254
3255
3256
3257 static void
3258 transfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
3259 {
3260         ModestMsgViewWindow *self = NULL;
3261
3262         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
3263         self = MODEST_MSG_VIEW_WINDOW (object);
3264         
3265         if (!modest_msg_view_window_select_next_message (self))
3266                 if (!modest_msg_view_window_select_previous_message (self))
3267                         /* No more messages to view, so close this window */
3268                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
3269 }
3270
3271 void
3272 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
3273                                              gpointer user_data)
3274 {
3275         GObject *win = modest_mail_operation_get_source (mail_op);
3276         const GError *error = NULL;
3277         const gchar *message = NULL;
3278         
3279         /* Get error message */
3280         error = modest_mail_operation_get_error (mail_op);
3281         if (error != NULL && error->message != NULL) {
3282                 message = error->message;
3283         } else {
3284                 message = _("mail_in_ui_folder_move_target_error");
3285         }
3286         
3287         /* Show notification dialog */
3288         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
3289         g_object_unref (win);
3290 }
3291
3292 void
3293 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
3294                                               gpointer user_data)
3295 {
3296         GObject *win = modest_mail_operation_get_source (mail_op);
3297         const GError *error = modest_mail_operation_get_error (mail_op);
3298
3299         g_return_if_fail (error != NULL);
3300         if (error->message != NULL)             
3301                 g_printerr ("modest: %s\n", error->message);
3302         else
3303                 g_printerr ("modest: unkonw error on send&receive operation");
3304
3305         /* Show error message */
3306 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
3307 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3308 /*                                                      _CS("sfil_ib_unable_to_receive")); */
3309 /*      else  */
3310 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3311 /*                                                      _CS("sfil_ib_unable_to_send")); */
3312         g_object_unref (win);
3313 }
3314
3315 static void
3316 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
3317                        TnyHeader *header, 
3318                        TnyMsg *msg, 
3319                        gpointer user_data)
3320 {
3321         TnyList *parts;
3322         TnyIterator *iter;
3323         gint pending_purges = 0;
3324         gboolean some_purged = FALSE;
3325         ModestWindow *win = MODEST_WINDOW (user_data);
3326
3327         /* If there was any error */
3328         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
3329                 return;
3330
3331         /* Once the message has been retrieved for purging, we check if
3332          * it's all ok for purging */
3333
3334         parts = tny_simple_list_new ();
3335         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
3336         iter = tny_list_create_iterator (parts);
3337
3338         while (!tny_iterator_is_done (iter)) {
3339                 TnyMimePart *part;
3340                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3341                 if (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)) {
3342                         if (tny_mime_part_is_purged (part))
3343                                 some_purged = TRUE;
3344                         else
3345                                 pending_purges++;
3346                 }
3347                 tny_iterator_next (iter);
3348         }
3349
3350         if (pending_purges>0) {
3351                 gint response;
3352                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
3353
3354                 if (response == GTK_RESPONSE_OK) {
3355                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
3356                         tny_iterator_first (iter);
3357                         while (!tny_iterator_is_done (iter)) {
3358                                 TnyMimePart *part;
3359                                 
3360                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3361                                 if (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))
3362                                         tny_mime_part_set_purged (part);
3363                                 tny_iterator_next (iter);
3364                         }
3365                         
3366                         tny_msg_rewrite_cache (msg);
3367                 }
3368         } else {
3369                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
3370         }
3371
3372         /* remove attachments */
3373         tny_iterator_first (iter);
3374         while (!tny_iterator_is_done (iter)) {
3375                 TnyMimePart *part;
3376                         
3377                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3378                 g_object_unref (part);
3379                 tny_iterator_next (iter);
3380         }
3381
3382         g_object_unref (iter);
3383         g_object_unref (parts);
3384 }
3385
3386 static void
3387 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
3388                                                      ModestMainWindow *win)
3389 {
3390         GtkWidget *header_view;
3391         TnyList *header_list;
3392         TnyIterator *iter;
3393         TnyHeader *header;
3394         TnyHeaderFlags flags;
3395         ModestWindow *msg_view_window =  NULL;
3396         gboolean found;
3397
3398         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3399
3400         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3401                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3402
3403         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
3404
3405         if (tny_list_get_length (header_list) == 1) {
3406                 iter = tny_list_create_iterator (header_list);
3407                 header = TNY_HEADER (tny_iterator_get_current (iter));
3408                 g_object_unref (iter);
3409         } else {
3410                 return;
3411         }
3412
3413         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
3414                                                           header, &msg_view_window);
3415         flags = tny_header_get_flags (header);
3416         if (!(flags & TNY_HEADER_FLAG_CACHED))
3417                 return;
3418         if (found) {
3419                 if (msg_view_window != NULL) 
3420                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
3421                 else {
3422                         /* do nothing; uid was registered before, so window is probably on it's way */
3423                         g_warning ("debug: header %p has already been registered", header);
3424                 }
3425         } else {
3426                 ModestMailOperation *mail_op = NULL;
3427                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header);
3428                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
3429                                                                          G_OBJECT (win),
3430                                                                          modest_ui_actions_get_msgs_full_error_handler,
3431                                                                          NULL);
3432                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3433                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
3434                 
3435                 g_object_unref (mail_op);
3436         }
3437         if (header)
3438                 g_object_unref (header);
3439         if (header_list)
3440                 g_object_unref (header_list);
3441 }
3442
3443 /**
3444  * Utility function that transfer messages from both the main window
3445  * and the msg view window when using the "Move to" dialog
3446  */
3447 static void
3448 modest_ui_actions_xfer_messages_from_move_to (TnyFolderStore *dst_folder,
3449                                               ModestWindow *win)
3450 {
3451         TnyList *headers = NULL;
3452         gint response = 0;
3453
3454         if (!TNY_IS_FOLDER (dst_folder)) {
3455                 modest_platform_information_banner (GTK_WIDGET (win),
3456                                                     NULL,
3457                                                     _CS("ckdg_ib_unable_to_move_to_current_location"));
3458                 return;
3459         }
3460
3461         /* Get selected headers */
3462         headers = get_selected_headers (MODEST_WINDOW (win));
3463
3464         /* Ask for user confirmation */
3465         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
3466                                               TNY_FOLDER (dst_folder), 
3467                                               headers);
3468
3469         /* Transfer messages */
3470         if (response == GTK_RESPONSE_OK) {
3471                 ModestMailOperation *mail_op = 
3472                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3473                                                                        G_OBJECT(win),
3474                                                                        modest_ui_actions_move_folder_error_handler,
3475                                                                        NULL);
3476                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3477                                                  mail_op);
3478
3479                 modest_mail_operation_xfer_msgs (mail_op, 
3480                                                  headers,
3481                                                  TNY_FOLDER (dst_folder),
3482                                                  TRUE,
3483                                                  (MODEST_IS_MSG_VIEW_WINDOW (win)) ? transfer_msgs_from_viewer_cb : NULL,
3484                                                  NULL);
3485
3486                 g_object_unref (G_OBJECT (mail_op));
3487         }
3488         g_object_unref (headers);
3489 }
3490
3491
3492 /*
3493  * UI handler for the "Move to" action when invoked from the
3494  * ModestMainWindow
3495  */
3496 static void 
3497 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
3498                                           GtkWidget *folder_view,
3499                                           TnyFolderStore *dst_folder,
3500                                           ModestMainWindow *win)
3501 {
3502         GtkWidget *header_view = NULL;
3503         ModestMailOperation *mail_op = NULL;
3504         TnyFolderStore *src_folder;
3505
3506         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3507
3508         /* Get the source folder */
3509         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3510         
3511         /* Offer the connection dialog if necessary, if the source folder is in a networked account: */
3512         if (!modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), 
3513                                                                       src_folder))
3514                 goto end;
3515
3516         /* Get header view */
3517         header_view = 
3518                 modest_main_window_get_child_widget (win, MODEST_WIDGET_TYPE_HEADER_VIEW);
3519
3520         /* Get folder or messages to transfer */
3521         if (gtk_widget_is_focus (folder_view)) {
3522
3523                 /* Allow only to transfer folders to the local root folder */
3524                 if (TNY_IS_ACCOUNT (dst_folder) && 
3525                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder))
3526                         goto end;
3527                 
3528                 /* Clean folder on header view before moving it */
3529                 modest_header_view_clear (MODEST_HEADER_VIEW (header_view)); 
3530
3531                 if (TNY_IS_FOLDER (src_folder)) {
3532                         mail_op = 
3533                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3534                                                                                G_OBJECT(win),
3535                                                                                modest_ui_actions_move_folder_error_handler,
3536                                                                                NULL);
3537                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3538                                                          mail_op);
3539
3540                         modest_mail_operation_xfer_folder (mail_op, 
3541                                                            TNY_FOLDER (src_folder),
3542                                                            dst_folder,
3543                                                            TRUE, NULL, NULL);
3544                         /* Unref mail operation */
3545                         g_object_unref (G_OBJECT (mail_op));
3546                 } else {
3547                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);       
3548                 }
3549         } else if (gtk_widget_is_focus (header_view)) {
3550                 /* Transfer messages */
3551                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
3552         }
3553         
3554  end:
3555     if (src_folder)
3556         g_object_unref (src_folder);
3557 }
3558
3559
3560 /*
3561  * UI handler for the "Move to" action when invoked from the
3562  * ModestMsgViewWindow
3563  */
3564 static void 
3565 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
3566                                               TnyFolderStore *dst_folder,
3567                                               ModestMsgViewWindow *win)
3568 {
3569         TnyHeader *header = NULL;
3570         TnyFolder *src_folder;
3571
3572         /* Create header list */
3573         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
3574         src_folder = tny_header_get_folder(header);
3575         g_object_unref (header);
3576
3577         /* Transfer the message */
3578         if (modest_platform_connect_and_wait_if_network_folderstore (NULL, TNY_FOLDER_STORE (src_folder)))
3579                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
3580
3581         g_object_unref (src_folder);
3582 }
3583
3584 void 
3585 modest_ui_actions_on_move_to (GtkAction *action, 
3586                               ModestWindow *win)
3587 {
3588         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
3589         gint result = 0;
3590         TnyFolderStore *dst_folder = NULL;
3591         ModestMainWindow *main_window;
3592
3593         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
3594                           MODEST_IS_MSG_VIEW_WINDOW (win));
3595
3596         /* Get the main window if exists */
3597         if (MODEST_IS_MAIN_WINDOW (win))
3598                 main_window = MODEST_MAIN_WINDOW (win);
3599         else
3600                 main_window = 
3601                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
3602
3603         /* Get the folder view widget if exists */
3604         if (main_window)
3605                 folder_view = modest_main_window_get_child_widget (main_window,
3606                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
3607         else
3608                 folder_view = NULL;
3609
3610         /* Create and run the dialog */
3611         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
3612         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (tree_view), TRUE);
3613         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
3614         result = gtk_dialog_run (GTK_DIALOG(dialog));
3615         g_object_ref (tree_view);
3616         gtk_widget_destroy (dialog);
3617
3618         if (result != GTK_RESPONSE_ACCEPT)
3619                 return;
3620
3621         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
3622         /* Offer the connection dialog if necessary: */
3623         if (modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), 
3624                                                                       dst_folder)) {
3625
3626                 /* Do window specific stuff */
3627                 if (MODEST_IS_MAIN_WINDOW (win))
3628                         modest_ui_actions_on_main_window_move_to (action,
3629                                                                   folder_view,
3630                                                                   dst_folder,
3631                                                                   MODEST_MAIN_WINDOW (win));
3632                 else
3633                         modest_ui_actions_on_msg_view_window_move_to (action,
3634                                                                       dst_folder,
3635                                                                       MODEST_MSG_VIEW_WINDOW (win));
3636         }
3637         if (dst_folder)
3638                 g_object_unref (dst_folder);
3639 }
3640
3641 /*
3642  * Calls #HeadersFunc for each header already selected in the main
3643  * window or the message currently being shown in the msg view window
3644  */
3645 static void
3646 do_headers_action (ModestWindow *win, 
3647                    HeadersFunc func,
3648                    gpointer user_data)
3649 {
3650         TnyList *headers_list;
3651         TnyIterator *iter;
3652         TnyHeader *header;
3653         TnyFolder *folder;
3654
3655         /* Get headers */
3656         headers_list = get_selected_headers (win);
3657         if (!headers_list)
3658                 return;
3659
3660         /* Get the folder */
3661         iter = tny_list_create_iterator (headers_list);
3662         header = TNY_HEADER (tny_iterator_get_current (iter));
3663         folder = tny_header_get_folder (header);
3664         g_object_unref (header);
3665
3666         /* Call the function for each header */
3667         while (!tny_iterator_is_done (iter)) {
3668                 header = TNY_HEADER (tny_iterator_get_current (iter));
3669                 func (header, win, user_data);
3670                 g_object_unref (header);
3671                 tny_iterator_next (iter);
3672         }
3673
3674         /* Trick: do a poke status in order to speed up the signaling
3675            of observers */
3676         tny_folder_poke_status (folder);
3677
3678         /* Frees */
3679         g_object_unref (folder);
3680         g_object_unref (iter);
3681         g_object_unref (headers_list);
3682 }
3683
3684 void 
3685 modest_ui_actions_view_attachment (GtkAction *action,
3686                                    ModestWindow *window)
3687 {
3688         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3689                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
3690         } else {
3691                 /* not supported window for this action */
3692                 g_return_if_reached ();
3693         }
3694 }
3695
3696 void
3697 modest_ui_actions_save_attachments (GtkAction *action,
3698                                     ModestWindow *window)
3699 {
3700         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3701                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
3702         } else {
3703                 /* not supported window for this action */
3704                 g_return_if_reached ();
3705         }
3706 }
3707
3708 void
3709 modest_ui_actions_remove_attachments (GtkAction *action,
3710                                       ModestWindow *window)
3711 {
3712         if (MODEST_IS_MAIN_WINDOW (window)) {
3713                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
3714         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3715                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
3716         } else {
3717                 /* not supported window for this action */
3718                 g_return_if_reached ();
3719         }
3720 }
3721
3722 void 
3723 modest_ui_actions_on_settings (GtkAction *action, 
3724                                ModestWindow *win)
3725 {
3726         GtkWidget *dialog;
3727
3728         dialog = modest_platform_get_global_settings_dialog ();
3729         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
3730         gtk_widget_show_all (dialog);
3731
3732         gtk_dialog_run (GTK_DIALOG (dialog));
3733
3734         gtk_widget_destroy (dialog);
3735 }
3736
3737 void 
3738 modest_ui_actions_on_help (GtkAction *action, 
3739                            ModestWindow *win)
3740 {
3741         const gchar *help_id = NULL;
3742
3743         if (MODEST_IS_MAIN_WINDOW (win)) {
3744                 const gchar *action_name;
3745                 action_name = gtk_action_get_name (action);
3746
3747                 if (!strcmp (action_name, "FolderViewCSMHelp") ||
3748                     !strcmp (action_name, "HeaderViewCSMHelp")) {
3749                         GtkWidget *folder_view;
3750                         TnyFolderStore *folder_store;
3751                         /* Get selected folder */
3752                         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3753                                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
3754                         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3755
3756                         /* Switch help_id */
3757                         if (TNY_IS_FOLDER (folder_store)) {
3758                                 switch (modest_tny_folder_guess_folder_type (TNY_FOLDER (folder_store))) {
3759                                 case TNY_FOLDER_TYPE_NORMAL:
3760                                         help_id = "applications_email_managefolders";
3761                                         break;
3762                                 case TNY_FOLDER_TYPE_INBOX:
3763                                         help_id = "applications_email_inbox";
3764                                         break;
3765                                 case TNY_FOLDER_TYPE_OUTBOX:
3766                                         help_id = "applications_email_outbox";
3767                                         break;
3768                                 case TNY_FOLDER_TYPE_SENT:
3769                                         help_id = "applications_email_sent";
3770                                         break;
3771                                 case TNY_FOLDER_TYPE_DRAFTS:
3772                                         help_id = "applications_email_drafts";
3773                                         break;
3774                                 case TNY_FOLDER_TYPE_ARCHIVE:
3775                                         help_id = "applications_email_managefolders";
3776                                         break;
3777                                 default:
3778                                         help_id = "applications_email_managefolders";
3779                                 }
3780                         } else {
3781                                 help_id = "applications_email_mainview";        
3782                         }
3783                         g_object_unref (folder_store);
3784                 } else {
3785                         help_id = "applications_email_mainview";        
3786                 }
3787         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3788                 help_id = "applications_email_viewer";
3789         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
3790                 help_id = "applications_email_editor";
3791
3792         modest_platform_show_help (GTK_WINDOW (win), help_id);
3793 }
3794
3795 void 
3796 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
3797                                             ModestWindow *window)
3798 {
3799         ModestMailOperation *mail_op;
3800         TnyList *headers;
3801
3802         /* Get headers */
3803         headers = get_selected_headers (window);
3804         if (!headers)
3805                 return;
3806
3807         /* Create mail operation */
3808         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3809                                                                  G_OBJECT (window),
3810                                                                  modest_ui_actions_get_msgs_full_error_handler, 
3811                                                                  NULL);
3812         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3813         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
3814
3815         /* Frees */
3816         g_object_unref (headers);
3817         g_object_unref (mail_op);
3818 }
3819
3820 void
3821 modest_ui_actions_on_email_menu_activated (GtkAction *action,
3822                                           ModestWindow *window)
3823 {
3824         g_return_if_fail (MODEST_IS_WINDOW (window));
3825
3826         /* Update dimmed */     
3827         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3828 }
3829
3830 void
3831 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
3832                                           ModestWindow *window)
3833 {
3834         g_return_if_fail (MODEST_IS_WINDOW (window));
3835
3836         /* Update dimmed */     
3837         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3838 }
3839
3840 void
3841 modest_ui_actions_on_view_menu_activated (GtkAction *action,
3842                                           ModestWindow *window)
3843 {
3844         g_return_if_fail (MODEST_IS_WINDOW (window));
3845
3846         /* Update dimmed */     
3847         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3848 }
3849
3850 void
3851 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
3852                                           ModestWindow *window)
3853 {
3854         g_return_if_fail (MODEST_IS_WINDOW (window));
3855
3856         /* Update dimmed */     
3857         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3858 }
3859
3860 void
3861 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
3862                                           ModestWindow *window)
3863 {
3864         g_return_if_fail (MODEST_IS_WINDOW (window));
3865
3866         /* Update dimmed */     
3867         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3868 }
3869
3870 void
3871 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
3872                                                  ModestWindow *window)
3873 {
3874         g_return_if_fail (MODEST_IS_WINDOW (window));
3875
3876         /* Update dimmed */     
3877         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3878 }
3879
3880 void
3881 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
3882                                                      ModestWindow *window)
3883 {
3884         g_return_if_fail (MODEST_IS_WINDOW (window));
3885
3886         /* Update dimmed */     
3887         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3888 }
3889
3890 void
3891 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
3892                                                      ModestWindow *window)
3893 {
3894         g_return_if_fail (MODEST_IS_WINDOW (window));
3895
3896         /* Update dimmed */     
3897         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3898 }
3899
3900 void
3901 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
3902 {
3903         g_return_if_fail (MODEST_IS_WINDOW (window));
3904
3905         /* Update dimmed */     
3906         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
3907 }
3908
3909 void
3910 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
3911 {
3912         g_return_if_fail (MODEST_IS_WINDOW (window));
3913
3914         modest_platform_show_search_messages (GTK_WINDOW (window));
3915 }
3916
3917 void     
3918 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
3919 {
3920         g_return_if_fail (MODEST_IS_WINDOW (win));
3921         modest_platform_show_addressbook (GTK_WINDOW (win));
3922 }
3923
3924
3925 void
3926 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
3927                                           ModestWindow *window)
3928 {
3929         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3930
3931         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
3932 }
3933
3934 static void 
3935 _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
3936                                    ModestMailOperationState *state,
3937                                    gpointer user_data)
3938 {
3939         g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
3940
3941         /* Set send/receive operation finished */       
3942         if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3943                 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));
3944         
3945 }
3946
3947