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