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