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