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