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