2007-07-12 Murray Cumming <murrayc@murrayc.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
2184 void 
2185 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2186 {
2187         TnyFolderStore *parent_folder;
2188         GtkWidget *folder_view;
2189         
2190         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2191
2192         folder_view = modest_main_window_get_child_widget (main_window,
2193                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2194         if (!folder_view)
2195                 return;
2196
2197         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2198         
2199         if (parent_folder) {
2200                 gboolean finished = FALSE;
2201                 gint result;
2202                 gchar *folder_name = NULL, *suggested_name = NULL;
2203
2204                 /* Run the new folder dialog */
2205                 while (!finished) {
2206                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (main_window),
2207                                                                         parent_folder,
2208                                                                         suggested_name,
2209                                                                         &folder_name);
2210
2211                         g_free (suggested_name);
2212                         suggested_name = NULL;
2213
2214                         if (result == GTK_RESPONSE_REJECT) {
2215                                 finished = TRUE;
2216                         } else {
2217                                 ModestMailOperation *mail_op;
2218                                 TnyFolder *new_folder = NULL;
2219
2220                                 mail_op  = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2221                                                                                           G_OBJECT(main_window),
2222                                                                                           modest_ui_actions_new_folder_error_handler,
2223                                                                                           main_window);
2224
2225                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2226                                                                  mail_op);
2227                                 new_folder = modest_mail_operation_create_folder (mail_op,
2228                                                                                   parent_folder,
2229                                                                                   (const gchar *) folder_name);
2230                                 if (new_folder) {
2231                                         if (main_window) {
2232                                                 folder_view = modest_main_window_get_child_widget (main_window,
2233                                                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
2234                                                 if (folder_view)
2235                                                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), 
2236                                                                                           new_folder, TRUE);
2237                                         }
2238
2239                                         g_object_unref (new_folder);
2240                                         finished = TRUE;
2241                                 }
2242                                 g_object_unref (mail_op);
2243                         }
2244
2245                         suggested_name = folder_name;
2246                         folder_name = NULL;
2247                 }
2248
2249                 g_object_unref (parent_folder);
2250         }
2251 }
2252
2253 static void
2254 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2255                                                gpointer user_data)
2256 {
2257         GObject *win = modest_mail_operation_get_source (mail_op);
2258         const GError *error = NULL;
2259         const gchar *message = NULL;
2260         
2261         /* Get error message */
2262         error = modest_mail_operation_get_error (mail_op);
2263         if (error != NULL && error->message != NULL) {
2264                 message = error->message;
2265         } else {
2266                 message = _("!!! FIXME: Unable to rename");
2267         }
2268         
2269         /* Show notification dialog */
2270         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
2271         g_object_unref (win);
2272 }
2273
2274 void 
2275 modest_ui_actions_on_rename_folder (GtkAction *action,
2276                                      ModestMainWindow *main_window)
2277 {
2278         TnyFolderStore *folder;
2279         GtkWidget *folder_view;
2280         GtkWidget *header_view; 
2281
2282         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2283
2284         folder_view = modest_main_window_get_child_widget (main_window,
2285                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2286         if (!folder_view)
2287                 return;
2288
2289         header_view = modest_main_window_get_child_widget (main_window,
2290                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2291         
2292         if (!header_view)
2293                 return;
2294
2295         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2296         if (!folder)
2297                 return;
2298
2299         /* Offer the connection dialog if necessary: */
2300         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2301                 g_object_unref (G_OBJECT (folder));
2302                 return;
2303         }
2304
2305         
2306         if (TNY_IS_FOLDER (folder)) {
2307                 gchar *folder_name;
2308                 gint response;
2309                 const gchar *current_name;
2310
2311                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2312                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), NULL,
2313                                                                      current_name, &folder_name);
2314
2315                 if (response == GTK_RESPONSE_ACCEPT && strlen (folder_name) > 0) {
2316                         ModestMailOperation *mail_op;
2317
2318                         mail_op = 
2319                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO, 
2320                                                                                G_OBJECT(main_window),
2321                                                                                modest_ui_actions_rename_folder_error_handler,
2322                                                                                NULL);
2323
2324
2325                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2326                                                          mail_op);
2327
2328                         modest_header_view_clear (MODEST_HEADER_VIEW (header_view));
2329                         
2330                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2331                                                           TNY_FOLDER(folder), TRUE);
2332
2333
2334                         modest_header_view_clear ((ModestHeaderView *) header_view);
2335  
2336                         modest_mail_operation_rename_folder (mail_op,
2337                                                              TNY_FOLDER (folder),
2338                                                              (const gchar *) folder_name);
2339
2340                         g_object_unref (mail_op);
2341                         g_free (folder_name);
2342                 }
2343         }
2344         g_object_unref (folder);
2345 }
2346
2347 static void
2348 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2349                                                gpointer user_data)
2350 {
2351         GObject *win = modest_mail_operation_get_source (mail_op);
2352
2353         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2354                                                 _("mail_in_ui_folder_delete_error"));
2355         g_object_unref (win);
2356 }
2357
2358 static void
2359 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2360 {
2361         TnyFolderStore *folder;
2362         GtkWidget *folder_view;
2363         gint response;
2364         gchar *message;
2365         
2366         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2367
2368         folder_view = modest_main_window_get_child_widget (main_window,
2369                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2370         if (!folder_view)
2371                 return;
2372
2373         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2374
2375         /* Show an error if it's an account */
2376         if (!TNY_IS_FOLDER (folder)) {
2377                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2378                                                         _("mail_in_ui_folder_delete_error"));
2379                 g_object_unref (G_OBJECT (folder));
2380                 return ;
2381         }
2382
2383         /* Offer the connection dialog if necessary: */
2384         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2385                 g_object_unref (G_OBJECT (folder));
2386                 return;
2387         }
2388
2389         /* Ask the user */      
2390         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2391                                     tny_folder_get_name (TNY_FOLDER (folder)));
2392         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2393                                                             (const gchar *) message);
2394         g_free (message);
2395
2396         if (response == GTK_RESPONSE_OK) {
2397                 ModestMailOperation *mail_op = 
2398                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
2399                                                                        G_OBJECT(main_window),
2400                                                                        modest_ui_actions_delete_folder_error_handler,
2401                                                                        NULL);
2402
2403                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2404                                                  mail_op);
2405                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2406                 g_object_unref (G_OBJECT (mail_op));
2407         }
2408
2409         g_object_unref (G_OBJECT (folder));
2410 }
2411
2412 void 
2413 modest_ui_actions_on_delete_folder (GtkAction *action,
2414                                      ModestMainWindow *main_window)
2415 {
2416         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2417
2418         delete_folder (main_window, FALSE);
2419 }
2420
2421 void 
2422 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2423 {
2424         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2425         
2426         delete_folder (main_window, TRUE);
2427 }
2428
2429 void
2430 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2431                                          const gchar* server_account_name,
2432                                          gchar **username,
2433                                          gchar **password, 
2434                                          gboolean *cancel, 
2435                                          gboolean *remember,
2436                                          ModestMainWindow *main_window)
2437 {
2438         g_return_if_fail(server_account_name);
2439         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2440         
2441         /* Initalize output parameters: */
2442         if (cancel)
2443                 *cancel = FALSE;
2444                 
2445         if (remember)
2446                 *remember = TRUE;
2447                 
2448 #ifdef MODEST_PLATFORM_MAEMO
2449         /* Maemo uses a different (awkward) button order,
2450          * It should probably just use gtk_alternative_dialog_button_order ().
2451          */
2452         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2453                                               NULL,
2454                                               GTK_DIALOG_MODAL,
2455                                               GTK_STOCK_OK,
2456                                               GTK_RESPONSE_ACCEPT,
2457                                               GTK_STOCK_CANCEL,
2458                                               GTK_RESPONSE_REJECT,
2459                                               NULL);
2460 #else
2461         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2462                                               NULL,
2463                                               GTK_DIALOG_MODAL,
2464                                               GTK_STOCK_CANCEL,
2465                                               GTK_RESPONSE_REJECT,
2466                                               GTK_STOCK_OK,
2467                                               GTK_RESPONSE_ACCEPT,
2468                                               NULL);
2469 #endif /* MODEST_PLATFORM_MAEMO */
2470
2471         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2472         
2473         gchar *server_name = modest_server_account_get_hostname (
2474                 modest_runtime_get_account_mgr(), server_account_name);
2475         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2476                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2477                 *cancel = TRUE;
2478                 return;
2479         }
2480         
2481         /* This causes a warning because the logical ID has no %s in it, 
2482          * though the translation does, but there is not much we can do about that: */
2483         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2484         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2485                             FALSE, FALSE, 0);
2486         g_free (txt);
2487         g_free (server_name);
2488         server_name = NULL;
2489
2490         /* username: */
2491         gchar *initial_username = modest_server_account_get_username (
2492                 modest_runtime_get_account_mgr(), server_account_name);
2493         
2494         GtkWidget *entry_username = gtk_entry_new ();
2495         if (initial_username)
2496                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2497         /* Dim this if a connection has ever succeeded with this username,
2498          * as per the UI spec: */
2499         const gboolean username_known = 
2500                 modest_server_account_get_username_has_succeeded(
2501                         modest_runtime_get_account_mgr(), server_account_name);
2502         gtk_widget_set_sensitive (entry_username, !username_known);
2503         
2504 #ifdef MODEST_PLATFORM_MAEMO
2505         /* Auto-capitalization is the default, so let's turn it off: */
2506         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2507         
2508         /* Create a size group to be used by all captions.
2509          * Note that HildonCaption does not create a default size group if we do not specify one.
2510          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2511         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2512         
2513         GtkWidget *caption = hildon_caption_new (sizegroup, 
2514                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2515         gtk_widget_show (entry_username);
2516         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2517                 FALSE, FALSE, MODEST_MARGIN_HALF);
2518         gtk_widget_show (caption);
2519 #else 
2520         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2521                             TRUE, FALSE, 0);
2522 #endif /* MODEST_PLATFORM_MAEMO */      
2523                             
2524         /* password: */
2525         GtkWidget *entry_password = gtk_entry_new ();
2526         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2527         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2528         
2529 #ifdef MODEST_PLATFORM_MAEMO
2530         /* Auto-capitalization is the default, so let's turn it off: */
2531         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2532                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2533         
2534         caption = hildon_caption_new (sizegroup, 
2535                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2536         gtk_widget_show (entry_password);
2537         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2538                 FALSE, FALSE, MODEST_MARGIN_HALF);
2539         gtk_widget_show (caption);
2540         g_object_unref (sizegroup);
2541 #else 
2542         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2543                             TRUE, FALSE, 0);
2544 #endif /* MODEST_PLATFORM_MAEMO */      
2545                                 
2546 /* This is not in the Maemo UI spec:
2547         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2548         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2549                             TRUE, FALSE, 0);
2550 */
2551
2552         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2553         
2554         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2555                 if (username) {
2556                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2557                         
2558                         modest_server_account_set_username (
2559                                  modest_runtime_get_account_mgr(), server_account_name, 
2560                                  *username);
2561                                  
2562                         const gboolean username_was_changed = 
2563                                 (strcmp (*username, initial_username) != 0);
2564                         if (username_was_changed) {
2565                                 g_warning ("%s: tinymail does not yet support changing the "
2566                                         "username in the get_password() callback.\n", __FUNCTION__);
2567                         }
2568                 }
2569                         
2570                 if (password) {
2571                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2572                         
2573                         /* We do not save the password in the configuration, 
2574                          * because this function is only called for passwords that should 
2575                          * not be remembered:
2576                         modest_server_account_set_password (
2577                                  modest_runtime_get_account_mgr(), server_account_name, 
2578                                  *password);
2579                         */
2580                 }
2581                 
2582                 if (cancel)
2583                         *cancel   = FALSE;
2584                         
2585         } else {
2586                 if (username)
2587                         *username = NULL;
2588                         
2589                 if (password)
2590                         *password = NULL;
2591                         
2592                 if (cancel)
2593                         *cancel   = TRUE;
2594         }
2595
2596 /* This is not in the Maemo UI spec:
2597         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2598                 *remember = TRUE;
2599         else
2600                 *remember = FALSE;
2601 */
2602
2603         gtk_widget_destroy (dialog);
2604         
2605         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2606 }
2607
2608 void
2609 modest_ui_actions_on_cut (GtkAction *action,
2610                           ModestWindow *window)
2611 {
2612         GtkWidget *focused_widget;
2613
2614         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2615         if (GTK_IS_EDITABLE (focused_widget)) {
2616                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2617         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2618                 GtkTextBuffer *buffer;
2619                 GtkClipboard *clipboard;
2620
2621                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2622                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2623                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2624                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2625         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2626                 modest_header_view_cut_selection (MODEST_HEADER_VIEW (focused_widget));
2627         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2628                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2629         }
2630 }
2631
2632 void
2633 modest_ui_actions_on_copy (GtkAction *action,
2634                            ModestWindow *window)
2635 {
2636         GtkClipboard *clipboard;
2637         GtkWidget *focused_widget;
2638
2639         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2640         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2641
2642         if (GTK_IS_LABEL (focused_widget)) {
2643                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2644         } else if (GTK_IS_EDITABLE (focused_widget)) {
2645                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2646         } else if (GTK_IS_HTML (focused_widget)) {
2647                 gtk_html_copy (GTK_HTML (focused_widget));
2648         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2649                 GtkTextBuffer *buffer;
2650                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2651                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2652                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2653         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2654                 TnyList *header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (focused_widget));
2655                 TnyIterator *iter = tny_list_create_iterator (header_list);
2656                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2657                 TnyFolder *folder = tny_header_get_folder (header);
2658                 TnyAccount *account = tny_folder_get_account (folder);
2659                 const gchar *proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2660                 /* If it's POP then ask */
2661                 gboolean ask = (modest_protocol_info_get_transport_store_protocol (proto_str) == 
2662                        MODEST_PROTOCOL_STORE_POP) ? TRUE : FALSE;
2663                 g_object_unref (account);
2664                 g_object_unref (folder);
2665                 g_object_unref (header);
2666                 g_object_unref (iter);
2667                 
2668                 /* Check that the messages have been previously downloaded */
2669                 gboolean continue_download = TRUE;
2670                 if (ask)
2671                         continue_download = download_uncached_messages (header_list, GTK_WINDOW (window), FALSE);
2672                 if (continue_download)
2673                         modest_header_view_copy_selection (MODEST_HEADER_VIEW (focused_widget));
2674                 g_object_unref (header_list);
2675         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2676                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
2677         }    
2678
2679         /* Show information banner */
2680         modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
2681         
2682 }
2683
2684 void
2685 modest_ui_actions_on_undo (GtkAction *action,
2686                            ModestWindow *window)
2687 {
2688         ModestEmailClipboard *clipboard = NULL;
2689
2690         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2691                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2692         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2693                 /* Clear clipboard source */
2694                 clipboard = modest_runtime_get_email_clipboard ();
2695                 modest_email_clipboard_clear (clipboard);               
2696         }
2697         else {
2698                 g_return_if_reached ();
2699         }
2700 }
2701
2702 void
2703 modest_ui_actions_on_redo (GtkAction *action,
2704                            ModestWindow *window)
2705 {
2706         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2707                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
2708         }
2709         else {
2710                 g_return_if_reached ();
2711         }
2712 }
2713
2714
2715 static void
2716 paste_msgs_cb (const GObject *object, gpointer user_data)
2717 {
2718         g_return_if_fail (MODEST_IS_MAIN_WINDOW (object));
2719         g_return_if_fail (GTK_IS_WIDGET (user_data));
2720         
2721         /* destroy information note */
2722         gtk_widget_destroy (GTK_WIDGET(user_data));
2723 }
2724
2725 void
2726 modest_ui_actions_on_paste (GtkAction *action,
2727                             ModestWindow *window)
2728 {
2729         GtkWidget *focused_widget = NULL;
2730         GtkWidget *inf_note = NULL;
2731         ModestMailOperation *mail_op = NULL;
2732
2733         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2734         if (GTK_IS_EDITABLE (focused_widget)) {
2735                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
2736         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2737                 GtkTextBuffer *buffer;
2738                 GtkClipboard *clipboard;
2739
2740                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2741                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2742                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
2743         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2744                 ModestEmailClipboard *clipboard = NULL;
2745                 TnyFolder *src_folder = NULL;
2746                 TnyFolderStore *folder_store = NULL;
2747                 TnyList *data = NULL;           
2748                 gboolean delete = FALSE;
2749                 
2750                 /* Check clipboard source */
2751                 clipboard = modest_runtime_get_email_clipboard ();
2752                 if (modest_email_clipboard_cleared (clipboard)) 
2753                         return;
2754                 
2755                 /* Get elements to paste */
2756                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
2757
2758                 /* Create a new mail operation */
2759                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
2760                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2761                                                  mail_op);
2762                 
2763                 /* Get destination folder */
2764                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
2765
2766                 /* Launch notification */
2767                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
2768                                                              _CS("ckct_nw_pasting"));
2769                 if (inf_note != NULL)  {
2770                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
2771                         gtk_widget_show (GTK_WIDGET(inf_note));
2772                 }
2773
2774                 /* transfer messages  */
2775                 if (data != NULL) {
2776                         modest_mail_operation_xfer_msgs (mail_op, 
2777                                                          data,
2778                                                          TNY_FOLDER (folder_store),
2779                                                          delete,
2780                                                          paste_msgs_cb,
2781                                                          inf_note);
2782                         
2783                 } else if (src_folder != NULL) {                        
2784                         modest_mail_operation_xfer_folder (mail_op, 
2785                                                            src_folder,
2786                                                            folder_store,
2787                                                            delete,
2788                                                            paste_msgs_cb,
2789                                                            inf_note);
2790                 }
2791
2792                 /* Free */
2793                 if (data != NULL) 
2794                         g_object_unref (data);
2795                 if (src_folder != NULL) 
2796                         g_object_unref (src_folder);
2797                 if (folder_store != NULL) 
2798                         g_object_unref (folder_store);
2799         }
2800 }
2801
2802
2803 void
2804 modest_ui_actions_on_select_all (GtkAction *action,
2805                                  ModestWindow *window)
2806 {
2807         GtkWidget *focused_widget;
2808
2809         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2810         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
2811                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
2812         } else if (GTK_IS_LABEL (focused_widget)) {
2813                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
2814         } else if (GTK_IS_EDITABLE (focused_widget)) {
2815                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
2816         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2817                 GtkTextBuffer *buffer;
2818                 GtkTextIter start, end;
2819
2820                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2821                 gtk_text_buffer_get_start_iter (buffer, &start);
2822                 gtk_text_buffer_get_end_iter (buffer, &end);
2823                 gtk_text_buffer_select_range (buffer, &start, &end);
2824         } else if (GTK_IS_HTML (focused_widget)) {
2825                 gtk_html_select_all (GTK_HTML (focused_widget));
2826         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2827                 GtkWidget *header_view = focused_widget;
2828                 GtkTreeSelection *selection = NULL;
2829                 
2830                 if (!(MODEST_IS_HEADER_VIEW (focused_widget)))
2831                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
2832                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2833                                 
2834                 /* Select all messages */
2835                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
2836                 gtk_tree_selection_select_all (selection);
2837
2838                 /* Set focuse on header view */
2839                 gtk_widget_grab_focus (header_view);
2840         }
2841
2842 }
2843
2844 void
2845 modest_ui_actions_on_mark_as_read (GtkAction *action,
2846                                    ModestWindow *window)
2847 {       
2848         g_return_if_fail (MODEST_IS_WINDOW(window));
2849                 
2850         /* Mark each header as read */
2851         do_headers_action (window, headers_action_mark_as_read, NULL);
2852 }
2853
2854 void
2855 modest_ui_actions_on_mark_as_unread (GtkAction *action,
2856                                      ModestWindow *window)
2857 {       
2858         g_return_if_fail (MODEST_IS_WINDOW(window));
2859                 
2860         /* Mark each header as read */
2861         do_headers_action (window, headers_action_mark_as_unread, NULL);
2862 }
2863
2864 void
2865 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
2866                                   GtkRadioAction *selected,
2867                                   ModestWindow *window)
2868 {
2869         gint value;
2870
2871         value = gtk_radio_action_get_current_value (selected);
2872         if (MODEST_IS_WINDOW (window)) {
2873                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
2874         }
2875 }
2876
2877 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
2878                                                         GtkRadioAction *selected,
2879                                                         ModestWindow *window)
2880 {
2881         TnyHeaderFlags flags;
2882         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2883
2884         flags = gtk_radio_action_get_current_value (selected);
2885         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
2886 }
2887
2888 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
2889                                                            GtkRadioAction *selected,
2890                                                            ModestWindow *window)
2891 {
2892         gint file_format;
2893
2894         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2895
2896         file_format = gtk_radio_action_get_current_value (selected);
2897         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
2898 }
2899
2900
2901 void     
2902 modest_ui_actions_on_zoom_plus (GtkAction *action,
2903                                 ModestWindow *window)
2904 {
2905         g_return_if_fail (MODEST_IS_WINDOW (window));
2906
2907         modest_window_zoom_plus (MODEST_WINDOW (window));
2908 }
2909
2910 void     
2911 modest_ui_actions_on_zoom_minus (GtkAction *action,
2912                                  ModestWindow *window)
2913 {
2914         g_return_if_fail (MODEST_IS_WINDOW (window));
2915
2916         modest_window_zoom_minus (MODEST_WINDOW (window));
2917 }
2918
2919 void     
2920 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
2921                                            ModestWindow *window)
2922 {
2923         ModestWindowMgr *mgr;
2924         gboolean fullscreen, active;
2925         g_return_if_fail (MODEST_IS_WINDOW (window));
2926
2927         mgr = modest_runtime_get_window_mgr ();
2928
2929         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
2930         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2931
2932         if (active != fullscreen) {
2933                 modest_window_mgr_set_fullscreen_mode (mgr, active);
2934                 gtk_window_present (GTK_WINDOW (window));
2935         }
2936 }
2937
2938 void
2939 modest_ui_actions_on_change_fullscreen (GtkAction *action,
2940                                         ModestWindow *window)
2941 {
2942         ModestWindowMgr *mgr;
2943         gboolean fullscreen;
2944
2945         g_return_if_fail (MODEST_IS_WINDOW (window));
2946
2947         mgr = modest_runtime_get_window_mgr ();
2948         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2949         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
2950
2951         gtk_window_present (GTK_WINDOW (window));
2952 }
2953
2954 /* 
2955  * Used by modest_ui_actions_on_details to call do_headers_action 
2956  */
2957 static void
2958 headers_action_show_details (TnyHeader *header, 
2959                              ModestWindow *window,
2960                              gpointer user_data)
2961
2962 {
2963         GtkWidget *dialog;
2964         
2965         /* Create dialog */
2966         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
2967
2968         /* Run dialog */
2969         gtk_widget_show_all (dialog);
2970         gtk_dialog_run (GTK_DIALOG (dialog));
2971
2972         gtk_widget_destroy (dialog);
2973 }
2974
2975 /*
2976  * Show the folder details in a ModestDetailsDialog widget
2977  */
2978 static void
2979 show_folder_details (TnyFolder *folder, 
2980                      GtkWindow *window)
2981 {
2982         GtkWidget *dialog;
2983         
2984         /* Create dialog */
2985         dialog = modest_details_dialog_new_with_folder (window, folder);
2986
2987         /* Run dialog */
2988         gtk_widget_show_all (dialog);
2989         gtk_dialog_run (GTK_DIALOG (dialog));
2990
2991         gtk_widget_destroy (dialog);
2992 }
2993
2994 /*
2995  * Show the header details in a ModestDetailsDialog widget
2996  */
2997 void     
2998 modest_ui_actions_on_details (GtkAction *action, 
2999                               ModestWindow *win)
3000 {
3001         TnyList * headers_list;
3002         TnyIterator *iter;
3003         TnyHeader *header;              
3004
3005         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3006                 TnyMsg *msg;
3007
3008                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3009                 if (!msg)
3010                         return;
3011                 g_object_unref (msg);           
3012
3013                 headers_list = get_selected_headers (win);
3014                 if (!headers_list)
3015                         return;
3016
3017                 iter = tny_list_create_iterator (headers_list);
3018
3019                 header = TNY_HEADER (tny_iterator_get_current (iter));
3020                 headers_action_show_details (header, win, NULL);
3021                 g_object_unref (header);
3022
3023                 g_object_unref (iter);
3024                 g_object_unref (headers_list);
3025
3026         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3027                 GtkWidget *folder_view, *header_view;
3028
3029                 /* Check which widget has the focus */
3030                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3031                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
3032                 if (gtk_widget_is_focus (folder_view)) {
3033                         TnyFolderStore *folder_store
3034                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3035                         if (!folder_store) {
3036                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3037                                 return; 
3038                         }
3039                         /* Show only when it's a folder */
3040                         /* This function should not be called for account items, 
3041                          * because we dim the menu item for them. */
3042                         if (TNY_IS_FOLDER (folder_store)) {
3043                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3044                         }
3045
3046                         g_object_unref (folder_store);
3047
3048                 } else {
3049                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3050                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3051                         /* Show details of each header */
3052                         do_headers_action (win, headers_action_show_details, header_view);
3053                 }
3054         }
3055 }
3056
3057 void     
3058 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3059                                      ModestMsgEditWindow *window)
3060 {
3061         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3062
3063         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3064 }
3065
3066 void     
3067 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3068                                       ModestMsgEditWindow *window)
3069 {
3070         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3071
3072         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3073 }
3074
3075 void
3076 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3077                                        ModestMainWindow *main_window)
3078 {
3079         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3080
3081         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3082                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3083         else
3084                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3085 }
3086
3087 void 
3088 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3089                                      ModestWindow *window)
3090 {
3091         gboolean active, fullscreen = FALSE;
3092         ModestWindowMgr *mgr;
3093
3094         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3095
3096         /* Check if we want to toggle the toolbar vuew in fullscreen
3097            or normal mode */
3098         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3099                      "ViewShowToolbarFullScreen")) {
3100                 fullscreen = TRUE;
3101         }
3102
3103         /* Toggle toolbar */
3104         mgr = modest_runtime_get_window_mgr ();
3105         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
3106 }
3107
3108 void     
3109 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3110                                            ModestMsgEditWindow *window)
3111 {
3112         modest_msg_edit_window_select_font (window);
3113 }
3114
3115 void
3116 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3117                                                   const gchar *display_name,
3118                                                   GtkWindow *window)
3119 {
3120         /* Do not change the application name if the widget has not
3121            the focus. This callback could be called even if the folder
3122            view has not the focus, because the handled signal could be
3123            emitted when the folder view is redrawn */
3124         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3125                 if (display_name)
3126                         gtk_window_set_title (window, display_name);
3127                 else
3128                         gtk_window_set_title (window, " ");
3129         }
3130 }
3131
3132 void
3133 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3134 {
3135         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3136         modest_msg_edit_window_select_contacts (window);
3137 }
3138
3139 void
3140 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3141 {
3142         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3143         modest_msg_edit_window_check_names (window);
3144 }
3145
3146
3147 static GtkWidget*
3148 create_move_to_dialog (GtkWindow *win,
3149                        GtkWidget *folder_view,
3150                        GtkWidget **tree_view)
3151 {
3152         GtkWidget *dialog, *scroll;
3153
3154         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3155                                               GTK_WINDOW (win),
3156                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3157                                               GTK_STOCK_OK,
3158                                               GTK_RESPONSE_ACCEPT,
3159                                               GTK_STOCK_CANCEL,
3160                                               GTK_RESPONSE_REJECT,
3161                                               NULL);
3162
3163         /* Create scrolled window */
3164         scroll = gtk_scrolled_window_new (NULL, NULL);
3165         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3166                                          GTK_POLICY_AUTOMATIC,
3167                                          GTK_POLICY_AUTOMATIC);
3168
3169         /* Create folder view */
3170         *tree_view = modest_platform_create_folder_view (NULL);
3171
3172         /* It could happen that we're trying to move a message from a
3173            window (msg window for example) after the main window was
3174            closed, so we can not just get the model of the folder
3175            view */
3176         if (MODEST_IS_FOLDER_VIEW (folder_view))
3177                 gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
3178                                          gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
3179         else
3180                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
3181                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3182
3183         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
3184         
3185         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3186
3187         /* Add scroll to dialog */
3188         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
3189                             scroll, FALSE, FALSE, 0);
3190
3191         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3192
3193         return dialog;
3194 }
3195
3196 /*
3197  * Returns TRUE if at least one of the headers of the list belongs to
3198  * a message that has been fully retrieved.
3199  */
3200 static gboolean
3201 has_retrieved_msgs (TnyList *list)
3202 {
3203         TnyIterator *iter;
3204         gboolean found = FALSE;
3205
3206         iter = tny_list_create_iterator (list);
3207         while (tny_iterator_is_done (iter) && !found) {
3208                 TnyHeader *header;
3209                 TnyHeaderFlags flags;
3210
3211                 header = TNY_HEADER (tny_iterator_get_current (iter));
3212                 flags = tny_header_get_flags (header);
3213                 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
3214                         found = TRUE;
3215
3216                 if (!found)
3217                         tny_iterator_next (iter);
3218         }
3219         g_object_unref (iter);
3220
3221         return found;
3222 }
3223
3224 /*
3225  * Shows a confirmation dialog to the user when we're moving messages
3226  * from a remote server to the local storage. Returns the dialog
3227  * response. If it's other kind of movement the it always returns
3228  * GTK_RESPONSE_OK
3229  */
3230 static gint
3231 msgs_move_to_confirmation (GtkWindow *win,
3232                            TnyFolder *dest_folder,
3233                            TnyList *headers)
3234 {
3235         gint response = GTK_RESPONSE_OK;
3236
3237         /* If the destination is a local folder */
3238         if (modest_tny_folder_is_local_folder (dest_folder)) {
3239                 TnyFolder *src_folder;
3240                 TnyIterator *iter;
3241                 TnyHeader *header;
3242
3243                 /* Get source folder */
3244                 iter = tny_list_create_iterator (headers);
3245                 header = TNY_HEADER (tny_iterator_get_current (iter));
3246                 src_folder = tny_header_get_folder (header);
3247                 g_object_unref (header);
3248                 g_object_unref (iter);
3249
3250                 /* if no src_folder, message may be an attahcment */
3251                 if (src_folder == NULL) 
3252                         return GTK_RESPONSE_CANCEL;
3253
3254                 /* If the source is a remote folder */
3255                 if (!modest_tny_folder_is_local_folder (src_folder)) {
3256                         const gchar *message;
3257                         
3258                         if (has_retrieved_msgs (headers))
3259                                 message = ngettext ("mcen_nc_move_retrieve", "mcen_nc_move_retrieves",
3260                                                     tny_list_get_length (headers));
3261                         else 
3262                                 message = ngettext ("mcen_nc_move_header", "mcen_nc_move_headers",
3263                                                     tny_list_get_length (headers));
3264
3265                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
3266                                                                             (const gchar *) message);
3267                 }
3268                 g_object_unref (src_folder);
3269         }
3270         return response;
3271 }
3272
3273
3274
3275 static void
3276 transfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
3277 {
3278         ModestMsgViewWindow *self = NULL;
3279
3280         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
3281         self = MODEST_MSG_VIEW_WINDOW (object);
3282         
3283         if (!modest_msg_view_window_select_next_message (self))
3284                 if (!modest_msg_view_window_select_previous_message (self))
3285                         /* No more messages to view, so close this window */
3286                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
3287 }
3288
3289 void
3290 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
3291                                              gpointer user_data)
3292 {
3293         GObject *win = modest_mail_operation_get_source (mail_op);
3294         const GError *error = NULL;
3295         const gchar *message = NULL;
3296         
3297         /* Get error message */
3298         error = modest_mail_operation_get_error (mail_op);
3299         if (error != NULL && error->message != NULL) {
3300                 message = error->message;
3301         } else {
3302                 message = _("mail_in_ui_folder_move_target_error");
3303         }
3304         
3305         /* Show notification dialog */
3306         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
3307         g_object_unref (win);
3308 }
3309
3310 void
3311 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
3312                                               gpointer user_data)
3313 {
3314         GObject *win = modest_mail_operation_get_source (mail_op);
3315         const GError *error = modest_mail_operation_get_error (mail_op);
3316
3317         g_return_if_fail (error != NULL);
3318         if (error->message != NULL)             
3319                 g_printerr ("modest: %s\n", error->message);
3320         else
3321                 g_printerr ("modest: unkonw error on send&receive operation");
3322
3323         /* Show error message */
3324 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
3325 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3326 /*                                                      _CS("sfil_ib_unable_to_receive")); */
3327 /*      else  */
3328 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3329 /*                                                      _CS("sfil_ib_unable_to_send")); */
3330         g_object_unref (win);
3331 }
3332
3333 static void
3334 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
3335                        TnyHeader *header, 
3336                        TnyMsg *msg, 
3337                        gpointer user_data)
3338 {
3339         TnyList *parts;
3340         TnyIterator *iter;
3341         gint pending_purges = 0;
3342         gboolean some_purged = FALSE;
3343         ModestWindow *win = MODEST_WINDOW (user_data);
3344         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3345
3346         /* If there was any error */
3347         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
3348                 modest_window_mgr_unregister_header (mgr, header);
3349                 return;
3350         }
3351
3352         /* Once the message has been retrieved for purging, we check if
3353          * it's all ok for purging */
3354
3355         parts = tny_simple_list_new ();
3356         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
3357         iter = tny_list_create_iterator (parts);
3358
3359         while (!tny_iterator_is_done (iter)) {
3360                 TnyMimePart *part;
3361                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3362                 if (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)) {
3363                         if (tny_mime_part_is_purged (part))
3364                                 some_purged = TRUE;
3365                         else
3366                                 pending_purges++;
3367                 }
3368                 tny_iterator_next (iter);
3369         }
3370
3371         if (pending_purges>0) {
3372                 gint response;
3373                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
3374
3375                 if (response == GTK_RESPONSE_OK) {
3376                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
3377                         tny_iterator_first (iter);
3378                         while (!tny_iterator_is_done (iter)) {
3379                                 TnyMimePart *part;
3380                                 
3381                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3382                                 if (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))
3383                                         tny_mime_part_set_purged (part);
3384                                 tny_iterator_next (iter);
3385                         }
3386                         
3387                         tny_msg_rewrite_cache (msg);
3388                 }
3389         } else {
3390                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
3391         }
3392
3393         /* remove attachments */
3394         tny_iterator_first (iter);
3395         while (!tny_iterator_is_done (iter)) {
3396                 TnyMimePart *part;
3397                         
3398                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3399                 g_object_unref (part);
3400                 tny_iterator_next (iter);
3401         }
3402         modest_window_mgr_unregister_header (mgr, header);
3403
3404         g_object_unref (iter);
3405         g_object_unref (parts);
3406 }
3407
3408 static void
3409 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
3410                                                      ModestMainWindow *win)
3411 {
3412         GtkWidget *header_view;
3413         TnyList *header_list;
3414         TnyIterator *iter;
3415         TnyHeader *header;
3416         TnyHeaderFlags flags;
3417         ModestWindow *msg_view_window =  NULL;
3418         gboolean found;
3419
3420         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3421
3422         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3423                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3424
3425         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
3426
3427         if (tny_list_get_length (header_list) == 1) {
3428                 iter = tny_list_create_iterator (header_list);
3429                 header = TNY_HEADER (tny_iterator_get_current (iter));
3430                 g_object_unref (iter);
3431         } else {
3432                 return;
3433         }
3434
3435         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
3436                                                           header, &msg_view_window);
3437         flags = tny_header_get_flags (header);
3438         if (!(flags & TNY_HEADER_FLAG_CACHED))
3439                 return;
3440         if (found) {
3441                 if (msg_view_window != NULL) 
3442                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
3443                 else {
3444                         /* do nothing; uid was registered before, so window is probably on it's way */
3445                         g_warning ("debug: header %p has already been registered", header);
3446                 }
3447         } else {
3448                 ModestMailOperation *mail_op = NULL;
3449                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header);
3450                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
3451                                                                          G_OBJECT (win),
3452                                                                          modest_ui_actions_get_msgs_full_error_handler,
3453                                                                          NULL);
3454                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3455                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
3456                 
3457                 g_object_unref (mail_op);
3458         }
3459         if (header)
3460                 g_object_unref (header);
3461         if (header_list)
3462                 g_object_unref (header_list);
3463 }
3464
3465 /**
3466  * Utility function that transfer messages from both the main window
3467  * and the msg view window when using the "Move to" dialog
3468  */
3469 static void
3470 modest_ui_actions_xfer_messages_from_move_to (TnyFolderStore *dst_folder,
3471                                               ModestWindow *win)
3472 {
3473         TnyList *headers = NULL;
3474         gint response = 0;
3475
3476         if (!TNY_IS_FOLDER (dst_folder)) {
3477                 modest_platform_information_banner (GTK_WIDGET (win),
3478                                                     NULL,
3479                                                     _CS("ckdg_ib_unable_to_move_to_current_location"));
3480                 return;
3481         }
3482
3483         /* Get selected headers */
3484         headers = get_selected_headers (MODEST_WINDOW (win));
3485
3486         /* Ask for user confirmation */
3487         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
3488                                               TNY_FOLDER (dst_folder), 
3489                                               headers);
3490
3491         /* Transfer messages */
3492         if (response == GTK_RESPONSE_OK) {
3493                 ModestMailOperation *mail_op = 
3494                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3495                                                                        G_OBJECT(win),
3496                                                                        modest_ui_actions_move_folder_error_handler,
3497                                                                        NULL);
3498                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3499                                                  mail_op);
3500
3501                 modest_mail_operation_xfer_msgs (mail_op, 
3502                                                  headers,
3503                                                  TNY_FOLDER (dst_folder),
3504                                                  TRUE,
3505                                                  (MODEST_IS_MSG_VIEW_WINDOW (win)) ? transfer_msgs_from_viewer_cb : NULL,
3506                                                  NULL);
3507
3508                 g_object_unref (G_OBJECT (mail_op));
3509         }
3510         g_object_unref (headers);
3511 }
3512
3513
3514 /*
3515  * UI handler for the "Move to" action when invoked from the
3516  * ModestMainWindow
3517  */
3518 static void 
3519 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
3520                                           GtkWidget *folder_view,
3521                                           TnyFolderStore *dst_folder,
3522                                           ModestMainWindow *win)
3523 {
3524         GtkWidget *header_view = NULL;
3525         ModestMailOperation *mail_op = NULL;
3526         TnyFolderStore *src_folder;
3527
3528         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3529
3530         /* Get the source folder */
3531         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3532         
3533         /* Offer the connection dialog if necessary, if the source folder is in a networked account: */
3534         if (!modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), 
3535                                                                       src_folder))
3536                 goto end;
3537
3538         /* Get header view */
3539         header_view = 
3540                 modest_main_window_get_child_widget (win, MODEST_WIDGET_TYPE_HEADER_VIEW);
3541
3542         /* Get folder or messages to transfer */
3543         if (gtk_widget_is_focus (folder_view)) {
3544
3545                 /* Allow only to transfer folders to the local root folder */
3546                 if (TNY_IS_ACCOUNT (dst_folder) && 
3547                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder))
3548                         goto end;
3549                 
3550                 /* Clean folder on header view before moving it */
3551                 modest_header_view_clear (MODEST_HEADER_VIEW (header_view)); 
3552
3553                 if (TNY_IS_FOLDER (src_folder)) {
3554                         mail_op = 
3555                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3556                                                                                G_OBJECT(win),
3557                                                                                modest_ui_actions_move_folder_error_handler,
3558                                                                                NULL);
3559                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3560                                                          mail_op);
3561
3562                         modest_mail_operation_xfer_folder (mail_op, 
3563                                                            TNY_FOLDER (src_folder),
3564                                                            dst_folder,
3565                                                            TRUE, NULL, NULL);
3566                         /* Unref mail operation */
3567                         g_object_unref (G_OBJECT (mail_op));
3568                 } else {
3569                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);       
3570                 }
3571         } else if (gtk_widget_is_focus (header_view)) {
3572                 /* Transfer messages */
3573                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
3574         }
3575         
3576  end:
3577     if (src_folder)
3578         g_object_unref (src_folder);
3579 }
3580
3581
3582 /*
3583  * UI handler for the "Move to" action when invoked from the
3584  * ModestMsgViewWindow
3585  */
3586 static void 
3587 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
3588                                               TnyFolderStore *dst_folder,
3589                                               ModestMsgViewWindow *win)
3590 {
3591         TnyHeader *header = NULL;
3592         TnyFolder *src_folder;
3593
3594         /* Create header list */
3595         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
3596         src_folder = tny_header_get_folder(header);
3597         g_object_unref (header);
3598
3599         /* Transfer the message */
3600         if (modest_platform_connect_and_wait_if_network_folderstore (NULL, TNY_FOLDER_STORE (src_folder)))
3601                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
3602
3603         g_object_unref (src_folder);
3604 }
3605
3606 void 
3607 modest_ui_actions_on_move_to (GtkAction *action, 
3608                               ModestWindow *win)
3609 {
3610         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
3611         gint result = 0;
3612         TnyFolderStore *dst_folder = NULL;
3613         ModestMainWindow *main_window;
3614
3615         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
3616                           MODEST_IS_MSG_VIEW_WINDOW (win));
3617
3618         /* Get the main window if exists */
3619         if (MODEST_IS_MAIN_WINDOW (win))
3620                 main_window = MODEST_MAIN_WINDOW (win);
3621         else
3622                 main_window = 
3623                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
3624
3625         /* Get the folder view widget if exists */
3626         if (main_window)
3627                 folder_view = modest_main_window_get_child_widget (main_window,
3628                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
3629         else
3630                 folder_view = NULL;
3631
3632         /* Create and run the dialog */
3633         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
3634         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
3635         result = gtk_dialog_run (GTK_DIALOG(dialog));
3636         g_object_ref (tree_view);
3637         gtk_widget_destroy (dialog);
3638
3639         if (result != GTK_RESPONSE_ACCEPT)
3640                 return;
3641
3642         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
3643         /* Offer the connection dialog if necessary: */
3644         if (modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), 
3645                                                                       dst_folder)) {
3646
3647                 /* Do window specific stuff */
3648                 if (MODEST_IS_MAIN_WINDOW (win))
3649                         modest_ui_actions_on_main_window_move_to (action,
3650                                                                   folder_view,
3651                                                                   dst_folder,
3652                                                                   MODEST_MAIN_WINDOW (win));
3653                 else
3654                         modest_ui_actions_on_msg_view_window_move_to (action,
3655                                                                       dst_folder,
3656                                                                       MODEST_MSG_VIEW_WINDOW (win));
3657         }
3658         if (dst_folder)
3659                 g_object_unref (dst_folder);
3660 }
3661
3662 /*
3663  * Calls #HeadersFunc for each header already selected in the main
3664  * window or the message currently being shown in the msg view window
3665  */
3666 static void
3667 do_headers_action (ModestWindow *win, 
3668                    HeadersFunc func,
3669                    gpointer user_data)
3670 {
3671         TnyList *headers_list;
3672         TnyIterator *iter;
3673         TnyHeader *header;
3674         TnyFolder *folder;
3675
3676         /* Get headers */
3677         headers_list = get_selected_headers (win);
3678         if (!headers_list)
3679                 return;
3680
3681         /* Get the folder */
3682         iter = tny_list_create_iterator (headers_list);
3683         header = TNY_HEADER (tny_iterator_get_current (iter));
3684         folder = tny_header_get_folder (header);
3685         g_object_unref (header);
3686
3687         /* Call the function for each header */
3688         while (!tny_iterator_is_done (iter)) {
3689                 header = TNY_HEADER (tny_iterator_get_current (iter));
3690                 func (header, win, user_data);
3691                 g_object_unref (header);
3692                 tny_iterator_next (iter);
3693         }
3694
3695         /* Trick: do a poke status in order to speed up the signaling
3696            of observers */
3697         tny_folder_poke_status (folder);
3698
3699         /* Frees */
3700         g_object_unref (folder);
3701         g_object_unref (iter);
3702         g_object_unref (headers_list);
3703 }
3704
3705 void 
3706 modest_ui_actions_view_attachment (GtkAction *action,
3707                                    ModestWindow *window)
3708 {
3709         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3710                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
3711         } else {
3712                 /* not supported window for this action */
3713                 g_return_if_reached ();
3714         }
3715 }
3716
3717 void
3718 modest_ui_actions_save_attachments (GtkAction *action,
3719                                     ModestWindow *window)
3720 {
3721         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3722                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
3723         } else {
3724                 /* not supported window for this action */
3725                 g_return_if_reached ();
3726         }
3727 }
3728
3729 void
3730 modest_ui_actions_remove_attachments (GtkAction *action,
3731                                       ModestWindow *window)
3732 {
3733         if (MODEST_IS_MAIN_WINDOW (window)) {
3734                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
3735         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3736                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
3737         } else {
3738                 /* not supported window for this action */
3739                 g_return_if_reached ();
3740         }
3741 }
3742
3743 void 
3744 modest_ui_actions_on_settings (GtkAction *action, 
3745                                ModestWindow *win)
3746 {
3747         GtkWidget *dialog;
3748
3749         dialog = modest_platform_get_global_settings_dialog ();
3750         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
3751         gtk_widget_show_all (dialog);
3752
3753         gtk_dialog_run (GTK_DIALOG (dialog));
3754
3755         gtk_widget_destroy (dialog);
3756 }
3757
3758 void 
3759 modest_ui_actions_on_help (GtkAction *action, 
3760                            ModestWindow *win)
3761 {
3762         const gchar *help_id = NULL;
3763
3764         if (MODEST_IS_MAIN_WINDOW (win)) {
3765                 const gchar *action_name;
3766                 action_name = gtk_action_get_name (action);
3767
3768                 if (!strcmp (action_name, "FolderViewCSMHelp") ||
3769                     !strcmp (action_name, "HeaderViewCSMHelp")) {
3770                         GtkWidget *folder_view;
3771                         TnyFolderStore *folder_store;
3772                         /* Get selected folder */
3773                         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3774                                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
3775                         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3776
3777                         /* Switch help_id */
3778                         if (TNY_IS_FOLDER (folder_store)) {
3779                                 switch (modest_tny_folder_guess_folder_type (TNY_FOLDER (folder_store))) {
3780                                 case TNY_FOLDER_TYPE_NORMAL:
3781                                         help_id = "applications_email_managefolders";
3782                                         break;
3783                                 case TNY_FOLDER_TYPE_INBOX:
3784                                         help_id = "applications_email_inbox";
3785                                         break;
3786                                 case TNY_FOLDER_TYPE_OUTBOX:
3787                                         help_id = "applications_email_outbox";
3788                                         break;
3789                                 case TNY_FOLDER_TYPE_SENT:
3790                                         help_id = "applications_email_sent";
3791                                         break;
3792                                 case TNY_FOLDER_TYPE_DRAFTS:
3793                                         help_id = "applications_email_drafts";
3794                                         break;
3795                                 case TNY_FOLDER_TYPE_ARCHIVE:
3796                                         help_id = "applications_email_managefolders";
3797                                         break;
3798                                 default:
3799                                         help_id = "applications_email_managefolders";
3800                                 }
3801                         } else {
3802                                 help_id = "applications_email_mainview";        
3803                         }
3804                         g_object_unref (folder_store);
3805                 } else {
3806                         help_id = "applications_email_mainview";        
3807                 }
3808         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3809                 help_id = "applications_email_viewer";
3810         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
3811                 help_id = "applications_email_editor";
3812
3813         modest_platform_show_help (GTK_WINDOW (win), help_id);
3814 }
3815
3816 void 
3817 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
3818                                             ModestWindow *window)
3819 {
3820         ModestMailOperation *mail_op;
3821         TnyList *headers;
3822
3823         /* Get headers */
3824         headers = get_selected_headers (window);
3825         if (!headers)
3826                 return;
3827
3828         /* Create mail operation */
3829         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3830                                                                  G_OBJECT (window),
3831                                                                  modest_ui_actions_get_msgs_full_error_handler, 
3832                                                                  NULL);
3833         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3834         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
3835
3836         /* Frees */
3837         g_object_unref (headers);
3838         g_object_unref (mail_op);
3839 }
3840
3841 void
3842 modest_ui_actions_on_email_menu_activated (GtkAction *action,
3843                                           ModestWindow *window)
3844 {
3845         g_return_if_fail (MODEST_IS_WINDOW (window));
3846
3847         /* Update dimmed */     
3848         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3849 }
3850
3851 void
3852 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
3853                                           ModestWindow *window)
3854 {
3855         g_return_if_fail (MODEST_IS_WINDOW (window));
3856
3857         /* Update dimmed */     
3858         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3859 }
3860
3861 void
3862 modest_ui_actions_on_view_menu_activated (GtkAction *action,
3863                                           ModestWindow *window)
3864 {
3865         g_return_if_fail (MODEST_IS_WINDOW (window));
3866
3867         /* Update dimmed */     
3868         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3869 }
3870
3871 void
3872 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
3873                                           ModestWindow *window)
3874 {
3875         g_return_if_fail (MODEST_IS_WINDOW (window));
3876
3877         /* Update dimmed */     
3878         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3879 }
3880
3881 void
3882 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
3883                                           ModestWindow *window)
3884 {
3885         g_return_if_fail (MODEST_IS_WINDOW (window));
3886
3887         /* Update dimmed */     
3888         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3889 }
3890
3891 void
3892 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
3893                                                  ModestWindow *window)
3894 {
3895         g_return_if_fail (MODEST_IS_WINDOW (window));
3896
3897         /* Update dimmed */     
3898         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3899 }
3900
3901 void
3902 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
3903                                                      ModestWindow *window)
3904 {
3905         g_return_if_fail (MODEST_IS_WINDOW (window));
3906
3907         /* Update dimmed */     
3908         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3909 }
3910
3911 void
3912 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
3913                                                      ModestWindow *window)
3914 {
3915         g_return_if_fail (MODEST_IS_WINDOW (window));
3916
3917         /* Update dimmed */     
3918         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3919 }
3920
3921 void
3922 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
3923 {
3924         g_return_if_fail (MODEST_IS_WINDOW (window));
3925
3926         /* Update dimmed */     
3927         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
3928 }
3929
3930 void
3931 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
3932 {
3933         g_return_if_fail (MODEST_IS_WINDOW (window));
3934
3935         modest_platform_show_search_messages (GTK_WINDOW (window));
3936 }
3937
3938 void     
3939 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
3940 {
3941         g_return_if_fail (MODEST_IS_WINDOW (win));
3942         modest_platform_show_addressbook (GTK_WINDOW (win));
3943 }
3944
3945
3946 void
3947 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
3948                                           ModestWindow *window)
3949 {
3950         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3951
3952         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
3953 }
3954
3955 static void 
3956 _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
3957                                    ModestMailOperationState *state,
3958                                    gpointer user_data)
3959 {
3960         g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
3961
3962         /* Set send/receive operation finished */       
3963         if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3964                 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));
3965         
3966 }
3967
3968