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