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