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