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