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