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