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