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