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