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