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