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