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