* Fixes NB#64200, do not ask for a new connection when trying to open a message...
[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 //                      modest_platform_connect_and_wait ();
1813                 }
1814         }
1815         gtk_widget_destroy (dialog);
1816 }
1817
1818 void
1819 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1820                                      ModestWindow *win)
1821 {
1822         /* g_message ("%s %s", __FUNCTION__, link); */
1823 }       
1824
1825
1826 void
1827 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1828                                         ModestWindow *win)
1829 {
1830         modest_platform_activate_uri (link);
1831 }
1832
1833 void
1834 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1835                                           ModestWindow *win)
1836 {
1837         modest_platform_show_uri_popup (link);
1838 }
1839
1840 void
1841 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1842                                              ModestWindow *win)
1843 {
1844         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
1845 }
1846
1847 void
1848 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1849                                           const gchar *address,
1850                                           ModestWindow *win)
1851 {
1852         /* g_message ("%s %s", __FUNCTION__, address); */
1853 }
1854
1855 void
1856 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1857 {
1858         TnyTransportAccount *transport_account;
1859         ModestMailOperation *mail_operation;
1860         MsgData *data;
1861         gchar *account_name, *from;
1862         ModestAccountMgr *account_mgr;
1863         gchar *info_text = NULL;
1864
1865         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1866         
1867         data = modest_msg_edit_window_get_msg_data (edit_window);
1868
1869         account_mgr = modest_runtime_get_account_mgr();
1870         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1871         if (!account_name) 
1872                 account_name = modest_account_mgr_get_default_account (account_mgr);
1873         if (!account_name) {
1874                 g_printerr ("modest: no account found\n");
1875                 modest_msg_edit_window_free_msg_data (edit_window, data);
1876                 return;
1877         }
1878
1879         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1880                 account_name = g_strdup (data->account_name);
1881         }
1882
1883         transport_account =
1884                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_server_account
1885                                       (modest_runtime_get_account_store(),
1886                                        account_name,
1887                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1888         if (!transport_account) {
1889                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1890                 g_free (account_name);
1891                 modest_msg_edit_window_free_msg_data (edit_window, data);
1892                 return;
1893         }
1894         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1895
1896         /* Create the mail operation */         
1897         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_INFO, G_OBJECT(edit_window));
1898         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1899
1900         modest_mail_operation_save_to_drafts (mail_operation,
1901                                               transport_account,
1902                                               data->draft_msg,
1903                                               edit_window,
1904                                               from,
1905                                               data->to, 
1906                                               data->cc, 
1907                                               data->bcc,
1908                                               data->subject, 
1909                                               data->plain_body, 
1910                                               data->html_body,
1911                                               data->attachments,
1912                                               data->priority_flags);
1913         /* Frees */
1914         g_free (from);
1915         g_free (account_name);
1916         g_object_unref (G_OBJECT (transport_account));
1917         g_object_unref (G_OBJECT (mail_operation));
1918
1919         modest_msg_edit_window_free_msg_data (edit_window, data);
1920
1921         info_text = g_strdup_printf (_("mail_va_saved_to_drafts"), _("mcen_me_folder_drafts"));
1922         modest_platform_information_banner (NULL, NULL, info_text);
1923         g_free (info_text);
1924 }
1925
1926 /* For instance, when clicking the Send toolbar button when editing a message: */
1927 void
1928 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1929 {
1930         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1931
1932         if (!modest_msg_edit_window_check_names (edit_window, TRUE))
1933                 return;
1934         
1935         /* Offer the connection dialog, if necessary: */        
1936         if (!modest_platform_connect_and_wait (GTK_WINDOW (edit_window), NULL))
1937                 return;
1938         
1939         /* FIXME: Code added just for testing. The final version will
1940            use the send queue provided by tinymail and some
1941            classifier */
1942         ModestAccountMgr *account_mgr = modest_runtime_get_account_mgr();
1943         gchar *account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1944         if (!account_name) 
1945                 account_name = modest_account_mgr_get_default_account (account_mgr);
1946                 
1947         if (!account_name) {
1948                 g_printerr ("modest: no account found\n");
1949                 return;
1950         }
1951         
1952         MsgData *data = modest_msg_edit_window_get_msg_data (edit_window);
1953
1954         if (!strcmp (account_name, MODEST_LOCAL_FOLDERS_ACCOUNT_ID)) {
1955                 account_name = g_strdup (data->account_name);
1956         }
1957         
1958         /* Get the currently-active transport account for this modest account: */
1959         TnyTransportAccount *transport_account =
1960                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
1961                                       (modest_runtime_get_account_store(),
1962                                        account_name));
1963         if (!transport_account) {
1964                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1965                 g_free (account_name);
1966                 modest_msg_edit_window_free_msg_data (edit_window, data);
1967                 return;
1968         }
1969         
1970         gchar *from = modest_account_mgr_get_from_string (account_mgr, account_name);
1971
1972         /* mail content checks and dialogs */
1973         if (data->subject == NULL || data->subject[0] == '\0') {
1974                 GtkResponseType response;
1975                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1976                                                                     _("mcen_nc_subject_is_empty_send"));
1977                 if (response == GTK_RESPONSE_CANCEL) {
1978                         g_free (account_name);
1979                         return;
1980                 }
1981         }
1982
1983         if (data->plain_body == NULL || data->plain_body[0] == '\0') {
1984                 GtkResponseType response;
1985                 gchar *note_message;
1986                 gchar *note_subject = data->subject;
1987                 if (note_subject == NULL || note_subject[0] == '\0')
1988                         note_subject = _("mail_va_no_subject");
1989                 note_message = g_strdup_printf (_("emev_ni_ui_smtp_message_null"), note_subject);
1990                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (edit_window),
1991                                                                     note_message);
1992                 g_free (note_message);
1993                 if (response == GTK_RESPONSE_CANCEL) {
1994                         g_free (account_name);
1995                         return;
1996                 }
1997         }
1998
1999         modest_platform_information_banner (NULL, NULL, _("mcen_ib_outbox_waiting_to_be_sent"));
2000
2001         /* Create the mail operation */
2002         ModestMailOperation *mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_SEND, G_OBJECT(edit_window));
2003         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
2004
2005         modest_mail_operation_send_new_mail (mail_operation,
2006                                              transport_account,
2007                                              data->draft_msg,
2008                                              from,
2009                                              data->to, 
2010                                              data->cc, 
2011                                              data->bcc,
2012                                              data->subject, 
2013                                              data->plain_body, 
2014                                              data->html_body,
2015                                              data->attachments,
2016                                              data->priority_flags);
2017                                              
2018         /* Free data: */
2019         g_free (from);
2020         g_free (account_name);
2021         g_object_unref (G_OBJECT (transport_account));
2022         g_object_unref (G_OBJECT (mail_operation));
2023
2024         modest_msg_edit_window_free_msg_data (edit_window, data);
2025         modest_msg_edit_window_set_sent (edit_window, TRUE);
2026
2027         /* Save settings and close the window: */
2028         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW (edit_window));
2029 }
2030
2031 void 
2032 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
2033                                   ModestMsgEditWindow *window)
2034 {
2035         ModestMsgEditFormatState *format_state = NULL;
2036
2037         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2038         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2039
2040         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2041                 return;
2042
2043         format_state = modest_msg_edit_window_get_format_state (window);
2044         g_return_if_fail (format_state != NULL);
2045
2046         format_state->bold = gtk_toggle_action_get_active (action);
2047         modest_msg_edit_window_set_format_state (window, format_state);
2048         g_free (format_state);
2049         
2050 }
2051
2052 void 
2053 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
2054                                      ModestMsgEditWindow *window)
2055 {
2056         ModestMsgEditFormatState *format_state = NULL;
2057
2058         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2059         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2060
2061         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2062                 return;
2063
2064         format_state = modest_msg_edit_window_get_format_state (window);
2065         g_return_if_fail (format_state != NULL);
2066
2067         format_state->italics = gtk_toggle_action_get_active (action);
2068         modest_msg_edit_window_set_format_state (window, format_state);
2069         g_free (format_state);
2070         
2071 }
2072
2073 void 
2074 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
2075                                      ModestMsgEditWindow *window)
2076 {
2077         ModestMsgEditFormatState *format_state = NULL;
2078
2079         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2080         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
2081
2082         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2083                 return;
2084
2085         format_state = modest_msg_edit_window_get_format_state (window);
2086         g_return_if_fail (format_state != NULL);
2087
2088         format_state->bullet = gtk_toggle_action_get_active (action);
2089         modest_msg_edit_window_set_format_state (window, format_state);
2090         g_free (format_state);
2091         
2092 }
2093
2094 void 
2095 modest_ui_actions_on_change_justify (GtkRadioAction *action,
2096                                      GtkRadioAction *selected,
2097                                      ModestMsgEditWindow *window)
2098 {
2099         ModestMsgEditFormatState *format_state = NULL;
2100         GtkJustification value;
2101
2102         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2103
2104         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2105                 return;
2106
2107         value = gtk_radio_action_get_current_value (selected);
2108
2109         format_state = modest_msg_edit_window_get_format_state (window);
2110         g_return_if_fail (format_state != NULL);
2111
2112         format_state->justification = value;
2113         modest_msg_edit_window_set_format_state (window, format_state);
2114         g_free (format_state);
2115 }
2116
2117 void 
2118 modest_ui_actions_on_select_editor_color (GtkAction *action,
2119                                           ModestMsgEditWindow *window)
2120 {
2121         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2122         g_return_if_fail (GTK_IS_ACTION (action));
2123
2124         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2125                 return;
2126
2127         modest_msg_edit_window_select_color (window);
2128 }
2129
2130 void 
2131 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
2132                                                      ModestMsgEditWindow *window)
2133 {
2134         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2135         g_return_if_fail (GTK_IS_ACTION (action));
2136
2137         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2138                 return;
2139
2140         modest_msg_edit_window_select_background_color (window);
2141 }
2142
2143 void 
2144 modest_ui_actions_on_insert_image (GtkAction *action,
2145                                    ModestMsgEditWindow *window)
2146 {
2147         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2148         g_return_if_fail (GTK_IS_ACTION (action));
2149
2150         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
2151                 return;
2152
2153         modest_msg_edit_window_insert_image (window);
2154 }
2155
2156 void 
2157 modest_ui_actions_on_attach_file (GtkAction *action,
2158                                   ModestMsgEditWindow *window)
2159 {
2160         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2161         g_return_if_fail (GTK_IS_ACTION (action));
2162
2163         modest_msg_edit_window_offer_attach_file (window);
2164 }
2165
2166 void 
2167 modest_ui_actions_on_remove_attachments (GtkAction *action,
2168                                          ModestMsgEditWindow *window)
2169 {
2170         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2171         g_return_if_fail (GTK_IS_ACTION (action));
2172
2173         modest_msg_edit_window_remove_attachments (window, NULL);
2174 }
2175
2176 static void
2177 modest_ui_actions_new_folder_error_handler (ModestMailOperation *mail_op,
2178                                             gpointer user_data)
2179 {
2180         ModestMainWindow *window = MODEST_MAIN_WINDOW (user_data);
2181         const GError *error = modest_mail_operation_get_error (mail_op);
2182
2183         if(error)
2184         {
2185                 modest_platform_information_banner (GTK_WIDGET (window), NULL,
2186                                                     modest_mail_operation_get_error (mail_op)->message);
2187         }
2188 }
2189
2190 static void
2191 modest_ui_actions_create_folder(GtkWidget *parent_window,
2192                                 GtkWidget *folder_view)
2193 {
2194         TnyFolderStore *parent_folder;
2195
2196         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2197         
2198         if (parent_folder) {
2199                 gboolean finished = FALSE;
2200                 gint result;
2201                 gchar *folder_name = NULL, *suggested_name = NULL;
2202
2203                 /* Run the new folder dialog */
2204                 while (!finished) {
2205                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (parent_window),
2206                                                                         parent_folder,
2207                                                                         suggested_name,
2208                                                                         &folder_name);
2209
2210                         g_free (suggested_name);
2211                         suggested_name = NULL;
2212
2213                         if (result == GTK_RESPONSE_REJECT) {
2214                                 finished = TRUE;
2215                         } else {
2216                                 ModestMailOperation *mail_op;
2217                                 TnyFolder *new_folder = NULL;
2218
2219                                 mail_op  = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO,
2220                                                                                           G_OBJECT(parent_window),
2221                                                                                           modest_ui_actions_new_folder_error_handler,
2222                                                                                           parent_window);
2223
2224                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2225                                                                  mail_op);
2226                                 new_folder = modest_mail_operation_create_folder (mail_op,
2227                                                                                   parent_folder,
2228                                                                                   (const gchar *) folder_name);
2229                                 if (new_folder) {
2230                                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view), 
2231                                                                           new_folder, TRUE);
2232
2233                                         g_object_unref (new_folder);
2234                                         finished = TRUE;
2235                                 }
2236                                 g_object_unref (mail_op);
2237                         }
2238
2239                         suggested_name = folder_name;
2240                         folder_name = NULL;
2241                 }
2242
2243                 g_object_unref (parent_folder);
2244         }
2245 }
2246
2247 void 
2248 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
2249 {
2250         GtkWidget *folder_view;
2251         
2252         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2253
2254         folder_view = modest_main_window_get_child_widget (main_window,
2255                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2256         if (!folder_view)
2257                 return;
2258
2259         modest_ui_actions_create_folder (GTK_WIDGET (main_window), folder_view);
2260 }
2261
2262 static void
2263 modest_ui_actions_rename_folder_error_handler (ModestMailOperation *mail_op,
2264                                                gpointer user_data)
2265 {
2266         GObject *win = modest_mail_operation_get_source (mail_op);
2267         const GError *error = NULL;
2268         const gchar *message = NULL;
2269         
2270         /* Get error message */
2271         error = modest_mail_operation_get_error (mail_op);
2272         if (error != NULL && error->message != NULL) {
2273                 message = error->message;
2274         } else {
2275                 message = _("!!! FIXME: Unable to rename");
2276         }
2277         
2278         /* Show notification dialog */
2279         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
2280         g_object_unref (win);
2281 }
2282
2283 void 
2284 modest_ui_actions_on_rename_folder (GtkAction *action,
2285                                      ModestMainWindow *main_window)
2286 {
2287         TnyFolderStore *folder;
2288         GtkWidget *folder_view;
2289         GtkWidget *header_view; 
2290
2291         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2292
2293         folder_view = modest_main_window_get_child_widget (main_window,
2294                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2295         if (!folder_view)
2296                 return;
2297
2298         header_view = modest_main_window_get_child_widget (main_window,
2299                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2300         
2301         if (!header_view)
2302                 return;
2303
2304         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
2305         if (!folder)
2306                 return;
2307
2308         /* Offer the connection dialog if necessary: */
2309         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2310                 g_object_unref (G_OBJECT (folder));
2311                 return;
2312         }
2313
2314         
2315         if (TNY_IS_FOLDER (folder)) {
2316                 gchar *folder_name;
2317                 gint response;
2318                 const gchar *current_name;
2319
2320                 current_name = tny_folder_get_name (TNY_FOLDER (folder));
2321                 response = modest_platform_run_rename_folder_dialog (GTK_WINDOW (main_window), NULL,
2322                                                                      current_name, &folder_name);
2323
2324                 if (response == GTK_RESPONSE_ACCEPT && strlen (folder_name) > 0) {
2325                         ModestMailOperation *mail_op;
2326
2327                         mail_op = 
2328                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_INFO, 
2329                                                                                G_OBJECT(main_window),
2330                                                                                modest_ui_actions_rename_folder_error_handler,
2331                                                                                NULL);
2332
2333
2334                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2335                                                          mail_op);
2336
2337                         modest_header_view_clear (MODEST_HEADER_VIEW (header_view));
2338                         
2339                         modest_folder_view_select_folder (MODEST_FOLDER_VIEW(folder_view),
2340                                                           TNY_FOLDER(folder), TRUE);
2341
2342
2343                         modest_header_view_clear ((ModestHeaderView *) header_view);
2344  
2345                         modest_mail_operation_rename_folder (mail_op,
2346                                                              TNY_FOLDER (folder),
2347                                                              (const gchar *) folder_name);
2348
2349                         g_object_unref (mail_op);
2350                         g_free (folder_name);
2351                 }
2352         }
2353         g_object_unref (folder);
2354 }
2355
2356 static void
2357 modest_ui_actions_delete_folder_error_handler (ModestMailOperation *mail_op,
2358                                                gpointer user_data)
2359 {
2360         GObject *win = modest_mail_operation_get_source (mail_op);
2361
2362         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL,
2363                                                 _("mail_in_ui_folder_delete_error"));
2364         g_object_unref (win);
2365 }
2366
2367 static void
2368 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
2369 {
2370         TnyFolderStore *folder;
2371         GtkWidget *folder_view;
2372         gint response;
2373         gchar *message;
2374         
2375         g_return_if_fail (MODEST_IS_MAIN_WINDOW (main_window));
2376
2377         folder_view = modest_main_window_get_child_widget (main_window,
2378                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2379         if (!folder_view)
2380                 return;
2381
2382         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2383
2384         /* Show an error if it's an account */
2385         if (!TNY_IS_FOLDER (folder)) {
2386                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
2387                                                         _("mail_in_ui_folder_delete_error"));
2388                 g_object_unref (G_OBJECT (folder));
2389                 return ;
2390         }
2391
2392         /* Offer the connection dialog if necessary: */
2393         if (!modest_platform_connect_and_wait_if_network_folderstore (NULL, folder)) {
2394                 g_object_unref (G_OBJECT (folder));
2395                 return;
2396         }
2397
2398         /* Ask the user */      
2399         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
2400                                     tny_folder_get_name (TNY_FOLDER (folder)));
2401         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window),
2402                                                             (const gchar *) message);
2403         g_free (message);
2404
2405         if (response == GTK_RESPONSE_OK) {
2406                 ModestMailOperation *mail_op = 
2407                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_DELETE, 
2408                                                                        G_OBJECT(main_window),
2409                                                                        modest_ui_actions_delete_folder_error_handler,
2410                                                                        NULL);
2411
2412                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
2413                                                  mail_op);
2414                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
2415                 g_object_unref (G_OBJECT (mail_op));
2416         }
2417
2418         g_object_unref (G_OBJECT (folder));
2419 }
2420
2421 void 
2422 modest_ui_actions_on_delete_folder (GtkAction *action,
2423                                      ModestMainWindow *main_window)
2424 {
2425         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2426
2427         delete_folder (main_window, FALSE);
2428 }
2429
2430 void 
2431 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
2432 {
2433         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2434         
2435         delete_folder (main_window, TRUE);
2436 }
2437
2438
2439 static void
2440 show_error (GtkWidget *parent_widget, const gchar* text)
2441 {
2442         hildon_banner_show_information(parent_widget, NULL, text);
2443         
2444 #if 0
2445         GtkDialog *dialog = GTK_DIALOG (hildon_note_new_information (parent_window, text)); */
2446         /*
2447           GtkDialog *dialog = GTK_DIALOG (gtk_message_dialog_new (parent_window,
2448           (GtkDialogFlags)0,
2449           GTK_MESSAGE_ERROR,
2450           GTK_BUTTONS_OK,
2451           text ));
2452         */
2453                  
2454         gtk_dialog_run (dialog);
2455         gtk_widget_destroy (GTK_WIDGET (dialog));
2456 #endif
2457 }
2458
2459 void
2460 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
2461                                          const gchar* server_account_name,
2462                                          gchar **username,
2463                                          gchar **password, 
2464                                          gboolean *cancel, 
2465                                          gboolean *remember,
2466                                          ModestMainWindow *main_window)
2467 {
2468         g_return_if_fail(server_account_name);
2469         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
2470         
2471         /* Initalize output parameters: */
2472         if (cancel)
2473                 *cancel = FALSE;
2474                 
2475         if (remember)
2476                 *remember = TRUE;
2477                 
2478 #ifdef MODEST_PLATFORM_MAEMO
2479         /* Maemo uses a different (awkward) button order,
2480          * It should probably just use gtk_alternative_dialog_button_order ().
2481          */
2482         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2483                                               NULL,
2484                                               GTK_DIALOG_MODAL,
2485                                               GTK_STOCK_OK,
2486                                               GTK_RESPONSE_ACCEPT,
2487                                               GTK_STOCK_CANCEL,
2488                                               GTK_RESPONSE_REJECT,
2489                                               NULL);
2490 #else
2491         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
2492                                               NULL,
2493                                               GTK_DIALOG_MODAL,
2494                                               GTK_STOCK_CANCEL,
2495                                               GTK_RESPONSE_REJECT,
2496                                               GTK_STOCK_OK,
2497                                               GTK_RESPONSE_ACCEPT,
2498                                               NULL);
2499 #endif /* MODEST_PLATFORM_MAEMO */
2500
2501         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
2502         
2503         gchar *server_name = modest_server_account_get_hostname (
2504                 modest_runtime_get_account_mgr(), server_account_name);
2505         if (!server_name) {/* This happened once, though I don't know why. murrayc. */
2506                 g_warning("%s: Could not get server name for server account '%s'", __FUNCTION__, server_account_name);
2507                 *cancel = TRUE;
2508                 return;
2509         }
2510         
2511         /* This causes a warning because the logical ID has no %s in it, 
2512          * though the translation does, but there is not much we can do about that: */
2513         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
2514         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
2515                             FALSE, FALSE, 0);
2516         g_free (txt);
2517         g_free (server_name);
2518         server_name = NULL;
2519
2520         /* username: */
2521         gchar *initial_username = modest_server_account_get_username (
2522                 modest_runtime_get_account_mgr(), server_account_name);
2523         
2524         GtkWidget *entry_username = gtk_entry_new ();
2525         if (initial_username)
2526                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
2527         /* Dim this if a connection has ever succeeded with this username,
2528          * as per the UI spec: */
2529         const gboolean username_known = 
2530                 modest_server_account_get_username_has_succeeded(
2531                         modest_runtime_get_account_mgr(), server_account_name);
2532         gtk_widget_set_sensitive (entry_username, !username_known);
2533         
2534 #ifdef MODEST_PLATFORM_MAEMO
2535         /* Auto-capitalization is the default, so let's turn it off: */
2536         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
2537         
2538         /* Create a size group to be used by all captions.
2539          * Note that HildonCaption does not create a default size group if we do not specify one.
2540          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
2541         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
2542         
2543         GtkWidget *caption = hildon_caption_new (sizegroup, 
2544                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
2545         gtk_widget_show (entry_username);
2546         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2547                 FALSE, FALSE, MODEST_MARGIN_HALF);
2548         gtk_widget_show (caption);
2549 #else 
2550         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
2551                             TRUE, FALSE, 0);
2552 #endif /* MODEST_PLATFORM_MAEMO */      
2553                             
2554         /* password: */
2555         GtkWidget *entry_password = gtk_entry_new ();
2556         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
2557         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
2558         
2559 #ifdef MODEST_PLATFORM_MAEMO
2560         /* Auto-capitalization is the default, so let's turn it off: */
2561         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
2562                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
2563         
2564         caption = hildon_caption_new (sizegroup, 
2565                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
2566         gtk_widget_show (entry_password);
2567         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
2568                 FALSE, FALSE, MODEST_MARGIN_HALF);
2569         gtk_widget_show (caption);
2570         g_object_unref (sizegroup);
2571 #else 
2572         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
2573                             TRUE, FALSE, 0);
2574 #endif /* MODEST_PLATFORM_MAEMO */      
2575                                 
2576 /* This is not in the Maemo UI spec:
2577         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
2578         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
2579                             TRUE, FALSE, 0);
2580 */
2581
2582         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2583         
2584         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
2585                 if (username) {
2586                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
2587                         
2588                         modest_server_account_set_username (
2589                                  modest_runtime_get_account_mgr(), server_account_name, 
2590                                  *username);
2591                                  
2592                         const gboolean username_was_changed = 
2593                                 (strcmp (*username, initial_username) != 0);
2594                         if (username_was_changed) {
2595                                 g_warning ("%s: tinymail does not yet support changing the "
2596                                         "username in the get_password() callback.\n", __FUNCTION__);
2597                         }
2598                 }
2599                         
2600                 if (password) {
2601                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
2602                         
2603                         /* We do not save the password in the configuration, 
2604                          * because this function is only called for passwords that should 
2605                          * not be remembered:
2606                         modest_server_account_set_password (
2607                                  modest_runtime_get_account_mgr(), server_account_name, 
2608                                  *password);
2609                         */
2610                 }
2611                 
2612                 if (cancel)
2613                         *cancel   = FALSE;
2614                         
2615         } else {
2616                 show_error(GTK_WIDGET (main_window), _("mail_ib_login_cancelled"));
2617                 
2618                 if (username)
2619                         *username = NULL;
2620                         
2621                 if (password)
2622                         *password = NULL;
2623                         
2624                 if (cancel)
2625                         *cancel   = TRUE;
2626         }
2627
2628 /* This is not in the Maemo UI spec:
2629         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
2630                 *remember = TRUE;
2631         else
2632                 *remember = FALSE;
2633 */
2634
2635         gtk_widget_destroy (dialog);
2636         
2637         /* printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel); */
2638 }
2639
2640 void
2641 modest_ui_actions_on_cut (GtkAction *action,
2642                           ModestWindow *window)
2643 {
2644         GtkWidget *focused_widget;
2645
2646         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2647         if (GTK_IS_EDITABLE (focused_widget)) {
2648                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
2649         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2650                 GtkTextBuffer *buffer;
2651                 GtkClipboard *clipboard;
2652
2653                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2654                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2655                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
2656                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2657         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2658                 modest_header_view_cut_selection (MODEST_HEADER_VIEW (focused_widget));
2659         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2660                 modest_folder_view_cut_selection (MODEST_FOLDER_VIEW (focused_widget));
2661         }
2662 }
2663
2664 void
2665 modest_ui_actions_on_copy (GtkAction *action,
2666                            ModestWindow *window)
2667 {
2668         GtkClipboard *clipboard;
2669         GtkWidget *focused_widget;
2670
2671         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2672         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2673
2674         if (GTK_IS_LABEL (focused_widget)) {
2675                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
2676         } else if (GTK_IS_EDITABLE (focused_widget)) {
2677                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
2678         } else if (GTK_IS_HTML (focused_widget)) {
2679                 gtk_html_copy (GTK_HTML (focused_widget));
2680         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2681                 GtkTextBuffer *buffer;
2682                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2683                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2684                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2685         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2686                 TnyList *header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (focused_widget));
2687                 TnyIterator *iter = tny_list_create_iterator (header_list);
2688                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2689                 
2690                 gboolean ask = FALSE;
2691                 if (header) {
2692                         TnyFolder *folder = tny_header_get_folder (header);
2693                         TnyAccount *account = tny_folder_get_account (folder);
2694                         const gchar *proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2695                         /* If it's POP then ask */
2696                         ask = (modest_protocol_info_get_transport_store_protocol (proto_str) == 
2697                                 MODEST_PROTOCOL_STORE_POP) ? TRUE : FALSE;
2698                         g_object_unref (account);
2699                         g_object_unref (folder);
2700                         g_object_unref (header);
2701                 }
2702
2703                 g_object_unref (iter);
2704                 
2705                 /* Check that the messages have been previously downloaded */
2706                 gboolean continue_download = TRUE;
2707                 if (ask)
2708                         continue_download = download_uncached_messages (header_list, GTK_WINDOW (window), FALSE);
2709                 if (continue_download)
2710                         modest_header_view_copy_selection (MODEST_HEADER_VIEW (focused_widget));
2711                 g_object_unref (header_list);
2712         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2713                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
2714         }    
2715
2716         /* Show information banner */
2717         modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
2718         
2719 }
2720
2721 void
2722 modest_ui_actions_on_undo (GtkAction *action,
2723                            ModestWindow *window)
2724 {
2725         ModestEmailClipboard *clipboard = NULL;
2726
2727         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2728                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2729         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2730                 /* Clear clipboard source */
2731                 clipboard = modest_runtime_get_email_clipboard ();
2732                 modest_email_clipboard_clear (clipboard);               
2733         }
2734         else {
2735                 g_return_if_reached ();
2736         }
2737 }
2738
2739 void
2740 modest_ui_actions_on_redo (GtkAction *action,
2741                            ModestWindow *window)
2742 {
2743         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2744                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
2745         }
2746         else {
2747                 g_return_if_reached ();
2748         }
2749 }
2750
2751
2752 static void
2753 paste_msgs_cb (const GObject *object, gpointer user_data)
2754 {
2755         g_return_if_fail (MODEST_IS_MAIN_WINDOW (object));
2756         g_return_if_fail (GTK_IS_WIDGET (user_data));
2757         
2758         /* destroy information note */
2759         gtk_widget_destroy (GTK_WIDGET(user_data));
2760 }
2761
2762 static void
2763 paste_as_attachment_free (gpointer data)
2764 {
2765         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) data;
2766
2767         gtk_widget_destroy (helper->banner);
2768         g_object_unref (helper->banner);
2769         g_free (helper);
2770 }
2771
2772 static void
2773 paste_msg_as_attachment_cb (ModestMailOperation *mail_op,
2774                             TnyHeader *header,
2775                             TnyMsg *msg,
2776                             gpointer userdata)
2777 {
2778         PasteAsAttachmentHelper *helper = (PasteAsAttachmentHelper *) userdata;
2779         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (helper->window));
2780
2781         if (msg == NULL)
2782                 return;
2783
2784         modest_msg_edit_window_add_part (MODEST_MSG_EDIT_WINDOW (helper->window), TNY_MIME_PART (msg));
2785         
2786 }
2787
2788 void
2789 modest_ui_actions_on_paste (GtkAction *action,
2790                             ModestWindow *window)
2791 {
2792         GtkWidget *focused_widget = NULL;
2793         GtkWidget *inf_note = NULL;
2794         ModestMailOperation *mail_op = NULL;
2795
2796         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2797         if (GTK_IS_EDITABLE (focused_widget)) {
2798                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
2799         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2800                 ModestEmailClipboard *e_clipboard = NULL;
2801                 e_clipboard = modest_runtime_get_email_clipboard ();
2802                 if (modest_email_clipboard_cleared (e_clipboard)) {
2803                         GtkTextBuffer *buffer;
2804                         GtkClipboard *clipboard;
2805
2806                         clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2807                         buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2808                         gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
2809                 } else if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2810                         ModestMailOperation *mail_op;
2811                         TnyFolder *src_folder;
2812                         TnyList *data;
2813                         gboolean delete;
2814                         PasteAsAttachmentHelper *helper = g_new0 (PasteAsAttachmentHelper, 1);
2815                         helper->window = MODEST_MSG_EDIT_WINDOW (window);
2816                         helper->banner = modest_platform_animation_banner (GTK_WIDGET (window), NULL,
2817                                                                            _CS("ckct_nw_pasting"));
2818                         modest_email_clipboard_get_data (e_clipboard, &src_folder, &data, &delete);
2819                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
2820                                                              G_OBJECT (window));
2821                         if (helper->banner != NULL) {
2822                                 g_object_ref (G_OBJECT (helper->banner));
2823                                 gtk_window_set_modal (GTK_WINDOW (helper->banner), FALSE);
2824                                 gtk_widget_show (GTK_WIDGET (helper->banner));
2825                         }
2826
2827                         if (data != NULL) {
2828                                 modest_mail_operation_get_msgs_full (mail_op, 
2829                                                                      data,
2830                                                                      (GetMsgAsyncUserCallback) paste_msg_as_attachment_cb,
2831                                                                      helper,
2832                                                                      paste_as_attachment_free);
2833                         }
2834                 }
2835         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2836                 ModestEmailClipboard *clipboard = NULL;
2837                 TnyFolder *src_folder = NULL;
2838                 TnyFolderStore *folder_store = NULL;
2839                 TnyList *data = NULL;           
2840                 gboolean delete = FALSE;
2841                 
2842                 /* Check clipboard source */
2843                 clipboard = modest_runtime_get_email_clipboard ();
2844                 if (modest_email_clipboard_cleared (clipboard)) 
2845                         return;
2846                 
2847                 /* Get elements to paste */
2848                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
2849
2850                 /* Create a new mail operation */
2851                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
2852                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2853                                                  mail_op);
2854                 
2855                 /* Get destination folder */
2856                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
2857
2858                 /* Launch notification */
2859                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
2860                                                              _CS("ckct_nw_pasting"));
2861                 if (inf_note != NULL)  {
2862                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
2863                         gtk_widget_show (GTK_WIDGET(inf_note));
2864                 }
2865
2866                 /* transfer messages  */
2867                 if (data != NULL) {
2868                         modest_mail_operation_xfer_msgs (mail_op, 
2869                                                          data,
2870                                                          TNY_FOLDER (folder_store),
2871                                                          delete,
2872                                                          paste_msgs_cb,
2873                                                          inf_note);
2874                         
2875                 } else if (src_folder != NULL) {                        
2876                         modest_mail_operation_xfer_folder (mail_op, 
2877                                                            src_folder,
2878                                                            folder_store,
2879                                                            delete,
2880                                                            paste_msgs_cb,
2881                                                            inf_note);
2882                 }
2883
2884                 /* Free */
2885                 if (data != NULL) 
2886                         g_object_unref (data);
2887                 if (src_folder != NULL) 
2888                         g_object_unref (src_folder);
2889                 if (folder_store != NULL) 
2890                         g_object_unref (folder_store);
2891         }
2892 }
2893
2894
2895 void
2896 modest_ui_actions_on_select_all (GtkAction *action,
2897                                  ModestWindow *window)
2898 {
2899         GtkWidget *focused_widget;
2900
2901         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2902         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
2903                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
2904         } else if (GTK_IS_LABEL (focused_widget)) {
2905                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
2906         } else if (GTK_IS_EDITABLE (focused_widget)) {
2907                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
2908         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2909                 GtkTextBuffer *buffer;
2910                 GtkTextIter start, end;
2911
2912                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2913                 gtk_text_buffer_get_start_iter (buffer, &start);
2914                 gtk_text_buffer_get_end_iter (buffer, &end);
2915                 gtk_text_buffer_select_range (buffer, &start, &end);
2916         } else if (GTK_IS_HTML (focused_widget)) {
2917                 gtk_html_select_all (GTK_HTML (focused_widget));
2918         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2919                 GtkWidget *header_view = focused_widget;
2920                 GtkTreeSelection *selection = NULL;
2921                 
2922                 if (!(MODEST_IS_HEADER_VIEW (focused_widget)))
2923                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
2924                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2925                                 
2926                 /* Select all messages */
2927                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
2928                 gtk_tree_selection_select_all (selection);
2929
2930                 /* Set focuse on header view */
2931                 gtk_widget_grab_focus (header_view);
2932         }
2933
2934 }
2935
2936 void
2937 modest_ui_actions_on_mark_as_read (GtkAction *action,
2938                                    ModestWindow *window)
2939 {       
2940         g_return_if_fail (MODEST_IS_WINDOW(window));
2941                 
2942         /* Mark each header as read */
2943         do_headers_action (window, headers_action_mark_as_read, NULL);
2944 }
2945
2946 void
2947 modest_ui_actions_on_mark_as_unread (GtkAction *action,
2948                                      ModestWindow *window)
2949 {       
2950         g_return_if_fail (MODEST_IS_WINDOW(window));
2951                 
2952         /* Mark each header as read */
2953         do_headers_action (window, headers_action_mark_as_unread, NULL);
2954 }
2955
2956 void
2957 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
2958                                   GtkRadioAction *selected,
2959                                   ModestWindow *window)
2960 {
2961         gint value;
2962
2963         value = gtk_radio_action_get_current_value (selected);
2964         if (MODEST_IS_WINDOW (window)) {
2965                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
2966         }
2967 }
2968
2969 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
2970                                                         GtkRadioAction *selected,
2971                                                         ModestWindow *window)
2972 {
2973         TnyHeaderFlags flags;
2974         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2975
2976         flags = gtk_radio_action_get_current_value (selected);
2977         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
2978 }
2979
2980 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
2981                                                            GtkRadioAction *selected,
2982                                                            ModestWindow *window)
2983 {
2984         gint file_format;
2985
2986         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2987
2988         file_format = gtk_radio_action_get_current_value (selected);
2989         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
2990 }
2991
2992
2993 void     
2994 modest_ui_actions_on_zoom_plus (GtkAction *action,
2995                                 ModestWindow *window)
2996 {
2997         g_return_if_fail (MODEST_IS_WINDOW (window));
2998
2999         modest_window_zoom_plus (MODEST_WINDOW (window));
3000 }
3001
3002 void     
3003 modest_ui_actions_on_zoom_minus (GtkAction *action,
3004                                  ModestWindow *window)
3005 {
3006         g_return_if_fail (MODEST_IS_WINDOW (window));
3007
3008         modest_window_zoom_minus (MODEST_WINDOW (window));
3009 }
3010
3011 void     
3012 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
3013                                            ModestWindow *window)
3014 {
3015         ModestWindowMgr *mgr;
3016         gboolean fullscreen, active;
3017         g_return_if_fail (MODEST_IS_WINDOW (window));
3018
3019         mgr = modest_runtime_get_window_mgr ();
3020
3021         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
3022         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3023
3024         if (active != fullscreen) {
3025                 modest_window_mgr_set_fullscreen_mode (mgr, active);
3026                 gtk_window_present (GTK_WINDOW (window));
3027         }
3028 }
3029
3030 void
3031 modest_ui_actions_on_change_fullscreen (GtkAction *action,
3032                                         ModestWindow *window)
3033 {
3034         ModestWindowMgr *mgr;
3035         gboolean fullscreen;
3036
3037         g_return_if_fail (MODEST_IS_WINDOW (window));
3038
3039         mgr = modest_runtime_get_window_mgr ();
3040         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
3041         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
3042
3043         gtk_window_present (GTK_WINDOW (window));
3044 }
3045
3046 /* 
3047  * Used by modest_ui_actions_on_details to call do_headers_action 
3048  */
3049 static void
3050 headers_action_show_details (TnyHeader *header, 
3051                              ModestWindow *window,
3052                              gpointer user_data)
3053
3054 {
3055         GtkWidget *dialog;
3056         
3057         /* Create dialog */
3058         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
3059
3060         /* Run dialog */
3061         gtk_widget_show_all (dialog);
3062         gtk_dialog_run (GTK_DIALOG (dialog));
3063
3064         gtk_widget_destroy (dialog);
3065 }
3066
3067 /*
3068  * Show the folder details in a ModestDetailsDialog widget
3069  */
3070 static void
3071 show_folder_details (TnyFolder *folder, 
3072                      GtkWindow *window)
3073 {
3074         GtkWidget *dialog;
3075         
3076         /* Create dialog */
3077         dialog = modest_details_dialog_new_with_folder (window, folder);
3078
3079         /* Run dialog */
3080         gtk_widget_show_all (dialog);
3081         gtk_dialog_run (GTK_DIALOG (dialog));
3082
3083         gtk_widget_destroy (dialog);
3084 }
3085
3086 /*
3087  * Show the header details in a ModestDetailsDialog widget
3088  */
3089 void     
3090 modest_ui_actions_on_details (GtkAction *action, 
3091                               ModestWindow *win)
3092 {
3093         TnyList * headers_list;
3094         TnyIterator *iter;
3095         TnyHeader *header;              
3096
3097         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3098                 TnyMsg *msg;
3099
3100                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
3101                 if (!msg)
3102                         return;
3103                 g_object_unref (msg);           
3104
3105                 headers_list = get_selected_headers (win);
3106                 if (!headers_list)
3107                         return;
3108
3109                 iter = tny_list_create_iterator (headers_list);
3110
3111                 header = TNY_HEADER (tny_iterator_get_current (iter));
3112                 if (header) {
3113                         headers_action_show_details (header, win, NULL);
3114                         g_object_unref (header);
3115                 }
3116
3117                 g_object_unref (iter);
3118                 g_object_unref (headers_list);
3119
3120         } else if (MODEST_IS_MAIN_WINDOW (win)) {
3121                 GtkWidget *folder_view, *header_view;
3122
3123                 /* Check which widget has the focus */
3124                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3125                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
3126                 if (gtk_widget_is_focus (folder_view)) {
3127                         TnyFolderStore *folder_store
3128                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3129                         if (!folder_store) {
3130                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
3131                                 return; 
3132                         }
3133                         /* Show only when it's a folder */
3134                         /* This function should not be called for account items, 
3135                          * because we dim the menu item for them. */
3136                         if (TNY_IS_FOLDER (folder_store)) {
3137                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
3138                         }
3139
3140                         g_object_unref (folder_store);
3141
3142                 } else {
3143                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3144                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3145                         /* Show details of each header */
3146                         do_headers_action (win, headers_action_show_details, header_view);
3147                 }
3148         }
3149 }
3150
3151 void     
3152 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
3153                                      ModestMsgEditWindow *window)
3154 {
3155         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3156
3157         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3158 }
3159
3160 void     
3161 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3162                                       ModestMsgEditWindow *window)
3163 {
3164         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3165
3166         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3167 }
3168
3169 void
3170 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3171                                        ModestMainWindow *main_window)
3172 {
3173         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3174
3175         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
3176                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3177         else
3178                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3179 }
3180
3181 void 
3182 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3183                                      ModestWindow *window)
3184 {
3185         gboolean active, fullscreen = FALSE;
3186         ModestWindowMgr *mgr;
3187
3188         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3189
3190         /* Check if we want to toggle the toolbar vuew in fullscreen
3191            or normal mode */
3192         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3193                      "ViewShowToolbarFullScreen")) {
3194                 fullscreen = TRUE;
3195         }
3196
3197         /* Toggle toolbar */
3198         mgr = modest_runtime_get_window_mgr ();
3199         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
3200 }
3201
3202 void     
3203 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3204                                            ModestMsgEditWindow *window)
3205 {
3206         modest_msg_edit_window_select_font (window);
3207 }
3208
3209 void
3210 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3211                                                   const gchar *display_name,
3212                                                   GtkWindow *window)
3213 {
3214         /* Do not change the application name if the widget has not
3215            the focus. This callback could be called even if the folder
3216            view has not the focus, because the handled signal could be
3217            emitted when the folder view is redrawn */
3218         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3219                 if (display_name)
3220                         gtk_window_set_title (window, display_name);
3221                 else
3222                         gtk_window_set_title (window, " ");
3223         }
3224 }
3225
3226 void
3227 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3228 {
3229         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3230         modest_msg_edit_window_select_contacts (window);
3231 }
3232
3233 void
3234 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3235 {
3236         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3237         modest_msg_edit_window_check_names (window, FALSE);
3238 }
3239
3240 static void
3241 create_move_to_dialog_on_new_folder(GtkWidget *button, gpointer user_data)
3242 {
3243         modest_ui_actions_create_folder (gtk_widget_get_toplevel (button),
3244                                          GTK_WIDGET (user_data));
3245 }
3246
3247 static GtkWidget*
3248 create_move_to_dialog (GtkWindow *win,
3249                        GtkWidget *folder_view,
3250                        GtkWidget **tree_view)
3251 {
3252         GtkWidget *dialog, *scroll;
3253         GtkWidget *new_button;
3254
3255         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3256                                               GTK_WINDOW (win),
3257                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3258                                               NULL);
3259
3260         gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
3261         /* We do this manually so GTK+ does not associate a response ID for
3262          * the button. */
3263         new_button = gtk_button_new_from_stock (GTK_STOCK_NEW);
3264         gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->action_area), new_button, FALSE, FALSE, 0);
3265         gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
3266
3267         /* Create scrolled window */
3268         scroll = gtk_scrolled_window_new (NULL, NULL);
3269         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3270                                          GTK_POLICY_AUTOMATIC,
3271                                          GTK_POLICY_AUTOMATIC);
3272
3273         /* Create folder view */
3274         *tree_view = modest_platform_create_folder_view (NULL);
3275
3276         g_signal_connect (G_OBJECT (new_button), "clicked", G_CALLBACK(create_move_to_dialog_on_new_folder), *tree_view);
3277
3278         /* It could happen that we're trying to move a message from a
3279            window (msg window for example) after the main window was
3280            closed, so we can not just get the model of the folder
3281            view */
3282         if (MODEST_IS_FOLDER_VIEW (folder_view))
3283                 gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
3284                                          gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
3285         else
3286                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
3287                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3288
3289         modest_folder_view_show_non_move_folders (MODEST_FOLDER_VIEW (*tree_view), FALSE);
3290         
3291         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3292
3293         /* Add scroll to dialog */
3294         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
3295                             scroll, TRUE, TRUE, 0);
3296
3297         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3298         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 300);
3299
3300         return dialog;
3301 }
3302
3303 /*
3304  * Returns TRUE if at least one of the headers of the list belongs to
3305  * a message that has been fully retrieved.
3306  */
3307 static gboolean
3308 has_retrieved_msgs (TnyList *list)
3309 {
3310         TnyIterator *iter;
3311         gboolean found = FALSE;
3312
3313         iter = tny_list_create_iterator (list);
3314         while (tny_iterator_is_done (iter) && !found) {
3315                 TnyHeader *header;
3316                 TnyHeaderFlags flags = 0;
3317
3318                 header = TNY_HEADER (tny_iterator_get_current (iter));
3319                 if (header) {
3320                         flags = tny_header_get_flags (header);
3321                         if (!(flags & TNY_HEADER_FLAG_PARTIAL))
3322                                 found = TRUE;
3323
3324                         g_object_unref (header);
3325                 }
3326
3327                 if (!found)
3328                         tny_iterator_next (iter);
3329         }
3330         g_object_unref (iter);
3331
3332         return found;
3333 }
3334
3335 /*
3336  * Shows a confirmation dialog to the user when we're moving messages
3337  * from a remote server to the local storage. Returns the dialog
3338  * response. If it's other kind of movement the it always returns
3339  * GTK_RESPONSE_OK
3340  */
3341 static gint
3342 msgs_move_to_confirmation (GtkWindow *win,
3343                            TnyFolder *dest_folder,
3344                            TnyList *headers)
3345 {
3346         gint response = GTK_RESPONSE_OK;
3347
3348         /* If the destination is a local folder */
3349         if (modest_tny_folder_is_local_folder (dest_folder)) {
3350                 TnyFolder *src_folder = NULL;
3351                 TnyIterator *iter = NULL;
3352                 TnyHeader *header = NULL;
3353
3354                 /* Get source folder */
3355                 iter = tny_list_create_iterator (headers);
3356                 header = TNY_HEADER (tny_iterator_get_current (iter));
3357                 if (header) {
3358                         src_folder = tny_header_get_folder (header);
3359                         g_object_unref (header);
3360                 }
3361
3362                 g_object_unref (iter);
3363
3364                 /* if no src_folder, message may be an attahcment */
3365                 if (src_folder == NULL) 
3366                         return GTK_RESPONSE_CANCEL;
3367
3368                 /* If the source is a remote folder */
3369                 if (!modest_tny_folder_is_local_folder (src_folder)) {
3370                         const gchar *message;
3371                         
3372                         if (has_retrieved_msgs (headers))
3373                                 message = ngettext ("mcen_nc_move_retrieve", "mcen_nc_move_retrieves",
3374                                                     tny_list_get_length (headers));
3375                         else 
3376                                 message = ngettext ("mcen_nc_move_header", "mcen_nc_move_headers",
3377                                                     tny_list_get_length (headers));
3378
3379                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
3380                                                                             (const gchar *) message);
3381                 }
3382                 
3383                 g_object_unref (src_folder);
3384         }
3385         
3386         return response;
3387 }
3388
3389
3390
3391 static void
3392 transfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
3393 {
3394         ModestMsgViewWindow *self = NULL;
3395
3396         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
3397         self = MODEST_MSG_VIEW_WINDOW (object);
3398         
3399         if (!modest_msg_view_window_select_next_message (self))
3400                 if (!modest_msg_view_window_select_previous_message (self))
3401                         /* No more messages to view, so close this window */
3402                         modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
3403 }
3404
3405 void
3406 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
3407                                              gpointer user_data)
3408 {
3409         GObject *win = modest_mail_operation_get_source (mail_op);
3410         const GError *error = NULL;
3411         const gchar *message = NULL;
3412         
3413         /* Get error message */
3414         error = modest_mail_operation_get_error (mail_op);
3415         if (error != NULL && error->message != NULL) {
3416                 message = error->message;
3417         } else {
3418                 message = _("mail_in_ui_folder_move_target_error");
3419         }
3420         
3421         /* Show notification dialog */
3422         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
3423         g_object_unref (win);
3424 }
3425
3426 void
3427 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
3428                                               gpointer user_data)
3429 {
3430         GObject *win = modest_mail_operation_get_source (mail_op);
3431         const GError *error = modest_mail_operation_get_error (mail_op);
3432
3433         g_return_if_fail (error != NULL);
3434         if (error->message != NULL)             
3435                 g_printerr ("modest: %s\n", error->message);
3436         else
3437                 g_printerr ("modest: unkonw error on send&receive operation");
3438
3439         /* Show error message */
3440 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
3441 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3442 /*                                                      _CS("sfil_ib_unable_to_receive")); */
3443 /*      else  */
3444 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3445 /*                                                      _CS("sfil_ib_unable_to_send")); */
3446         g_object_unref (win);
3447 }
3448
3449 static void
3450 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
3451                        TnyHeader *header, 
3452                        TnyMsg *msg, 
3453                        gpointer user_data)
3454 {
3455         TnyList *parts;
3456         TnyIterator *iter;
3457         gint pending_purges = 0;
3458         gboolean some_purged = FALSE;
3459         ModestWindow *win = MODEST_WINDOW (user_data);
3460         ModestWindowMgr *mgr = modest_runtime_get_window_mgr ();
3461
3462         /* If there was any error */
3463         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg)) {
3464                 modest_window_mgr_unregister_header (mgr, header);
3465                 return;
3466         }
3467
3468         /* Once the message has been retrieved for purging, we check if
3469          * it's all ok for purging */
3470
3471         parts = tny_simple_list_new ();
3472         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
3473         iter = tny_list_create_iterator (parts);
3474
3475         while (!tny_iterator_is_done (iter)) {
3476                 TnyMimePart *part;
3477                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3478                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))) {
3479                         if (tny_mime_part_is_purged (part))
3480                                 some_purged = TRUE;
3481                         else
3482                                 pending_purges++;
3483                 }
3484
3485                 if (part)
3486                         g_object_unref (part);
3487
3488                 tny_iterator_next (iter);
3489         }
3490
3491         if (pending_purges>0) {
3492                 gint response;
3493                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
3494
3495                 if (response == GTK_RESPONSE_OK) {
3496                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
3497                         tny_iterator_first (iter);
3498                         while (!tny_iterator_is_done (iter)) {
3499                                 TnyMimePart *part;
3500                                 
3501                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3502                                 if (part && (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)))
3503                                         tny_mime_part_set_purged (part);
3504
3505                                 if (part)
3506                                         g_object_unref (part);
3507
3508                                 tny_iterator_next (iter);
3509                         }
3510                         
3511                         tny_msg_rewrite_cache (msg);
3512                 }
3513         } else {
3514                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
3515         }
3516
3517         /* remove attachments */
3518         tny_iterator_first (iter);
3519         while (!tny_iterator_is_done (iter)) {
3520                 TnyMimePart *part;
3521                         
3522                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3523                 if (part) {
3524                         /* One for the reference given by tny_iterator_get_current(): */
3525                         g_object_unref (part);
3526
3527                         /* TODO: Is this meant to remove the attachment by doing another unref()? 
3528                          * Otherwise, this seems useless. */
3529                 }
3530
3531                 tny_iterator_next (iter);
3532         }
3533         modest_window_mgr_unregister_header (mgr, header);
3534
3535         g_object_unref (iter);
3536         g_object_unref (parts);
3537 }
3538
3539 static void
3540 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
3541                                                      ModestMainWindow *win)
3542 {
3543         GtkWidget *header_view;
3544         TnyList *header_list;
3545         TnyIterator *iter;
3546         TnyHeader *header;
3547         TnyHeaderFlags flags;
3548         ModestWindow *msg_view_window =  NULL;
3549         gboolean found;
3550
3551         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3552
3553         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3554                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3555
3556         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
3557
3558         if (tny_list_get_length (header_list) == 1) {
3559                 iter = tny_list_create_iterator (header_list);
3560                 header = TNY_HEADER (tny_iterator_get_current (iter));
3561                 g_object_unref (iter);
3562         } else {
3563                 return;
3564         }
3565
3566         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
3567                                                           header, &msg_view_window);
3568         flags = tny_header_get_flags (header);
3569         if (!(flags & TNY_HEADER_FLAG_CACHED))
3570                 return;
3571         if (found) {
3572                 if (msg_view_window != NULL) 
3573                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
3574                 else {
3575                         /* do nothing; uid was registered before, so window is probably on it's way */
3576                         g_warning ("debug: header %p has already been registered", header);
3577                 }
3578         } else {
3579                 ModestMailOperation *mail_op = NULL;
3580                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header);
3581                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
3582                                                                          G_OBJECT (win),
3583                                                                          modest_ui_actions_get_msgs_full_error_handler,
3584                                                                          NULL);
3585                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3586                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
3587                 
3588                 g_object_unref (mail_op);
3589         }
3590         if (header)
3591                 g_object_unref (header);
3592         if (header_list)
3593                 g_object_unref (header_list);
3594 }
3595
3596 /**
3597  * Utility function that transfer messages from both the main window
3598  * and the msg view window when using the "Move to" dialog
3599  */
3600 static void
3601 modest_ui_actions_xfer_messages_from_move_to (TnyFolderStore *dst_folder,
3602                                               ModestWindow *win)
3603 {
3604         TnyList *headers = NULL;
3605         gint response = 0;
3606
3607         if (!TNY_IS_FOLDER (dst_folder)) {
3608                 modest_platform_information_banner (GTK_WIDGET (win),
3609                                                     NULL,
3610                                                     _CS("ckdg_ib_unable_to_move_to_current_location"));
3611                 return;
3612         }
3613
3614         /* Get selected headers */
3615         headers = get_selected_headers (MODEST_WINDOW (win));
3616
3617         /* Ask for user confirmation */
3618         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
3619                                               TNY_FOLDER (dst_folder), 
3620                                               headers);
3621
3622         /* Transfer messages */
3623         if (response == GTK_RESPONSE_OK) {
3624                 ModestMailOperation *mail_op = 
3625                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3626                                                                        G_OBJECT(win),
3627                                                                        modest_ui_actions_move_folder_error_handler,
3628                                                                        NULL);
3629                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3630                                                  mail_op);
3631
3632                 modest_mail_operation_xfer_msgs (mail_op, 
3633                                                  headers,
3634                                                  TNY_FOLDER (dst_folder),
3635                                                  TRUE,
3636                                                  (MODEST_IS_MSG_VIEW_WINDOW (win)) ? transfer_msgs_from_viewer_cb : NULL,
3637                                                  NULL);
3638
3639                 g_object_unref (G_OBJECT (mail_op));
3640         }
3641         g_object_unref (headers);
3642 }
3643
3644
3645 /*
3646  * UI handler for the "Move to" action when invoked from the
3647  * ModestMainWindow
3648  */
3649 static void 
3650 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
3651                                           GtkWidget *folder_view,
3652                                           TnyFolderStore *dst_folder,
3653                                           ModestMainWindow *win)
3654 {
3655         GtkWidget *header_view = NULL;
3656         ModestMailOperation *mail_op = NULL;
3657         TnyFolderStore *src_folder;
3658
3659         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3660
3661         /* Get the source folder */
3662         src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3663         
3664         /* Offer the connection dialog if necessary, if the source folder is in a networked account: */
3665         if (!modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), 
3666                                                                       src_folder))
3667                 goto end;
3668
3669         /* Get header view */
3670         header_view = 
3671                 modest_main_window_get_child_widget (win, MODEST_WIDGET_TYPE_HEADER_VIEW);
3672
3673         /* Get folder or messages to transfer */
3674         if (gtk_widget_is_focus (folder_view)) {
3675
3676                 /* Allow only to transfer folders to the local root folder */
3677                 if (TNY_IS_ACCOUNT (dst_folder) && 
3678                     !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (dst_folder))
3679                         goto end;
3680                 
3681                 /* Clean folder on header view before moving it */
3682                 modest_header_view_clear (MODEST_HEADER_VIEW (header_view)); 
3683
3684                 if (TNY_IS_FOLDER (src_folder)) {
3685                         mail_op = 
3686                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3687                                                                                G_OBJECT(win),
3688                                                                                modest_ui_actions_move_folder_error_handler,
3689                                                                                NULL);
3690                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3691                                                          mail_op);
3692
3693                         modest_mail_operation_xfer_folder (mail_op, 
3694                                                            TNY_FOLDER (src_folder),
3695                                                            dst_folder,
3696                                                            TRUE, NULL, NULL);
3697                         /* Unref mail operation */
3698                         g_object_unref (G_OBJECT (mail_op));
3699                 } else {
3700                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);       
3701                 }
3702         } else if (gtk_widget_is_focus (header_view)) {
3703                 /* Transfer messages */
3704                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
3705         }
3706         
3707  end:
3708     if (src_folder)
3709         g_object_unref (src_folder);
3710 }
3711
3712
3713 /*
3714  * UI handler for the "Move to" action when invoked from the
3715  * ModestMsgViewWindow
3716  */
3717 static void 
3718 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
3719                                               TnyFolderStore *dst_folder,
3720                                               ModestMsgViewWindow *win)
3721 {
3722         TnyHeader *header = NULL;
3723         TnyFolder *src_folder;
3724
3725         /* Create header list */
3726         header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
3727         src_folder = tny_header_get_folder(header);
3728         g_object_unref (header);
3729
3730         /* Transfer the message */
3731         if (modest_platform_connect_and_wait_if_network_folderstore (NULL, TNY_FOLDER_STORE (src_folder)))
3732                 modest_ui_actions_xfer_messages_from_move_to (dst_folder, MODEST_WINDOW (win));
3733
3734         g_object_unref (src_folder);
3735 }
3736
3737 void 
3738 modest_ui_actions_on_move_to (GtkAction *action, 
3739                               ModestWindow *win)
3740 {
3741         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
3742         gint result = 0;
3743         TnyFolderStore *dst_folder = NULL;
3744         ModestMainWindow *main_window;
3745
3746         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
3747                           MODEST_IS_MSG_VIEW_WINDOW (win));
3748
3749         /* Get the main window if exists */
3750         if (MODEST_IS_MAIN_WINDOW (win))
3751                 main_window = MODEST_MAIN_WINDOW (win);
3752         else
3753                 main_window = 
3754                         MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
3755
3756         /* Get the folder view widget if exists */
3757         if (main_window)
3758                 folder_view = modest_main_window_get_child_widget (main_window,
3759                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
3760         else
3761                 folder_view = NULL;
3762
3763         /* Create and run the dialog */
3764         dialog = create_move_to_dialog (GTK_WINDOW (win), folder_view, &tree_view);
3765         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
3766         result = gtk_dialog_run (GTK_DIALOG(dialog));
3767         g_object_ref (tree_view);
3768         gtk_widget_destroy (dialog);
3769
3770         if (result != GTK_RESPONSE_ACCEPT)
3771                 return;
3772
3773         dst_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
3774         /* Offer the connection dialog if necessary: */
3775         if (modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), 
3776                                                                       dst_folder)) {
3777
3778                 /* Do window specific stuff */
3779                 if (MODEST_IS_MAIN_WINDOW (win))
3780                         modest_ui_actions_on_main_window_move_to (action,
3781                                                                   folder_view,
3782                                                                   dst_folder,
3783                                                                   MODEST_MAIN_WINDOW (win));
3784                 else
3785                         modest_ui_actions_on_msg_view_window_move_to (action,
3786                                                                       dst_folder,
3787                                                                       MODEST_MSG_VIEW_WINDOW (win));
3788         }
3789         if (dst_folder)
3790                 g_object_unref (dst_folder);
3791 }
3792
3793 /*
3794  * Calls #HeadersFunc for each header already selected in the main
3795  * window or the message currently being shown in the msg view window
3796  */
3797 static void
3798 do_headers_action (ModestWindow *win, 
3799                    HeadersFunc func,
3800                    gpointer user_data)
3801 {
3802         TnyList *headers_list = NULL;
3803         TnyIterator *iter = NULL;
3804         TnyHeader *header = NULL;
3805         TnyFolder *folder = NULL;
3806
3807         /* Get headers */
3808         headers_list = get_selected_headers (win);
3809         if (!headers_list)
3810                 return;
3811
3812         /* Get the folder */
3813         iter = tny_list_create_iterator (headers_list);
3814         header = TNY_HEADER (tny_iterator_get_current (iter));
3815         if (header) {
3816                 folder = tny_header_get_folder (header);
3817                 g_object_unref (header);
3818         }
3819
3820         /* Call the function for each header */
3821         while (!tny_iterator_is_done (iter)) {
3822                 header = TNY_HEADER (tny_iterator_get_current (iter));
3823                 func (header, win, user_data);
3824                 g_object_unref (header);
3825                 tny_iterator_next (iter);
3826         }
3827
3828         /* Trick: do a poke status in order to speed up the signaling
3829            of observers */
3830         tny_folder_poke_status (folder);
3831
3832         /* Frees */
3833         g_object_unref (folder);
3834         g_object_unref (iter);
3835         g_object_unref (headers_list);
3836 }
3837
3838 void 
3839 modest_ui_actions_view_attachment (GtkAction *action,
3840                                    ModestWindow *window)
3841 {
3842         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3843                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
3844         } else {
3845                 /* not supported window for this action */
3846                 g_return_if_reached ();
3847         }
3848 }
3849
3850 void
3851 modest_ui_actions_save_attachments (GtkAction *action,
3852                                     ModestWindow *window)
3853 {
3854         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3855                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
3856         } else {
3857                 /* not supported window for this action */
3858                 g_return_if_reached ();
3859         }
3860 }
3861
3862 void
3863 modest_ui_actions_remove_attachments (GtkAction *action,
3864                                       ModestWindow *window)
3865 {
3866         if (MODEST_IS_MAIN_WINDOW (window)) {
3867                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
3868         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3869                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
3870         } else {
3871                 /* not supported window for this action */
3872                 g_return_if_reached ();
3873         }
3874 }
3875
3876 void 
3877 modest_ui_actions_on_settings (GtkAction *action, 
3878                                ModestWindow *win)
3879 {
3880         GtkWidget *dialog;
3881
3882         dialog = modest_platform_get_global_settings_dialog ();
3883         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
3884         gtk_widget_show_all (dialog);
3885
3886         gtk_dialog_run (GTK_DIALOG (dialog));
3887
3888         gtk_widget_destroy (dialog);
3889 }
3890
3891 void 
3892 modest_ui_actions_on_help (GtkAction *action, 
3893                            ModestWindow *win)
3894 {
3895         const gchar *help_id = NULL;
3896
3897         if (MODEST_IS_MAIN_WINDOW (win)) {
3898                 const gchar *action_name;
3899                 action_name = gtk_action_get_name (action);
3900
3901                 if (!strcmp (action_name, "FolderViewCSMHelp") ||
3902                     !strcmp (action_name, "HeaderViewCSMHelp")) {
3903                         GtkWidget *folder_view;
3904                         TnyFolderStore *folder_store;
3905                         /* Get selected folder */
3906                         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3907                                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
3908                         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3909
3910                         /* Switch help_id */
3911                         if (TNY_IS_FOLDER (folder_store)) {
3912                                 switch (modest_tny_folder_guess_folder_type (TNY_FOLDER (folder_store))) {
3913                                 case TNY_FOLDER_TYPE_NORMAL:
3914                                         help_id = "applications_email_managefolders";
3915                                         break;
3916                                 case TNY_FOLDER_TYPE_INBOX:
3917                                         help_id = "applications_email_inbox";
3918                                         break;
3919                                 case TNY_FOLDER_TYPE_OUTBOX:
3920                                         help_id = "applications_email_outbox";
3921                                         break;
3922                                 case TNY_FOLDER_TYPE_SENT:
3923                                         help_id = "applications_email_sent";
3924                                         break;
3925                                 case TNY_FOLDER_TYPE_DRAFTS:
3926                                         help_id = "applications_email_drafts";
3927                                         break;
3928                                 case TNY_FOLDER_TYPE_ARCHIVE:
3929                                         help_id = "applications_email_managefolders";
3930                                         break;
3931                                 default:
3932                                         help_id = "applications_email_managefolders";
3933                                 }
3934                         } else {
3935                                 help_id = "applications_email_mainview";        
3936                         }
3937                         g_object_unref (folder_store);
3938                 } else {
3939                         help_id = "applications_email_mainview";        
3940                 }
3941         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3942                 help_id = "applications_email_viewer";
3943         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
3944                 help_id = "applications_email_editor";
3945
3946         modest_platform_show_help (GTK_WINDOW (win), help_id);
3947 }
3948
3949 void 
3950 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
3951                                             ModestWindow *window)
3952 {
3953         ModestMailOperation *mail_op;
3954         TnyList *headers;
3955
3956         /* Get headers */
3957         headers = get_selected_headers (window);
3958         if (!headers)
3959                 return;
3960
3961         /* Create mail operation */
3962         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3963                                                                  G_OBJECT (window),
3964                                                                  modest_ui_actions_get_msgs_full_error_handler, 
3965                                                                  NULL);
3966         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3967         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
3968
3969         /* Frees */
3970         g_object_unref (headers);
3971         g_object_unref (mail_op);
3972 }
3973
3974 void
3975 modest_ui_actions_on_email_menu_activated (GtkAction *action,
3976                                           ModestWindow *window)
3977 {
3978         g_return_if_fail (MODEST_IS_WINDOW (window));
3979
3980         /* Update dimmed */     
3981         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3982 }
3983
3984 void
3985 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
3986                                           ModestWindow *window)
3987 {
3988         g_return_if_fail (MODEST_IS_WINDOW (window));
3989
3990         /* Update dimmed */     
3991         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3992 }
3993
3994 void
3995 modest_ui_actions_on_view_menu_activated (GtkAction *action,
3996                                           ModestWindow *window)
3997 {
3998         g_return_if_fail (MODEST_IS_WINDOW (window));
3999
4000         /* Update dimmed */     
4001         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4002 }
4003
4004 void
4005 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
4006                                           ModestWindow *window)
4007 {
4008         g_return_if_fail (MODEST_IS_WINDOW (window));
4009
4010         /* Update dimmed */     
4011         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4012 }
4013
4014 void
4015 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
4016                                           ModestWindow *window)
4017 {
4018         g_return_if_fail (MODEST_IS_WINDOW (window));
4019
4020         /* Update dimmed */     
4021         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4022 }
4023
4024 void
4025 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
4026                                                  ModestWindow *window)
4027 {
4028         g_return_if_fail (MODEST_IS_WINDOW (window));
4029
4030         /* Update dimmed */     
4031         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4032 }
4033
4034 void
4035 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
4036                                                      ModestWindow *window)
4037 {
4038         g_return_if_fail (MODEST_IS_WINDOW (window));
4039
4040         /* Update dimmed */     
4041         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4042 }
4043
4044 void
4045 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
4046                                                      ModestWindow *window)
4047 {
4048         g_return_if_fail (MODEST_IS_WINDOW (window));
4049
4050         /* Update dimmed */     
4051         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
4052 }
4053
4054 void
4055 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
4056 {
4057         g_return_if_fail (MODEST_IS_WINDOW (window));
4058
4059         /* Update dimmed */     
4060         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
4061 }
4062
4063 void
4064 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
4065 {
4066         g_return_if_fail (MODEST_IS_WINDOW (window));
4067
4068         modest_platform_show_search_messages (GTK_WINDOW (window));
4069 }
4070
4071 void     
4072 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
4073 {
4074         g_return_if_fail (MODEST_IS_WINDOW (win));
4075         modest_platform_show_addressbook (GTK_WINDOW (win));
4076 }
4077
4078
4079 void
4080 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
4081                                           ModestWindow *window)
4082 {
4083         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
4084
4085         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
4086 }
4087
4088 static void 
4089 _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
4090                                    ModestMailOperationState *state,
4091                                    gpointer user_data)
4092 {
4093         g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
4094
4095         /* Set send/receive operation finished */       
4096         if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
4097                 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));
4098         
4099 }
4100
4101