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