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 (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                 g_object_unref (folder_store);
1505         }
1506         
1507         /* Refresh the active account */
1508         modest_ui_actions_do_send_receive (NULL, win);
1509 }
1510
1511
1512 void
1513 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
1514 {
1515         ModestConf *conf;
1516         GtkWidget *header_view;
1517         
1518         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1519
1520         header_view = modest_main_window_get_child_widget (main_window,
1521                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1522         if (!header_view)
1523                 return;
1524
1525         conf = modest_runtime_get_conf ();
1526         
1527         /* what is saved/restored is depending on the style; thus; we save with
1528          * old style, then update the style, and restore for this new style
1529          */
1530         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
1531         
1532         if (modest_header_view_get_style
1533             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
1534                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1535                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
1536         else
1537                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
1538                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
1539
1540         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1541                                       MODEST_CONF_HEADER_VIEW_KEY);
1542 }
1543
1544
1545 void 
1546 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
1547                                       TnyHeader *header,
1548                                       ModestMainWindow *main_window)
1549 {
1550         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1551         g_return_if_fail (MODEST_IS_HEADER_VIEW (header_view));
1552         
1553         /* If no header has been selected then exit */
1554         if (!header)
1555                 return;
1556
1557         /* Update focus */
1558         if (!gtk_widget_is_focus (GTK_WIDGET(header_view)))
1559             gtk_widget_grab_focus (GTK_WIDGET(header_view));
1560
1561         /* Update Main window title */
1562         if (gtk_widget_is_focus (GTK_WIDGET(header_view))) {
1563                 const gchar *subject = tny_header_get_subject (header);
1564                 if (subject && strlen(subject) > 0)
1565                         gtk_window_set_title (GTK_WINDOW (main_window), subject);
1566                 else
1567                         gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
1568         }
1569
1570         /* Update toolbar dimming state */
1571         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1572 }
1573
1574 void
1575 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1576                                        TnyHeader *header,
1577                                        ModestMainWindow *main_window)
1578 {
1579         TnyList *headers;
1580
1581         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1582         
1583         if (!header)
1584                 return;
1585
1586         headers = tny_simple_list_new ();
1587         tny_list_prepend (headers, G_OBJECT (header));
1588
1589         _modest_ui_actions_open (headers, MODEST_WINDOW (main_window));
1590
1591         g_object_unref (headers);
1592 }
1593
1594 static void
1595 set_active_account_from_tny_account (TnyAccount *account,
1596                                      ModestWindow *window)
1597 {
1598         const gchar *server_acc_name = tny_account_get_id (account);
1599         
1600         /* We need the TnyAccount provided by the
1601            account store because that is the one that
1602            knows the name of the Modest account */
1603         TnyAccount *modest_server_account = modest_server_account = 
1604                 modest_tny_account_store_get_tny_account_by (modest_runtime_get_account_store (),
1605                                                              MODEST_TNY_ACCOUNT_STORE_QUERY_ID, 
1606                                                              server_acc_name);
1607         
1608         const gchar *modest_acc_name = 
1609                 modest_tny_account_get_parent_modest_account_name_for_server_account (modest_server_account);
1610         modest_window_set_active_account (window, modest_acc_name);
1611         g_object_unref (modest_server_account);
1612 }
1613
1614
1615 static void
1616 folder_refreshed_cb (ModestMailOperation *mail_op, 
1617                      TnyFolder *folder, 
1618                      gpointer user_data)
1619 {
1620         ModestMainWindow *win = NULL;
1621         GtkWidget *header_view;
1622
1623         g_return_if_fail (TNY_IS_FOLDER (folder));
1624
1625         win = MODEST_MAIN_WINDOW (user_data);
1626         header_view = 
1627                 modest_main_window_get_child_widget(win, MODEST_WIDGET_TYPE_HEADER_VIEW);
1628
1629         /* Check if folder is empty and set headers view contents style */
1630         if (tny_folder_get_all_count (folder) == 0) {
1631         printf ("DEBUG: %s: tny_folder_get_all_count() returned 0.\n", __FUNCTION__);
1632                 modest_main_window_set_contents_style (win,
1633                                                        MODEST_MAIN_WINDOW_CONTENTS_STYLE_EMPTY);
1634         } else {
1635                 printf ("DEBUG: %s: tny_folder_get_all_count() returned >0.\n", __FUNCTION__);
1636         }
1637 }
1638
1639 void 
1640 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1641                                                TnyFolderStore *folder_store, 
1642                                                gboolean selected,
1643                                                ModestMainWindow *main_window)
1644 {
1645         ModestConf *conf;
1646         GtkWidget *header_view;
1647
1648         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1649
1650         header_view = modest_main_window_get_child_widget(main_window,
1651                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
1652         if (!header_view)
1653                 return;
1654         
1655         conf = modest_runtime_get_conf ();
1656
1657         if (TNY_IS_ACCOUNT (folder_store)) {
1658                 if (selected) {
1659                         /* Update active account */
1660                         set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1661                         /* Show account details */
1662                         modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1663                 }
1664         } else {
1665                 if (TNY_IS_FOLDER (folder_store) && selected) {
1666                         
1667                         /* Update the active account */
1668                         TnyAccount *account = modest_tny_folder_get_account (TNY_FOLDER (folder_store));
1669                         if (account) {
1670                                 set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1671                                 g_object_unref (account);
1672                                 account = NULL;
1673                         }
1674
1675                         /* Set the header style by default, it could
1676                            be changed later by the refresh callback to
1677                            empty */
1678                         modest_main_window_set_contents_style (main_window, 
1679                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1680
1681                         /* Set folder on header view. This function
1682                            will call tny_folder_refresh_async so we
1683                            pass a callback that will be called when
1684                            finished. We use that callback to set the
1685                            empty view if there are no messages */
1686                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1687                                                        TNY_FOLDER (folder_store),
1688                                                        folder_refreshed_cb,
1689                                                        main_window);
1690                         
1691                         /* Restore configuration. We need to do this
1692                            *after* the set_folder because the widget
1693                            memory asks the header view about its
1694                            folder  */
1695                         modest_widget_memory_restore (modest_runtime_get_conf (), 
1696                                                       G_OBJECT(header_view),
1697                                                       MODEST_CONF_HEADER_VIEW_KEY);
1698                 } else {
1699                         /* Update the active account */
1700                         modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
1701                         /* Save only if we're seeing headers */
1702                         if (modest_main_window_get_contents_style (main_window) ==
1703                             MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS)
1704                                 modest_widget_memory_save (conf, G_OBJECT (header_view), 
1705                                                            MODEST_CONF_HEADER_VIEW_KEY);
1706                         modest_header_view_clear (MODEST_HEADER_VIEW(header_view));
1707                 }
1708         }
1709
1710         /* Update toolbar dimming state */
1711         modest_ui_actions_check_toolbar_dimming_rules (MODEST_WINDOW (main_window));
1712 }
1713
1714 void 
1715 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1716                                      ModestWindow *win)
1717 {
1718         GtkWidget *dialog;
1719         gchar *txt, *item;
1720         gboolean online;
1721
1722         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1723         
1724         online = tny_device_is_online (modest_runtime_get_device());
1725
1726         if (online) {
1727                 /* already online -- the item is simply not there... */
1728                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1729                                                  GTK_DIALOG_MODAL,
1730                                                  GTK_MESSAGE_WARNING,
1731                                                  GTK_BUTTONS_OK,
1732                                                  _("The %s you selected cannot be found"),
1733                                                  item);
1734                 gtk_dialog_run (GTK_DIALOG(dialog));
1735         } else {
1736                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1737                                                       GTK_WINDOW (win),
1738                                                       GTK_DIALOG_MODAL,
1739                                                       GTK_STOCK_CANCEL,
1740                                                       GTK_RESPONSE_REJECT,
1741                                                       GTK_STOCK_OK,
1742                                                       GTK_RESPONSE_ACCEPT,
1743                                                       NULL);
1744                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1745                                          "Do you want to get online?"), item);
1746                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1747                                     gtk_label_new (txt), FALSE, FALSE, 0);
1748                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1749                 g_free (txt);
1750
1751                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1752                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1753 //                      modest_platform_connect_and_wait ();
1754                 }
1755         }
1756         gtk_widget_destroy (dialog);
1757 }
1758
1759 void
1760 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1761                                      ModestWindow *win)
1762 {
1763         /* g_message ("%s %s", __FUNCTION__, link); */
1764 }       
1765
1766
1767 void
1768 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1769                                         ModestWindow *win)
1770 {
1771         modest_platform_activate_uri (link);
1772 }
1773
1774 void
1775 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1776                                           ModestWindow *win)
1777 {
1778         modest_platform_show_uri_popup (link);
1779 }
1780
1781 void
1782 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1783                                              ModestWindow *win)
1784 {
1785         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
1786 }
1787
1788 void
1789 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1790                                           const gchar *address,
1791                                           ModestWindow *win)
1792 {
1793         /* g_message ("%s %s", __FUNCTION__, address); */
1794 }
1795
1796 void
1797 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1798 {
1799         TnyTransportAccount *transport_account;
1800         ModestMailOperation *mail_operation;
1801         MsgData *data;
1802         gchar *account_name, *from;
1803         ModestAccountMgr *account_mgr;
1804         gchar *info_text = NULL;
1805         TnyMsg *new_draft = NULL;
1806
1807         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1808         
1809         data = modest_msg_edit_window_get_msg_data (edit_window);
1810
1811         account_mgr = modest_runtime_get_account_mgr();
1812         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1813         if (!account_name) 
1814                 account_name = modest_account_mgr_get_default_account (account_mgr);
1815         if (!account_name) {
1816                 g_printerr ("modest: no account found\n");
1817                 modest_msg_edit_window_free_msg_data (edit_window, data);
1818                 return;
1819         }
1820
1821         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1822                 account_name = g_strdup (data->account_name);
1823         }
1824
1825         transport_account =
1826                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1827                                       (modest_runtime_get_account_store(),
1828                                        account_name,
1829                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1830         if (!transport_account) {
1831                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1832                 g_free (account_name);
1833                 modest_msg_edit_window_free_msg_data (edit_window, data);
1834                 return;
1835         }
1836         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1837
1838         /* Create the mail operation */         
1839         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
1840         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1841
1842         new_draft = modest_mail_operation_save_to_drafts (mail_operation,
1843                                                           transport_account,
1844                                                           data->draft_msg,
1845                                                           from,
1846                                                           data->to, 
1847                                                           data->cc, 
1848                                                           data->bcc,
1849                                                           data->subject, 
1850                                                           data->plain_body, 
1851                                                           data->html_body,
1852                                                           data->attachments,
1853                                                           data->priority_flags);
1854         /* Frees */
1855         g_free (from);
1856         g_free (account_name);
1857         g_object_unref (G_OBJECT (transport_account));
1858         g_object_unref (G_OBJECT (mail_operation));
1859
1860         modest_msg_edit_window_free_msg_data (edit_window, data);
1861
1862         modest_msg_edit_window_set_draft (edit_window, new_draft);
1863         if (new_draft != NULL)
1864                 g_object_unref (new_draft);
1865
1866         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
1867         modest_platform_information_banner (NULL, NULL, info_text);
1868         g_free (info_text);
1869 }
1870
1871 /* For instance, when clicking the Send toolbar button when editing a message: */
1872 void
1873 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1874 {
1875         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1876
1877         if (!modest_msg_edit_window_check_names (edit_window))
1878                 return;
1879         
1880         /* Offer the connection dialog, if necessary: */        
1881         if (!modest_platform_connect_and_wait (GTK_WINDOW (edit_window)))
1882                 return;
1883         
1884         /* FIXME: Code added just for testing. The final version will
1885            use the send queue provided by tinymail and some
1886            classifier */
1887         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
1888         gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1889         if (!account_name) 
1890                 account_name = modest_account_mgr_get_default_account (account_mgr);
1891                 
1892         if (!account_name) {
1893                 g_printerr ("modest: no account found\n");
1894                 return;
1895         }
1896         
1897         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
1898
1899         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1900                 account_name = g_strdup (data->account_name);
1901         }
1902         
1903         /* Get the currently-active transport account for this modest account: */
1904         TnyTransportAccount *transport_account =
1905                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
1906                                       (modest_runtime_get_account_store(),
1907                                        account_name));
1908         if (!transport_account) {
1909                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1910                 g_free (account_name);
1911                 modest_msg_edit_window_free_msg_data (edit_window, data);
1912                 return;
1913         }
1914         
1915         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
1916
1917         /* mail content checks and dialogs */
1918         if (data->subject == NULL || data->subject[0] == '\0') {
1919                 GtkResponseType response;
1920                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1921                                                                     _("mcen_nc_subject_is_empty_send"));
1922                 if (response == GTK_RESPONSE_CANCEL) {
1923                         g_free (account_name);
1924                         return;
1925                 }
1926         }
1927
1928         if (data->plain_body == NULL || data->plain_body[0] == '\0') {
1929                 GtkResponseType response;
1930                 gchar *note_message;
1931                 gchar *note_subject = data->subject;
1932                 if (note_subject == NULL || note_subject[0] == '\0')
1933                         note_subject = _("mail_va_no_subject");
1934                 note_message = g_strdup_printf (_("emev_ni_ui_smtp_message_null"), note_subject);
1935                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1936                                                                     note_message);
1937                 g_free (note_message);
1938                 if (response == GTK_RESPONSE_CANCEL) {
1939                         g_free (account_name);
1940                         return;
1941                 }
1942         }
1943
1944         modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
1945
1946         /* Create the mail operation */
1947         ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
1948         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1949
1950         modest_mail_operation_send_new_mail (mail_operation,
1951                                              transport_account,
1952                                              data->draft_msg,
1953                                              from,
1954                                              data->to, 
1955                                              data->cc, 
1956                                              data->bcc,
1957                                              data->subject, 
1958                                              data->plain_body, 
1959                                              data->html_body,
1960                                              data->attachments,
1961                                              data->priority_flags);
1962                                              
1963         /* Free data: */
1964         g_free (from);
1965         g_free (account_name);
1966         g_object_unref (G_OBJECT (transport_account));
1967         g_object_unref (G_OBJECT (mail_operation));
1968
1969         modest_msg_edit_window_free_msg_data (edit_window, data);
1970         modest_msg_edit_window_set_sent (edit_window, TRUE);
1971
1972         /* Save settings and close the window: */
1973         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
1974 }
1975
1976 void 
1977 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1978                                   ModestMsgEditWindow *window)
1979 {
1980         ModestMsgEditFormatState *format_state = NULL;
1981
1982         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1983         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1984
1985         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1986                 return;
1987
1988         format_state = modest_msg_edit_window_get_format_state (window);
1989         g_return_if_fail (format_state != NULL);
1990
1991         format_state->bold = gtk_toggle_action_get_active (action);
1992         modest_msg_edit_window_set_format_state (window, format_state);
1993         g_free (format_state);
1994         
1995 }
1996
1997 void 
1998 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1999                                      ModestMsgEditWindow *window)
2000 {
2001         ModestMsgEditFormatState *format_state = NULL;
2002
2003         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2004         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2005
2006         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2007                 return;
2008
2009         format_state = modest_msg_edit_window_get_format_state (window);
2010         g_return_if_fail (format_state != NULL);
2011
2012         format_state->italics = gtk_toggle_action_get_active (action);
2013         modest_msg_edit_window_set_format_state (window, format_state);
2014         g_free (format_state);
2015         
2016 }
2017
2018 void 
2019 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2020                                      ModestMsgEditWindow *window)
2021 {
2022         ModestMsgEditFormatState *format_state = NULL;
2023
2024         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2025         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2026
2027         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2028                 return;
2029
2030         format_state = modest_msg_edit_window_get_format_state (window);
2031         g_return_if_fail (format_state != NULL);
2032
2033         format_state->bullet = gtk_toggle_action_get_active (action);
2034         modest_msg_edit_window_set_format_state (window, format_state);
2035         g_free (format_state);
2036         
2037 }
2038
2039 void 
2040 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2041                                      GtkRadioAction *selected,
2042                                      ModestMsgEditWindow *window)
2043 {
2044         ModestMsgEditFormatState *format_state = NULL;
2045         GtkJustification value;
2046
2047         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2048
2049         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2050                 return;
2051
2052         value = gtk_radio_action_get_current_value (selected);
2053
2054         format_state = modest_msg_edit_window_get_format_state (window);
2055         g_return_if_fail (format_state != NULL);
2056
2057         format_state->justification = value;
2058         modest_msg_edit_window_set_format_state (window, format_state);
2059         g_free (format_state);
2060 }
2061
2062 void 
2063 modest_ui_actions_on_select_editor_color (GtkAction *action,
2064                                           ModestMsgEditWindow *window)
2065 {
2066         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2067         g_return_if_fail (GTK_IS_ACTION (action));
2068
2069         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2070                 return;
2071
2072         modest_msg_edit_window_select_color (window);
2073 }
2074
2075 void 
2076 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2077                                                      ModestMsgEditWindow *window)
2078 {
2079         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2080         g_return_if_fail (GTK_IS_ACTION (action));
2081
2082         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2083                 return;
2084
2085         modest_msg_edit_window_select_background_color (window);
2086 }
2087
2088 void 
2089 modest_ui_actions_on_insert_image (GtkAction *action,
2090                                    ModestMsgEditWindow *window)
2091 {
2092         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2093         g_return_if_fail (GTK_IS_ACTION (action));
2094
2095         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2096                 return;
2097
2098         modest_msg_edit_window_insert_image (window);
2099 }
2100
2101 void 
2102 modest_ui_actions_on_attach_file (GtkAction *action,
2103                                   ModestMsgEditWindow *window)
2104 {
2105         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2106         g_return_if_fail (GTK_IS_ACTION (action));
2107
2108         modest_msg_edit_window_attach_file (window);
2109 }
2110
2111 void 
2112 modest_ui_actions_on_remove_attachments (GtkAction *action,
2113                                          ModestMsgEditWindow *window)
2114 {
2115         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2116         g_return_if_fail (GTK_IS_ACTION (action));
2117
2118         modest_msg_edit_window_remove_attachments (window, NULL);
2119 }
2120
2121 static void
2122 modest_ui_actions_new_folder_error_handler (ModestMailOperation *mail_op,
2123                                             gpointer user_data)
2124 {
2125         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2126
2127         /* TODO: Note that folder creation might go wrong due to other
2128          * failures such as when the parent folder is non-writable. We can
2129          * query a GError* with modest_mail_operation_get_error(), but the
2130          * the error code (from tinymail) does not give us a clue about what
2131          * has gone wrong. We might use the error->message but it might come
2132          * from camel and not be suitable to show to the user directly. */
2133         modest_platform_information_banner (GTK_WIDGET (window), NULL,
2134                                             _CS("ckdg_ib_folder_already_exists"));
2135
2136 /*      modest_platform_information_banner (GTK_WIDGET (window), NULL,
2137                                             modest_mail_operation_get_error (mail_op)->message);*/
2138 }
2139
2140 void 
2141 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2142 {
2143         TnyFolderStore *parent_folder;
2144         GtkWidget *folder_view;
2145         
2146         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2147
2148         folder_view = modest_main_window_get_child_widget (main_window,
2149                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2150         if (!folder_view)
2151                 return;
2152
2153         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2154         
2155         if (parent_folder) {
2156                 gboolean finished = FALSE;
2157                 gint result;
2158                 gchar *folder_name = NULL, *suggested_name = NULL;
2159
2160                 /* Run the new folder dialog */
2161                 while (!finished) {
2162                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (main_window),
2163                                                                         parent_folder,
2164                                                                         suggested_name,
2165                                                                         &folder_name);
2166
2167                         g_free (suggested_name);
2168                         suggested_name = NULL;
2169
2170                         if (result == GTK_RESPONSE_REJECT) {
2171                                 finished = TRUE;
2172                         } else {
2173                                 ModestMailOperation *mail_op;
2174                                 TnyFolder *new_folder = NULL;
2175
2176                                 mail_op  = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2177                                                                                           G_OBJECT(main_window),
2178                                                                                           modest_ui_actions_new_folder_error_handler,
2179                                                                                           main_window);
2180
2181                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2182                                                                  mail_op);
2183                                 new_folder = modest_mail_operation_create_folder (mail_op,
2184                                                                                   parent_folder,
2185                                                                                   (const gchar *) folder_name);
2186                                 if (new_folder) {
2187                                         g_object_unref (new_folder);
2188                                         finished = TRUE;
2189                                 }
2190                                 g_object_unref (mail_op);
2191                         }
2192
2193                         suggested_name = folder_name;
2194                         folder_name = NULL;
2195                 }
2196
2197                 g_object_unref (parent_folder);
2198         }
2199 }
2200
2201 static void
2202 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2203                                                gpointer user_data)
2204 {
2205         GObject *win = modest_mail_operation_get_source (mail_op);
2206         const GError *error = NULL;
2207         const gchar *message = NULL;
2208         
2209         /* Get error message */
2210         error = modest_mail_operation_get_error (mail_op);
2211         if (error != NULL && error->message != NULL) {
2212                 message = error->message;
2213         } else {
2214                 message = _("!!! FIXME: Unable to rename");
2215         }
2216         
2217         /* Show notification dialog */
2218         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
2219         g_object_unref (win);
2220 }
2221
2222 void 
2223 modest_ui_actions_on_rename_folder (GtkAction *action,
2224                                      ModestMainWindow *main_window)
2225 {
2226         TnyFolderStore *folder;
2227         GtkWidget *folder_view;
2228         GtkWidget *header_view; 
2229
2230         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2231
2232         folder_view = modest_main_window_get_child_widget (main_window,
2233                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2234         if (!folder_view)
2235                 return;
2236
2237         header_view = modest_main_window_get_child_widget (main_window,
2238                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2239         
2240         if (!header_view)
2241                 return;
2242
2243         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2244
2245         /* Offer the connection dialog if necessary: */
2246         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2247                 g_object_unref (G_OBJECT (folder));
2248                 return;
2249         }
2250
2251         
2252         if (folder && TNY_IS_FOLDER (folder)) {
2253                 gchar *folder_name;
2254                 gint response;
2255                 const gchar *current_name;
2256
2257                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2258                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), NULL,
2259                                                                      current_name, &folder_name);
2260
2261                 if (response == GTK_RESPONSE_ACCEPT && strlen (folder_name) > 0) {
2262                         ModestMailOperation *mail_op;
2263
2264                         mail_op = 
2265                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO, 
2266                                                                                G_OBJECT(main_window),
2267                                                                                modest_ui_actions_rename_folder_error_handler,
2268                                                                                NULL);
2269
2270
2271                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2272                                                          mail_op);
2273
2274                         modest_header_view_clear (MODEST_HEADER_VIEW (header_view));
2275
2276                         modest_mail_operation_rename_folder (mail_op,
2277                                                              TNY_FOLDER (folder),
2278                                                              (const gchar *) folder_name);
2279
2280                         g_object_unref (mail_op);
2281                         g_free (folder_name);
2282                 }
2283                 g_object_unref (folder);
2284         }
2285 }
2286
2287 static void
2288 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2289                                                gpointer user_data)
2290 {
2291         GObject *win = modest_mail_operation_get_source (mail_op);
2292
2293         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2294                                                 _("mail_in_ui_folder_delete_error"));
2295         g_object_unref (win);
2296 }
2297
2298 static void
2299 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2300 {
2301         TnyFolderStore *folder;
2302         GtkWidget *folder_view;
2303         gint response;
2304         gchar *message;
2305         
2306         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2307
2308         folder_view = modest_main_window_get_child_widget (main_window,
2309                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2310         if (!folder_view)
2311                 return;
2312
2313         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2314
2315         /* Show an error if it's an account */
2316         if (!TNY_IS_FOLDER (folder)) {
2317                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2318                                                         _("mail_in_ui_folder_delete_error"));
2319                 g_object_unref (G_OBJECT (folder));
2320                 return ;
2321         }
2322
2323         /* Offer the connection dialog if necessary: */
2324         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2325                 g_object_unref (G_OBJECT (folder));
2326                 return;
2327         }
2328
2329         /* Ask the user */      
2330         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2331                                     tny_folder_get_name (TNY_FOLDER (folder)));
2332         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2333                                                             (const gchar *) message);
2334         g_free (message);
2335
2336         if (response == GTK_RESPONSE_OK) {
2337                 ModestMailOperation *mail_op = 
2338                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
2339                                                                        G_OBJECT(main_window),
2340                                                                        modest_ui_actions_delete_folder_error_handler,
2341                                                                        NULL);
2342
2343                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2344                                                  mail_op);
2345                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2346                 g_object_unref (G_OBJECT (mail_op));
2347         }
2348
2349         g_object_unref (G_OBJECT (folder));
2350 }
2351
2352 void 
2353 modest_ui_actions_on_delete_folder (GtkAction *action,
2354                                      ModestMainWindow *main_window)
2355 {
2356         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2357
2358         delete_folder (main_window, FALSE);
2359 }
2360
2361 void 
2362 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2363 {
2364         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2365         
2366         delete_folder (main_window, TRUE);
2367 }
2368
2369 void
2370 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2371                                          const gchar* server_account_name,
2372                                          gchar **username,
2373                                          gchar **password, 
2374                                          gboolean *cancel, 
2375                                          gboolean *remember,
2376                                          ModestMainWindow *main_window)
2377 {
2378         g_return_if_fail(server_account_name);
2379         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2380         
2381         /* Initalize output parameters: */
2382         if (cancel)
2383                 *cancel = FALSE;
2384                 
2385         if (remember)
2386                 *remember = TRUE;
2387                 
2388 #ifdef MODEST_PLATFORM_MAEMO
2389         /* Maemo uses a different (awkward) button order,
2390          * It should probably just use gtk_alternative_dialog_button_order ().
2391          */
2392         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2393                                               NULL,
2394                                               GTK_DIALOG_MODAL,
2395                                               GTK_STOCK_OK,
2396                                               GTK_RESPONSE_ACCEPT,
2397                                               GTK_STOCK_CANCEL,
2398                                               GTK_RESPONSE_REJECT,
2399                                               NULL);
2400 #else
2401         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2402                                               NULL,
2403                                               GTK_DIALOG_MODAL,
2404                                               GTK_STOCK_CANCEL,
2405                                               GTK_RESPONSE_REJECT,
2406                                               GTK_STOCK_OK,
2407                                               GTK_RESPONSE_ACCEPT,
2408                                               NULL);
2409 #endif /* MODEST_PLATFORM_MAEMO */
2410
2411         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2412         
2413         gchar *server_name = modest_server_account_get_hostname (
2414                 modest_runtime_get_account_mgr(), server_account_name);
2415         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2416                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2417                 *cancel = TRUE;
2418                 return;
2419         }
2420         
2421         /* This causes a warning because the logical ID has no %s in it, 
2422          * though the translation does, but there is not much we can do about that: */
2423         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2424         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2425                             FALSE, FALSE, 0);
2426         g_free (txt);
2427         g_free (server_name);
2428         server_name = NULL;
2429
2430         /* username: */
2431         gchar *initial_username = modest_server_account_get_username (
2432                 modest_runtime_get_account_mgr(), server_account_name);
2433         
2434         GtkWidget *entry_username = gtk_entry_new ();
2435         if (initial_username)
2436                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2437         /* Dim this if a connection has ever succeeded with this username,
2438          * as per the UI spec: */
2439         const gboolean username_known = 
2440                 modest_server_account_get_username_has_succeeded(
2441                         modest_runtime_get_account_mgr(), server_account_name);
2442         gtk_widget_set_sensitive (entry_username, !username_known);
2443         
2444 #ifdef MODEST_PLATFORM_MAEMO
2445         /* Auto-capitalization is the default, so let's turn it off: */
2446         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2447         
2448         /* Create a size group to be used by all captions.
2449          * Note that HildonCaption does not create a default size group if we do not specify one.
2450          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2451         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2452         
2453         GtkWidget *caption = hildon_caption_new (sizegroup, 
2454                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2455         gtk_widget_show (entry_username);
2456         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2457                 FALSE, FALSE, MODEST_MARGIN_HALF);
2458         gtk_widget_show (caption);
2459 #else 
2460         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2461                             TRUE, FALSE, 0);
2462 #endif /* MODEST_PLATFORM_MAEMO */      
2463                             
2464         /* password: */
2465         GtkWidget *entry_password = gtk_entry_new ();
2466         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2467         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2468         
2469 #ifdef MODEST_PLATFORM_MAEMO
2470         /* Auto-capitalization is the default, so let's turn it off: */
2471         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2472                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2473         
2474         caption = hildon_caption_new (sizegroup, 
2475                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2476         gtk_widget_show (entry_password);
2477         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2478                 FALSE, FALSE, MODEST_MARGIN_HALF);
2479         gtk_widget_show (caption);
2480         g_object_unref (sizegroup);
2481 #else 
2482         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2483                             TRUE, FALSE, 0);
2484 #endif /* MODEST_PLATFORM_MAEMO */      
2485                                 
2486 /* This is not in the Maemo UI spec:
2487         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2488         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2489                             TRUE, FALSE, 0);
2490 */
2491
2492         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2493         
2494         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2495                 if (username) {
2496                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2497                         
2498                         modest_server_account_set_username (
2499                                  modest_runtime_get_account_mgr(), server_account_name, 
2500                                  *username);
2501                                  
2502                         const gboolean username_was_changed = 
2503                                 (strcmp (*username, initial_username) != 0);
2504                         if (username_was_changed) {
2505                                 g_warning ("%s: tinymail does not yet support changing the "
2506                                         "username in the get_password() callback.\n", __FUNCTION__);
2507                         }
2508                 }
2509                         
2510                 if (password) {
2511                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2512                         
2513                         /* We do not save the password in the configuration, 
2514                          * because this function is only called for passwords that should 
2515                          * not be remembered:
2516                         modest_server_account_set_password (
2517                                  modest_runtime_get_account_mgr(), server_account_name, 
2518                                  *password);
2519                         */
2520                 }
2521                 
2522                 if (cancel)
2523                         *cancel   = FALSE;
2524                         
2525         } else {
2526                 if (username)
2527                         *username = NULL;
2528                         
2529                 if (password)
2530                         *password = NULL;
2531                         
2532                 if (cancel)
2533                         *cancel   = TRUE;
2534         }
2535
2536 /* This is not in the Maemo UI spec:
2537         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2538                 *remember = TRUE;
2539         else
2540                 *remember = FALSE;
2541 */
2542
2543         gtk_widget_destroy (dialog);
2544         
2545         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2546 }
2547
2548 void
2549 modest_ui_actions_on_cut (GtkAction *action,
2550                           ModestWindow *window)
2551 {
2552         GtkWidget *focused_widget;
2553
2554         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2555         if (GTK_IS_EDITABLE (focused_widget)) {
2556                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2557         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2558                 GtkTextBuffer *buffer;
2559                 GtkClipboard *clipboard;
2560
2561                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2562                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2563                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2564                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2565         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2566                 modest_header_view_cut_selection (MODEST_HEADER_VIEW (focused_widget));
2567         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2568                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2569         }
2570 }
2571
2572 void
2573 modest_ui_actions_on_copy (GtkAction *action,
2574                            ModestWindow *window)
2575 {
2576         GtkClipboard *clipboard;
2577         GtkWidget *focused_widget;
2578
2579         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2580         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2581
2582         if (GTK_IS_LABEL (focused_widget)) {
2583                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2584         } else if (GTK_IS_EDITABLE (focused_widget)) {
2585                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2586         } else if (GTK_IS_HTML (focused_widget)) {
2587                 gtk_html_copy (GTK_HTML (focused_widget));
2588         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2589                 GtkTextBuffer *buffer;
2590                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2591                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2592                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2593         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2594                 TnyList *header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (focused_widget));
2595                 TnyIterator *iter = tny_list_create_iterator (header_list);
2596                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2597                 TnyFolder *folder = tny_header_get_folder (header);
2598                 TnyAccount *account = tny_folder_get_account (folder);
2599                 const gchar *proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2600                 /* If it's POP then ask */
2601                 gboolean ask = (modest_protocol_info_get_transport_store_protocol (proto_str) == 
2602                        MODEST_PROTOCOL_STORE_POP) ? TRUE : FALSE;
2603                 g_object_unref (account);
2604                 g_object_unref (folder);
2605                 g_object_unref (header);
2606                 g_object_unref (iter);
2607                 
2608                 /* Check that the messages have been previously downloaded */
2609                 gboolean continue_download = TRUE;
2610                 if (ask)
2611                         continue_download = download_uncached_messages (header_list, GTK_WINDOW (window));
2612                 if (continue_download)
2613                         modest_header_view_copy_selection (MODEST_HEADER_VIEW (focused_widget));
2614                 g_object_unref (header_list);
2615         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2616                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
2617         }    
2618
2619         /* Show information banner */
2620         modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
2621         
2622 }
2623
2624 void
2625 modest_ui_actions_on_undo (GtkAction *action,
2626                            ModestWindow *window)
2627 {
2628         ModestEmailClipboard *clipboard = NULL;
2629
2630         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2631                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2632         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2633                 /* Clear clipboard source */
2634                 clipboard = modest_runtime_get_email_clipboard ();
2635                 modest_email_clipboard_clear (clipboard);               
2636         }
2637         else {
2638                 g_return_if_reached ();
2639         }
2640 }
2641
2642 void
2643 modest_ui_actions_on_redo (GtkAction *action,
2644                            ModestWindow *window)
2645 {
2646         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2647                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
2648         }
2649         else {
2650                 g_return_if_reached ();
2651         }
2652 }
2653
2654
2655 static void
2656 paste_msgs_cb (const GObject *object, gpointer user_data)
2657 {
2658         g_return_if_fail (MODEST_IS_MAIN_WINDOW (object));
2659         g_return_if_fail (GTK_IS_WIDGET (user_data));
2660         
2661         /* destroy information note */
2662         gtk_widget_destroy (GTK_WIDGET(user_data));
2663 }
2664
2665 void
2666 modest_ui_actions_on_paste (GtkAction *action,
2667                             ModestWindow *window)
2668 {
2669         GtkWidget *focused_widget = NULL;
2670         GtkWidget *inf_note = NULL;
2671         ModestMailOperation *mail_op = NULL;
2672
2673         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2674         if (GTK_IS_EDITABLE (focused_widget)) {
2675                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
2676         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2677                 GtkTextBuffer *buffer;
2678                 GtkClipboard *clipboard;
2679
2680                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2681                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2682                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
2683         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2684                 ModestEmailClipboard *clipboard = NULL;
2685                 TnyFolder *src_folder = NULL;
2686                 TnyFolderStore *folder_store = NULL;
2687                 TnyList *data = NULL;           
2688                 gboolean delete = FALSE;
2689                 
2690                 /* Check clipboard source */
2691                 clipboard = modest_runtime_get_email_clipboard ();
2692                 if (modest_email_clipboard_cleared (clipboard)) 
2693                         return;
2694                 
2695                 /* Get elements to paste */
2696                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
2697
2698                 /* Create a new mail operation */
2699                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
2700                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2701                                                  mail_op);
2702                 
2703                 /* Get destination folder */
2704                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
2705
2706                 /* Launch notification */
2707                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
2708                                                              _CS("ckct_nw_pasting"));
2709                 if (inf_note != NULL)  {
2710                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
2711                         gtk_widget_show (GTK_WIDGET(inf_note));
2712                 }
2713
2714                 /* transfer messages  */
2715                 if (data != NULL) {
2716                         modest_mail_operation_xfer_msgs (mail_op, 
2717                                                          data,
2718                                                          TNY_FOLDER (folder_store),
2719                                                          delete,
2720                                                          paste_msgs_cb,
2721                                                          inf_note);
2722                         
2723                 } else if (src_folder != NULL) {                        
2724                         modest_mail_operation_xfer_folder (mail_op, 
2725                                                            src_folder,
2726                                                            folder_store,
2727                                                            delete,
2728                                                            paste_msgs_cb,
2729                                                            inf_note);
2730                 }
2731
2732                 /* Free */
2733                 if (data != NULL) 
2734                         g_object_unref (data);
2735                 if (src_folder != NULL) 
2736                         g_object_unref (src_folder);
2737                 if (folder_store != NULL) 
2738                         g_object_unref (folder_store);
2739         }
2740 }
2741
2742
2743 void
2744 modest_ui_actions_on_select_all (GtkAction *action,
2745                                  ModestWindow *window)
2746 {
2747         GtkWidget *focused_widget;
2748
2749         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2750         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
2751                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
2752         } else if (GTK_IS_LABEL (focused_widget)) {
2753                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
2754         } else if (GTK_IS_EDITABLE (focused_widget)) {
2755                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
2756         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2757                 GtkTextBuffer *buffer;
2758                 GtkTextIter start, end;
2759
2760                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2761                 gtk_text_buffer_get_start_iter (buffer, &start);
2762                 gtk_text_buffer_get_end_iter (buffer, &end);
2763                 gtk_text_buffer_select_range (buffer, &start, &end);
2764         } else if (GTK_IS_HTML (focused_widget)) {
2765                 gtk_html_select_all (GTK_HTML (focused_widget));
2766         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2767                 GtkWidget *header_view = focused_widget;
2768                 GtkTreeSelection *selection = NULL;
2769                 
2770                 if (!(MODEST_IS_HEADER_VIEW (focused_widget)))
2771                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
2772                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2773                                 
2774                 /* Select all messages */
2775                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
2776                 gtk_tree_selection_select_all (selection);
2777
2778                 /* Set focuse on header view */
2779                 gtk_widget_grab_focus (header_view);
2780         }
2781
2782 }
2783
2784 void
2785 modest_ui_actions_on_mark_as_read (GtkAction *action,
2786                                    ModestWindow *window)
2787 {       
2788         g_return_if_fail (MODEST_IS_WINDOW(window));
2789                 
2790         /* Mark each header as read */
2791         do_headers_action (window, headers_action_mark_as_read, NULL);
2792 }
2793
2794 void
2795 modest_ui_actions_on_mark_as_unread (GtkAction *action,
2796                                      ModestWindow *window)
2797 {       
2798         g_return_if_fail (MODEST_IS_WINDOW(window));
2799                 
2800         /* Mark each header as read */
2801         do_headers_action (window, headers_action_mark_as_unread, NULL);
2802 }
2803
2804 void
2805 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
2806                                   GtkRadioAction *selected,
2807                                   ModestWindow *window)
2808 {
2809         gint value;
2810
2811         value = gtk_radio_action_get_current_value (selected);
2812         if (MODEST_IS_WINDOW (window)) {
2813                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
2814         }
2815 }
2816
2817 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
2818                                                         GtkRadioAction *selected,
2819                                                         ModestWindow *window)
2820 {
2821         TnyHeaderFlags flags;
2822         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2823
2824         flags = gtk_radio_action_get_current_value (selected);
2825         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
2826 }
2827
2828 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
2829                                                            GtkRadioAction *selected,
2830                                                            ModestWindow *window)
2831 {
2832         gint file_format;
2833
2834         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2835
2836         file_format = gtk_radio_action_get_current_value (selected);
2837         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
2838 }
2839
2840
2841 void     
2842 modest_ui_actions_on_zoom_plus (GtkAction *action,
2843                                 ModestWindow *window)
2844 {
2845         g_return_if_fail (MODEST_IS_WINDOW (window));
2846
2847         modest_window_zoom_plus (MODEST_WINDOW (window));
2848 }
2849
2850 void     
2851 modest_ui_actions_on_zoom_minus (GtkAction *action,
2852                                  ModestWindow *window)
2853 {
2854         g_return_if_fail (MODEST_IS_WINDOW (window));
2855
2856         modest_window_zoom_minus (MODEST_WINDOW (window));
2857 }
2858
2859 void     
2860 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
2861                                            ModestWindow *window)
2862 {
2863         ModestWindowMgr *mgr;
2864         gboolean fullscreen, active;
2865         g_return_if_fail (MODEST_IS_WINDOW (window));
2866
2867         mgr = modest_runtime_get_window_mgr ();
2868
2869         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
2870         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2871
2872         if (active != fullscreen) {
2873                 modest_window_mgr_set_fullscreen_mode (mgr, active);
2874                 gtk_window_present (GTK_WINDOW (window));
2875         }
2876 }
2877
2878 void
2879 modest_ui_actions_on_change_fullscreen (GtkAction *action,
2880                                         ModestWindow *window)
2881 {
2882         ModestWindowMgr *mgr;
2883         gboolean fullscreen;
2884
2885         g_return_if_fail (MODEST_IS_WINDOW (window));
2886
2887         mgr = modest_runtime_get_window_mgr ();
2888         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2889         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
2890
2891         gtk_window_present (GTK_WINDOW (window));
2892 }
2893
2894 /* 
2895  * Used by modest_ui_actions_on_details to call do_headers_action 
2896  */
2897 static void
2898 headers_action_show_details (TnyHeader *header, 
2899                              ModestWindow *window,
2900                              gpointer user_data)
2901
2902 {
2903         GtkWidget *dialog;
2904         
2905         /* Create dialog */
2906         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
2907
2908         /* Run dialog */
2909         gtk_widget_show_all (dialog);
2910         gtk_dialog_run (GTK_DIALOG (dialog));
2911
2912         gtk_widget_destroy (dialog);
2913 }
2914
2915 /*
2916  * Show the folder details in a ModestDetailsDialog widget
2917  */
2918 static void
2919 show_folder_details (TnyFolder *folder, 
2920                      GtkWindow *window)
2921 {
2922         GtkWidget *dialog;
2923         
2924         /* Create dialog */
2925         dialog = modest_details_dialog_new_with_folder (window, folder);
2926
2927         /* Run dialog */
2928         gtk_widget_show_all (dialog);
2929         gtk_dialog_run (GTK_DIALOG (dialog));
2930
2931         gtk_widget_destroy (dialog);
2932 }
2933
2934 /*
2935  * Show the header details in a ModestDetailsDialog widget
2936  */
2937 void     
2938 modest_ui_actions_on_details (GtkAction *action, 
2939                               ModestWindow *win)
2940 {
2941         TnyList * headers_list;
2942         TnyIterator *iter;
2943         TnyHeader *header;              
2944
2945         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
2946                 TnyMsg *msg;
2947
2948                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
2949                 if (!msg)
2950                         return;
2951                 g_object_unref (msg);           
2952
2953                 headers_list = get_selected_headers (win);
2954                 if (!headers_list)
2955                         return;
2956
2957                 iter = tny_list_create_iterator (headers_list);
2958
2959                 header = TNY_HEADER (tny_iterator_get_current (iter));
2960                 headers_action_show_details (header, win, NULL);
2961                 g_object_unref (header);
2962
2963                 g_object_unref (iter);
2964                 g_object_unref (headers_list);
2965
2966         } else if (MODEST_IS_MAIN_WINDOW (win)) {
2967                 GtkWidget *folder_view, *header_view;
2968
2969                 /* Check which widget has the focus */
2970                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2971                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
2972                 if (gtk_widget_is_focus (folder_view)) {
2973                         TnyFolderStore *folder_store
2974                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2975                         if (!folder_store) {
2976                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
2977                                 return; 
2978                         }
2979                         /* Show only when it's a folder */
2980                         /* This function should not be called for account items, 
2981                          * because we dim the menu item for them. */
2982                         if (TNY_IS_FOLDER (folder_store)) {
2983                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
2984                         }
2985
2986                         g_object_unref (folder_store);
2987
2988                 } else {
2989                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2990                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2991                         /* Show details of each header */
2992                         do_headers_action (win, headers_action_show_details, header_view);
2993                 }
2994         }
2995 }
2996
2997 void     
2998 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
2999                                      ModestMsgEditWindow *window)
3000 {
3001         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3002
3003         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3004 }
3005
3006 void     
3007 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3008                                       ModestMsgEditWindow *window)
3009 {
3010         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3011
3012         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3013 }
3014
3015 void
3016 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3017                                        ModestMainWindow *main_window)
3018 {
3019         ModestConf *conf;
3020         
3021         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3022
3023         conf = modest_runtime_get_conf ();
3024         
3025         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
3026                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3027         else
3028                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3029 }
3030
3031 void 
3032 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3033                                      ModestWindow *window)
3034 {
3035         gboolean active, fullscreen = FALSE;
3036         ModestWindowMgr *mgr;
3037
3038         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3039
3040         /* Check if we want to toggle the toolbar vuew in fullscreen
3041            or normal mode */
3042         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3043                      "ViewShowToolbarFullScreen")) {
3044                 fullscreen = TRUE;
3045         }
3046
3047         /* Toggle toolbar */
3048         mgr = modest_runtime_get_window_mgr ();
3049         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
3050 }
3051
3052 void     
3053 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3054                                            ModestMsgEditWindow *window)
3055 {
3056         modest_msg_edit_window_select_font (window);
3057 }
3058
3059 void
3060 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3061                                                   const gchar *display_name,
3062                                                   GtkWindow *window)
3063 {
3064         /* Do not change the application name if the widget has not
3065            the focus. This callback could be called even if the folder
3066            view has not the focus, because the handled signal could be
3067            emitted when the folder view is redrawn */
3068         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3069                 if (display_name)
3070                         gtk_window_set_title (window, display_name);
3071                 else
3072                         gtk_window_set_title (window, " ");
3073         }
3074 }
3075
3076 void
3077 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3078 {
3079         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3080         modest_msg_edit_window_select_contacts (window);
3081 }
3082
3083 void
3084 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3085 {
3086         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3087         modest_msg_edit_window_check_names (window);
3088 }
3089
3090
3091 static GtkWidget*
3092 create_move_to_dialog (ModestWindow *win,
3093                        GtkWidget *folder_view,
3094                        GtkWidget **tree_view)
3095 {
3096         GtkWidget *dialog, *scroll;
3097
3098         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3099                                               GTK_WINDOW (win),
3100                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3101                                               GTK_STOCK_OK,
3102                                               GTK_RESPONSE_ACCEPT,
3103                                               GTK_STOCK_CANCEL,
3104                                               GTK_RESPONSE_REJECT,
3105                                               NULL);
3106
3107         /* Create scrolled window */
3108         scroll = gtk_scrolled_window_new (NULL, NULL);
3109         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3110                                          GTK_POLICY_AUTOMATIC,
3111                                          GTK_POLICY_AUTOMATIC);
3112
3113         /* Create folder view */
3114         *tree_view = modest_platform_create_folder_view (NULL);
3115
3116         /* It could happen that we're trying to move a message from a
3117            window (msg window for example) after the main window was
3118            closed, so we can not just get the model of the folder
3119            view */
3120         if (MODEST_IS_FOLDER_VIEW (folder_view))
3121                 gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
3122                                          gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
3123         else
3124                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
3125                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3126
3127         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3128
3129         /* Add scroll to dialog */
3130         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
3131                             scroll, FALSE, FALSE, 0);
3132
3133         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3134
3135         /* Select INBOX or local account */
3136         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (*tree_view));
3137
3138         return dialog;
3139 }
3140
3141 /*
3142  * Returns TRUE if at least one of the headers of the list belongs to
3143  * a message that has been fully retrieved.
3144  */
3145 static gboolean
3146 has_retrieved_msgs (TnyList *list)
3147 {
3148         TnyIterator *iter;
3149         gboolean found = FALSE;
3150
3151         iter = tny_list_create_iterator (list);
3152         while (tny_iterator_is_done (iter) && !found) {
3153                 TnyHeader *header;
3154                 TnyHeaderFlags flags;
3155
3156                 header = TNY_HEADER (tny_iterator_get_current (iter));
3157                 flags = tny_header_get_flags (header);
3158                 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
3159                         found = TRUE;
3160
3161                 if (!found)
3162                         tny_iterator_next (iter);
3163         }
3164         g_object_unref (iter);
3165
3166         return found;
3167 }
3168
3169 /*
3170  * Shows a confirmation dialog to the user when we're moving messages
3171  * from a remote server to the local storage. Returns the dialog
3172  * response. If it's other kind of movement the it always returns
3173  * GTK_RESPONSE_OK
3174  */
3175 static gint
3176 msgs_move_to_confirmation (GtkWindow *win,
3177                            TnyFolder *dest_folder,
3178                            TnyList *headers)
3179 {
3180         gint response = GTK_RESPONSE_OK;
3181
3182         /* If the destination is a local folder */
3183         if (modest_tny_folder_is_local_folder (dest_folder)) {
3184                 TnyFolder *src_folder;
3185                 TnyIterator *iter;
3186                 TnyHeader *header;
3187
3188                 /* Get source folder */
3189                 iter = tny_list_create_iterator (headers);
3190                 header = TNY_HEADER (tny_iterator_get_current (iter));
3191                 src_folder = tny_header_get_folder (header);
3192                 g_object_unref (header);
3193                 g_object_unref (iter);
3194
3195                 /* if no src_folder, message may be an attahcment */
3196                 if (src_folder == NULL) 
3197                         return GTK_RESPONSE_CANCEL;
3198
3199                 /* If the source is a remote folder */
3200                 if (!modest_tny_folder_is_local_folder (src_folder)) {
3201                         const gchar *message;
3202                         
3203                         if (has_retrieved_msgs (headers))
3204                                 message = ngettext ("mcen_nc_move_retrieve", "mcen_nc_move_retrieves",
3205                                                     tny_list_get_length (headers));
3206                         else 
3207                                 message = ngettext ("mcen_nc_move_header", "mcen_nc_move_headers",
3208                                                     tny_list_get_length (headers));
3209
3210                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
3211                                                                             (const gchar *) message);
3212                 }
3213                 g_object_unref (src_folder);
3214         }
3215         return response;
3216 }
3217
3218
3219
3220 static void
3221 transfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
3222 {
3223         ModestMsgViewWindow *self = NULL;
3224         gboolean last, first;
3225
3226         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
3227         self = MODEST_MSG_VIEW_WINDOW (object);
3228         
3229         last = modest_msg_view_window_last_message_selected (self);
3230         first = modest_msg_view_window_first_message_selected (self);   
3231         if (last & first) {
3232                 /* No more messages to view, so close this window */
3233 /*              gboolean ret_value; */
3234 /*              g_signal_emit_by_name (G_OBJECT (self), "delete-event", NULL, &ret_value); */
3235                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
3236         } else if (last)
3237                 modest_msg_view_window_select_previous_message (self);
3238         else 
3239                 modest_msg_view_window_select_next_message (self);
3240 }
3241
3242 void
3243 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
3244                                              gpointer user_data)
3245 {
3246         GObject *win = modest_mail_operation_get_source (mail_op);
3247         const GError *error = NULL;
3248         const gchar *message = NULL;
3249         
3250         /* Get error message */
3251         error = modest_mail_operation_get_error (mail_op);
3252         if (error != NULL && error->message != NULL) {
3253                 message = error->message;
3254         } else {
3255                 message = _("mail_in_ui_folder_move_target_error");
3256         }
3257         
3258         /* Show notification dialog */
3259         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
3260         g_object_unref (win);
3261 }
3262
3263 void
3264 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
3265                                               gpointer user_data)
3266 {
3267         GObject *win = modest_mail_operation_get_source (mail_op);
3268         const GError *error = modest_mail_operation_get_error (mail_op);
3269
3270         g_return_if_fail (error != NULL);
3271         if (error->message != NULL)             
3272                 g_printerr ("modest: %s\n", error->message);
3273         else
3274                 g_printerr ("modest: unkonw error on send&receive operation");
3275
3276         /* Show error message */
3277 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
3278 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3279 /*                                                      _CS("sfil_ib_unable_to_receive")); */
3280 /*      else  */
3281 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3282 /*                                                      _CS("sfil_ib_unable_to_send")); */
3283         g_object_unref (win);
3284 }
3285
3286 static void
3287 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
3288                        TnyHeader *header, 
3289                        TnyMsg *msg, 
3290                        gpointer user_data)
3291 {
3292         TnyList *parts;
3293         TnyIterator *iter;
3294         gint pending_purges = 0;
3295         gboolean some_purged = FALSE;
3296         ModestWindow *win = MODEST_WINDOW (user_data);
3297
3298         /* If there was any error */
3299         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
3300                 return;
3301
3302         /* Once the message has been retrieved for purging, we check if
3303          * it's all ok for purging */
3304
3305         parts = tny_simple_list_new ();
3306         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
3307         iter = tny_list_create_iterator (parts);
3308
3309         while (!tny_iterator_is_done (iter)) {
3310                 TnyMimePart *part;
3311                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3312                 if (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)) {
3313                         if (tny_mime_part_is_purged (part))
3314                                 some_purged = TRUE;
3315                         else
3316                                 pending_purges++;
3317                 }
3318                 tny_iterator_next (iter);
3319         }
3320
3321         if (pending_purges>0) {
3322                 gint response;
3323                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
3324
3325                 if (response == GTK_RESPONSE_OK) {
3326                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
3327                         tny_iterator_first (iter);
3328                         while (!tny_iterator_is_done (iter)) {
3329                                 TnyMimePart *part;
3330                                 
3331                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3332                                 if (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))
3333                                         tny_mime_part_set_purged (part);
3334                                 tny_iterator_next (iter);
3335                         }
3336                         
3337                         tny_msg_rewrite_cache (msg);
3338                 }
3339         } else {
3340                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
3341         }
3342
3343         /* remove attachments */
3344         tny_iterator_first (iter);
3345         while (!tny_iterator_is_done (iter)) {
3346                 TnyMimePart *part;
3347                         
3348                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3349                 g_object_unref (part);
3350                 tny_iterator_next (iter);
3351         }
3352
3353         g_object_unref (iter);
3354         g_object_unref (parts);
3355 }
3356
3357 static void
3358 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
3359                                                      ModestMainWindow *win)
3360 {
3361         GtkWidget *header_view;
3362         TnyList *header_list;
3363         TnyIterator *iter;
3364         TnyHeader *header;
3365         TnyHeaderFlags flags;
3366         ModestWindow *msg_view_window =  NULL;
3367         gboolean found;
3368
3369         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3370
3371         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3372                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3373
3374         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
3375
3376         if (tny_list_get_length (header_list) == 1) {
3377                 iter = tny_list_create_iterator (header_list);
3378                 header = TNY_HEADER (tny_iterator_get_current (iter));
3379                 g_object_unref (iter);
3380         } else {
3381                 return;
3382         }
3383
3384         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
3385                                                           header, &msg_view_window);
3386         flags = tny_header_get_flags (header);
3387         if (!(flags & TNY_HEADER_FLAG_CACHED))
3388                 return;
3389         if (found) {
3390                 if (msg_view_window != NULL) 
3391                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
3392                 else {
3393                         /* do nothing; uid was registered before, so window is probably on it's way */
3394                         g_warning ("debug: header %p has already been registered", header);
3395                 }
3396         } else {
3397                 ModestMailOperation *mail_op = NULL;
3398                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header);
3399                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
3400                                                                          G_OBJECT (win),
3401                                                                          modest_ui_actions_get_msgs_full_error_handler,
3402                                                                          NULL);
3403                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3404                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
3405                 
3406                 g_object_unref (mail_op);
3407         }
3408         if (header)
3409                 g_object_unref (header);
3410         if (header_list)
3411                 g_object_unref (header_list);
3412 }
3413
3414 /*
3415  * UI handler for the "Move to" action when invoked from the
3416  * ModestMainWindow
3417  */
3418 static void 
3419 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
3420                                           ModestMainWindow *win)
3421 {
3422         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
3423         GtkWidget *header_view = NULL;
3424         gint result = 0;
3425         TnyFolderStore *folder_store = NULL;
3426         ModestMailOperation *mail_op = NULL;
3427
3428         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3429
3430         /* Get the folder view */
3431         folder_view = modest_main_window_get_child_widget (win,
3432                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
3433                                                            
3434         TnyFolderStore *src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3435         
3436         /* Offer the connection dialog if necessary, if the source folder is in a networked account: */
3437         if (!modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), src_folder)) {
3438                 if (src_folder) {
3439                         g_object_unref (src_folder);
3440                 }
3441                 
3442                 return;
3443         }
3444
3445         /* Get header view */
3446         header_view = modest_main_window_get_child_widget (win,
3447                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3448
3449         /* Create and run the dialog */
3450         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);
3451         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
3452         result = gtk_dialog_run (GTK_DIALOG(dialog));
3453         g_object_ref (tree_view);
3454
3455         /* We do this to save an indentation level ;-) */
3456         if (result != GTK_RESPONSE_ACCEPT)
3457                 goto end;
3458
3459         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
3460
3461         if (TNY_IS_ACCOUNT (folder_store) && 
3462             !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (folder_store))
3463                 goto end;
3464
3465         /* Offer the connection dialog if necessary: */
3466         if (!modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), folder_store)) {
3467                         goto end;
3468         }
3469
3470         /* Get folder or messages to transfer */
3471         if (gtk_widget_is_focus (folder_view)) {
3472                 
3473                 /* Clean folder on header view before moving it */
3474                 modest_header_view_clear (MODEST_HEADER_VIEW (header_view)); 
3475
3476                 if (TNY_IS_FOLDER (src_folder)) {
3477                         mail_op = 
3478                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3479                                                                        G_OBJECT(win),
3480                                                                        modest_ui_actions_move_folder_error_handler,
3481                                                                        NULL);
3482                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3483
3484                         modest_mail_operation_xfer_folder (mail_op, 
3485                                                            TNY_FOLDER (src_folder),
3486                                                            folder_store,
3487                                                            TRUE, NULL, NULL);
3488                         /* Unref mail operation */
3489                         g_object_unref (G_OBJECT (mail_op));
3490                 } else {
3491                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);       
3492                 }
3493         } else {
3494                 if (gtk_widget_is_focus (header_view)) {
3495                         TnyList *headers = NULL;
3496                         gint response = 0;
3497
3498                         /* TODO: Check for connection if the headers are on a network account. */
3499                         headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
3500
3501                         /* Ask for user confirmation */
3502                         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
3503                                                               TNY_FOLDER (folder_store), 
3504                                                               headers);
3505
3506                         /* Transfer messages */
3507                         if (response == GTK_RESPONSE_OK) {
3508                                 mail_op = 
3509                                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3510                                                                                        G_OBJECT(win),
3511                                                                                        modest_ui_actions_move_folder_error_handler,
3512                                                                                        NULL);
3513                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3514                                                                  mail_op);
3515
3516                                 modest_mail_operation_xfer_msgs (mail_op, 
3517                                                                  headers,
3518                                                                  TNY_FOLDER (folder_store),
3519                                                                  TRUE,
3520                                                                  NULL,
3521                                                                  NULL);
3522
3523                                 g_object_unref (G_OBJECT (mail_op));
3524                         }
3525                         g_object_unref (headers);
3526                 }
3527         }
3528         
3529  end:
3530     if (src_folder)
3531         g_object_unref (src_folder);
3532                         
3533         if (folder_store)
3534                 g_object_unref (folder_store);
3535
3536         gtk_widget_destroy (dialog);
3537 }
3538
3539
3540 /*
3541  * UI handler for the "Move to" action when invoked from the
3542  * ModestMsgViewWindow
3543  */
3544 static void 
3545 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
3546                                               ModestMsgViewWindow *win)
3547 {
3548         GtkWidget *dialog, *folder_view, *tree_view = NULL;
3549         gint result = 0;
3550         ModestMainWindow *main_window = NULL;
3551         TnyHeader *header = NULL;
3552         TnyList *headers = NULL;
3553
3554         /* Get the folder view */
3555         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
3556         if (main_window)
3557                 folder_view = modest_main_window_get_child_widget (main_window,
3558                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
3559         else
3560                 folder_view = NULL;
3561
3562         /* Create and run the dialog */
3563         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);  
3564         result = gtk_dialog_run (GTK_DIALOG(dialog));
3565
3566         if (result == GTK_RESPONSE_ACCEPT) {
3567                 TnyFolderStore *folder_store;
3568                 gint response;
3569
3570                 /* Create header list */
3571                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
3572                 g_return_if_fail (header != NULL);
3573
3574                 /* Offer the connection dialog if necessary: */
3575                 /* TODO: What's the extra g_object_ref() for? Isn't this leaking a ref? */
3576                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (g_object_ref (tree_view)));
3577                 TnyFolder *header_folder = tny_header_get_folder(header);
3578                 if (modest_platform_connect_and_wait_if_network_folderstore (NULL, folder_store) &&
3579                     modest_platform_connect_and_wait_if_network_folderstore (NULL, TNY_FOLDER_STORE (header_folder))) {
3580                         
3581                         headers = tny_simple_list_new ();
3582                         tny_list_prepend (headers, G_OBJECT (header));
3583                         g_object_unref (header);
3584
3585                         /* Ask user for confirmation. MSG-NOT404 */
3586                         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
3587                                                       TNY_FOLDER (folder_store), 
3588                                                       headers);
3589
3590                         /* Transfer current msg */
3591                         if (response == GTK_RESPONSE_OK) {
3592                                 ModestMailOperation *mail_op;
3593
3594                                 /* Create mail op */
3595                                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
3596                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3597                                                          mail_op);
3598                         
3599                                 /* Transfer messages */
3600                                 modest_mail_operation_xfer_msgs (mail_op, 
3601                                                          headers,
3602                                                          TNY_FOLDER (folder_store),
3603                                                          TRUE,
3604                                                          transfer_msgs_from_viewer_cb,
3605                                                          NULL);
3606                                 g_object_unref (G_OBJECT (mail_op));
3607                         }
3608                 }
3609                 
3610                 if (header_folder)
3611                         g_object_unref (header_folder);
3612
3613                 if (headers)
3614                         g_object_unref (headers);
3615                         
3616                 if (folder_store)
3617                         g_object_unref (folder_store);
3618         }
3619         
3620         gtk_widget_destroy (dialog);
3621 }
3622
3623 void 
3624 modest_ui_actions_on_move_to (GtkAction *action, 
3625                               ModestWindow *win)
3626 {
3627         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
3628                           MODEST_IS_MSG_VIEW_WINDOW (win));
3629
3630         if (MODEST_IS_MAIN_WINDOW (win)) 
3631                 modest_ui_actions_on_main_window_move_to (action, 
3632                                                           MODEST_MAIN_WINDOW (win));
3633         else
3634                 modest_ui_actions_on_msg_view_window_move_to (action, 
3635                                                               MODEST_MSG_VIEW_WINDOW (win));
3636 }
3637
3638 /*
3639  * Calls #HeadersFunc for each header already selected in the main
3640  * window or the message currently being shown in the msg view window
3641  */
3642 static void
3643 do_headers_action (ModestWindow *win, 
3644                    HeadersFunc func,
3645                    gpointer user_data)
3646 {
3647         TnyList *headers_list;
3648         TnyIterator *iter;
3649         TnyHeader *header;
3650         TnyFolder *folder;
3651
3652         /* Get headers */
3653         headers_list = get_selected_headers (win);
3654         if (!headers_list)
3655                 return;
3656
3657         /* Get the folder */
3658         iter = tny_list_create_iterator (headers_list);
3659         header = TNY_HEADER (tny_iterator_get_current (iter));
3660         folder = tny_header_get_folder (header);
3661         g_object_unref (header);
3662
3663         /* Call the function for each header */
3664         while (!tny_iterator_is_done (iter)) {
3665                 header = TNY_HEADER (tny_iterator_get_current (iter));
3666                 func (header, win, user_data);
3667                 g_object_unref (header);
3668                 tny_iterator_next (iter);
3669         }
3670
3671         /* Trick: do a poke status in order to speed up the signaling
3672            of observers */
3673         tny_folder_poke_status (folder);
3674
3675         /* Frees */
3676         g_object_unref (folder);
3677         g_object_unref (iter);
3678         g_object_unref (headers_list);
3679 }
3680
3681 void 
3682 modest_ui_actions_view_attachment (GtkAction *action,
3683                                    ModestWindow *window)
3684 {
3685         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3686                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
3687         } else {
3688                 /* not supported window for this action */
3689                 g_return_if_reached ();
3690         }
3691 }
3692
3693 void
3694 modest_ui_actions_save_attachments (GtkAction *action,
3695                                     ModestWindow *window)
3696 {
3697         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3698                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
3699         } else {
3700                 /* not supported window for this action */
3701                 g_return_if_reached ();
3702         }
3703 }
3704
3705 void
3706 modest_ui_actions_remove_attachments (GtkAction *action,
3707                                       ModestWindow *window)
3708 {
3709         if (MODEST_IS_MAIN_WINDOW (window)) {
3710                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
3711         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3712                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
3713         } else {
3714                 /* not supported window for this action */
3715                 g_return_if_reached ();
3716         }
3717 }
3718
3719 void 
3720 modest_ui_actions_on_settings (GtkAction *action, 
3721                                ModestWindow *win)
3722 {
3723         GtkWidget *dialog;
3724
3725         dialog = modest_platform_get_global_settings_dialog ();
3726         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
3727         gtk_widget_show_all (dialog);
3728
3729         gtk_dialog_run (GTK_DIALOG (dialog));
3730
3731         gtk_widget_destroy (dialog);
3732 }
3733
3734 void 
3735 modest_ui_actions_on_help (GtkAction *action, 
3736                            ModestWindow *win)
3737 {
3738         const gchar *help_id = NULL;
3739
3740         if (MODEST_IS_MAIN_WINDOW (win)) {
3741                 const gchar *action_name;
3742                 action_name = gtk_action_get_name (action);
3743
3744                 if (!strcmp (action_name, "FolderViewCSMHelp") ||
3745                     !strcmp (action_name, "HeaderViewCSMHelp")) {
3746                         GtkWidget *folder_view;
3747                         TnyFolderStore *folder_store;
3748                         /* Get selected folder */
3749                         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3750                                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
3751                         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3752
3753                         /* Switch help_id */
3754                         if (TNY_IS_FOLDER (folder_store)) {
3755                                 switch (tny_folder_get_folder_type (TNY_FOLDER (folder_store))) {
3756                                 case TNY_FOLDER_TYPE_NORMAL:
3757                                         help_id = "applications_email_userfolder";
3758                                         break;
3759                                 case TNY_FOLDER_TYPE_INBOX:
3760                                         help_id = "applications_email_inbox";
3761                                         break;
3762                                 case TNY_FOLDER_TYPE_OUTBOX:
3763                                         help_id = "applications_email_outbox";
3764                                         break;
3765                                 case TNY_FOLDER_TYPE_SENT:
3766                                         help_id = "applications_email_sent";
3767                                         break;
3768                                 case TNY_FOLDER_TYPE_DRAFTS:
3769                                         help_id = "applications_email_drafts";
3770                                         break;
3771                                 case TNY_FOLDER_TYPE_ARCHIVE:
3772                                         help_id = "applications_email_archive";
3773                                         break;
3774                                 default:
3775                                         help_id = "applications_email_mainview";
3776                                 }
3777                         } else {
3778                                 help_id = "applications_email_mainview";        
3779                         }
3780                         g_object_unref (folder_store);
3781                 } else {
3782                         help_id = "applications_email_mainview";        
3783                 }
3784         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3785                 help_id = "applications_email_viewer";
3786         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
3787                 help_id = "applications_email_editor";
3788
3789         modest_platform_show_help (GTK_WINDOW (win), help_id);
3790 }
3791
3792 void 
3793 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
3794                                             ModestWindow *window)
3795 {
3796         ModestMailOperation *mail_op;
3797         TnyList *headers;
3798
3799         /* Get headers */
3800         headers = get_selected_headers (window);
3801         if (!headers)
3802                 return;
3803
3804         /* Create mail operation */
3805         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3806                                                                  G_OBJECT (window),
3807                                                                  modest_ui_actions_get_msgs_full_error_handler, 
3808                                                                  NULL);
3809         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3810         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
3811
3812         /* Frees */
3813         g_object_unref (headers);
3814         g_object_unref (mail_op);
3815 }
3816
3817 void
3818 modest_ui_actions_on_email_menu_activated (GtkAction *action,
3819                                           ModestWindow *window)
3820 {
3821         g_return_if_fail (MODEST_IS_WINDOW (window));
3822
3823         /* Update dimmed */     
3824         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3825 }
3826
3827 void
3828 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
3829                                           ModestWindow *window)
3830 {
3831         g_return_if_fail (MODEST_IS_WINDOW (window));
3832
3833         /* Update dimmed */     
3834         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3835 }
3836
3837 void
3838 modest_ui_actions_on_view_menu_activated (GtkAction *action,
3839                                           ModestWindow *window)
3840 {
3841         g_return_if_fail (MODEST_IS_WINDOW (window));
3842
3843         /* Update dimmed */     
3844         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3845 }
3846
3847 void
3848 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
3849                                           ModestWindow *window)
3850 {
3851         g_return_if_fail (MODEST_IS_WINDOW (window));
3852
3853         /* Update dimmed */     
3854         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3855 }
3856
3857 void
3858 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
3859                                           ModestWindow *window)
3860 {
3861         g_return_if_fail (MODEST_IS_WINDOW (window));
3862
3863         /* Update dimmed */     
3864         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3865 }
3866
3867 void
3868 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
3869                                                  ModestWindow *window)
3870 {
3871         g_return_if_fail (MODEST_IS_WINDOW (window));
3872
3873         /* Update dimmed */     
3874         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3875 }
3876
3877 void
3878 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
3879                                                      ModestWindow *window)
3880 {
3881         g_return_if_fail (MODEST_IS_WINDOW (window));
3882
3883         /* Update dimmed */     
3884         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3885 }
3886
3887 void
3888 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
3889                                                      ModestWindow *window)
3890 {
3891         g_return_if_fail (MODEST_IS_WINDOW (window));
3892
3893         /* Update dimmed */     
3894         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3895 }
3896
3897 void
3898 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
3899 {
3900         g_return_if_fail (MODEST_IS_WINDOW (window));
3901
3902         /* Update dimmed */     
3903         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
3904 }
3905
3906 void
3907 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
3908 {
3909         g_return_if_fail (MODEST_IS_WINDOW (window));
3910
3911         modest_platform_show_search_messages (GTK_WINDOW (window));
3912 }
3913
3914 void     
3915 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
3916 {
3917         g_return_if_fail (MODEST_IS_WINDOW (win));
3918         modest_platform_show_addressbook (GTK_WINDOW (win));
3919 }
3920
3921
3922 void
3923 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
3924                                           ModestWindow *window)
3925 {
3926         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3927
3928         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
3929 }
3930
3931 static void 
3932 _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
3933                                    ModestMailOperationState *state,
3934                                    gpointer user_data)
3935 {
3936         g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
3937
3938         /* Set send/receive operation finished */       
3939         if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3940                 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));
3941         
3942 }
3943
3944