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