* src/maemo/modest-icon-names.h:
[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_TEXT_VIEW (focused_widget)) {
2588                 GtkTextBuffer *buffer;
2589                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2590                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
2591                 gtk_clipboard_set_can_store (clipboard, NULL, 0);
2592         } else if (MODEST_IS_HEADER_VIEW (focused_widget)) {
2593                 TnyList *header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (focused_widget));
2594                 TnyIterator *iter = tny_list_create_iterator (header_list);
2595                 TnyHeader *header = TNY_HEADER (tny_iterator_get_current (iter));
2596                 TnyFolder *folder = tny_header_get_folder (header);
2597                 TnyAccount *account = tny_folder_get_account (folder);
2598                 const gchar *proto_str = tny_account_get_proto (TNY_ACCOUNT (account));
2599                 /* If it's POP then ask */
2600                 gboolean ask = (modest_protocol_info_get_transport_store_protocol (proto_str) == 
2601                        MODEST_PROTOCOL_STORE_POP) ? TRUE : FALSE;
2602                 g_object_unref (account);
2603                 g_object_unref (folder);
2604                 g_object_unref (header);
2605                 g_object_unref (iter);
2606                 
2607                 /* Check that the messages have been previously downloaded */
2608                 gboolean continue_download = TRUE;
2609                 if (ask)
2610                         continue_download = download_uncached_messages (header_list, GTK_WINDOW (window));
2611                 if (continue_download)
2612                         modest_header_view_copy_selection (MODEST_HEADER_VIEW (focused_widget));
2613                 g_object_unref (header_list);
2614         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2615                 modest_folder_view_copy_selection (MODEST_FOLDER_VIEW (focused_widget));
2616         }    
2617
2618         /* Show information banner */
2619         modest_platform_information_banner (NULL, NULL, _CS("ecoc_ib_edwin_copied"));
2620         
2621 }
2622
2623 void
2624 modest_ui_actions_on_undo (GtkAction *action,
2625                            ModestWindow *window)
2626 {
2627         ModestEmailClipboard *clipboard = NULL;
2628
2629         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2630                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
2631         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2632                 /* Clear clipboard source */
2633                 clipboard = modest_runtime_get_email_clipboard ();
2634                 modest_email_clipboard_clear (clipboard);               
2635         }
2636         else {
2637                 g_return_if_reached ();
2638         }
2639 }
2640
2641 void
2642 modest_ui_actions_on_redo (GtkAction *action,
2643                            ModestWindow *window)
2644 {
2645         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
2646                 modest_msg_edit_window_redo (MODEST_MSG_EDIT_WINDOW (window));
2647         }
2648         else {
2649                 g_return_if_reached ();
2650         }
2651 }
2652
2653
2654 static void
2655 paste_msgs_cb (const GObject *object, gpointer user_data)
2656 {
2657         g_return_if_fail (MODEST_IS_MAIN_WINDOW (object));
2658         g_return_if_fail (GTK_IS_WIDGET (user_data));
2659         
2660         /* destroy information note */
2661         gtk_widget_destroy (GTK_WIDGET(user_data));
2662 }
2663
2664 void
2665 modest_ui_actions_on_paste (GtkAction *action,
2666                             ModestWindow *window)
2667 {
2668         GtkWidget *focused_widget = NULL;
2669         GtkWidget *inf_note = NULL;
2670         ModestMailOperation *mail_op = NULL;
2671
2672         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2673         if (GTK_IS_EDITABLE (focused_widget)) {
2674                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
2675         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2676                 GtkTextBuffer *buffer;
2677                 GtkClipboard *clipboard;
2678
2679                 clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
2680                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2681                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
2682         } else if (MODEST_IS_FOLDER_VIEW (focused_widget)) {
2683                 ModestEmailClipboard *clipboard = NULL;
2684                 TnyFolder *src_folder = NULL;
2685                 TnyFolderStore *folder_store = NULL;
2686                 TnyList *data = NULL;           
2687                 gboolean delete = FALSE;
2688                 
2689                 /* Check clipboard source */
2690                 clipboard = modest_runtime_get_email_clipboard ();
2691                 if (modest_email_clipboard_cleared (clipboard)) 
2692                         return;
2693                 
2694                 /* Get elements to paste */
2695                 modest_email_clipboard_get_data (clipboard, &src_folder, &data, &delete);
2696
2697                 /* Create a new mail operation */
2698                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(window));
2699                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2700                                                  mail_op);
2701                 
2702                 /* Get destination folder */
2703                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (focused_widget));
2704
2705                 /* Launch notification */
2706                 inf_note = modest_platform_animation_banner (GTK_WIDGET (window), NULL, 
2707                                                              _CS("ckct_nw_pasting"));
2708                 if (inf_note != NULL)  {
2709                         gtk_window_set_modal (GTK_WINDOW(inf_note), FALSE);
2710                         gtk_widget_show (GTK_WIDGET(inf_note));
2711                 }
2712
2713                 /* transfer messages  */
2714                 if (data != NULL) {
2715                         modest_mail_operation_xfer_msgs (mail_op, 
2716                                                          data,
2717                                                          TNY_FOLDER (folder_store),
2718                                                          delete,
2719                                                          paste_msgs_cb,
2720                                                          inf_note);
2721                         
2722                 } else if (src_folder != NULL) {                        
2723                         modest_mail_operation_xfer_folder (mail_op, 
2724                                                            src_folder,
2725                                                            folder_store,
2726                                                            delete,
2727                                                            paste_msgs_cb,
2728                                                            inf_note);
2729                 }
2730
2731                 /* Free */
2732                 if (data != NULL) 
2733                         g_object_unref (data);
2734                 if (src_folder != NULL) 
2735                         g_object_unref (src_folder);
2736                 if (folder_store != NULL) 
2737                         g_object_unref (folder_store);
2738         }
2739 }
2740
2741
2742 void
2743 modest_ui_actions_on_select_all (GtkAction *action,
2744                                  ModestWindow *window)
2745 {
2746         GtkWidget *focused_widget;
2747
2748         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
2749         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
2750                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
2751         } else if (GTK_IS_LABEL (focused_widget)) {
2752                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
2753         } else if (GTK_IS_EDITABLE (focused_widget)) {
2754                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
2755         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
2756                 GtkTextBuffer *buffer;
2757                 GtkTextIter start, end;
2758
2759                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
2760                 gtk_text_buffer_get_start_iter (buffer, &start);
2761                 gtk_text_buffer_get_end_iter (buffer, &end);
2762                 gtk_text_buffer_select_range (buffer, &start, &end);
2763         } else if (GTK_IS_HTML (focused_widget)) {
2764                 gtk_html_select_all (GTK_HTML (focused_widget));
2765         } else if (MODEST_IS_MAIN_WINDOW (window)) {
2766                 GtkWidget *header_view = focused_widget;
2767                 GtkTreeSelection *selection = NULL;
2768                 
2769                 if (!(MODEST_IS_HEADER_VIEW (focused_widget)))
2770                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (window),
2771                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2772                                 
2773                 /* Select all messages */
2774                 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(header_view));
2775                 gtk_tree_selection_select_all (selection);
2776
2777                 /* Set focuse on header view */
2778                 gtk_widget_grab_focus (header_view);
2779         }
2780
2781 }
2782
2783 void
2784 modest_ui_actions_on_mark_as_read (GtkAction *action,
2785                                    ModestWindow *window)
2786 {       
2787         g_return_if_fail (MODEST_IS_WINDOW(window));
2788                 
2789         /* Mark each header as read */
2790         do_headers_action (window, headers_action_mark_as_read, NULL);
2791 }
2792
2793 void
2794 modest_ui_actions_on_mark_as_unread (GtkAction *action,
2795                                      ModestWindow *window)
2796 {       
2797         g_return_if_fail (MODEST_IS_WINDOW(window));
2798                 
2799         /* Mark each header as read */
2800         do_headers_action (window, headers_action_mark_as_unread, NULL);
2801 }
2802
2803 void
2804 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
2805                                   GtkRadioAction *selected,
2806                                   ModestWindow *window)
2807 {
2808         gint value;
2809
2810         value = gtk_radio_action_get_current_value (selected);
2811         if (MODEST_IS_WINDOW (window)) {
2812                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
2813         }
2814 }
2815
2816 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
2817                                                         GtkRadioAction *selected,
2818                                                         ModestWindow *window)
2819 {
2820         TnyHeaderFlags flags;
2821         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2822
2823         flags = gtk_radio_action_get_current_value (selected);
2824         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
2825 }
2826
2827 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
2828                                                            GtkRadioAction *selected,
2829                                                            ModestWindow *window)
2830 {
2831         gint file_format;
2832
2833         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2834
2835         file_format = gtk_radio_action_get_current_value (selected);
2836         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
2837 }
2838
2839
2840 void     
2841 modest_ui_actions_on_zoom_plus (GtkAction *action,
2842                                 ModestWindow *window)
2843 {
2844         g_return_if_fail (MODEST_IS_WINDOW (window));
2845
2846         modest_window_zoom_plus (MODEST_WINDOW (window));
2847 }
2848
2849 void     
2850 modest_ui_actions_on_zoom_minus (GtkAction *action,
2851                                  ModestWindow *window)
2852 {
2853         g_return_if_fail (MODEST_IS_WINDOW (window));
2854
2855         modest_window_zoom_minus (MODEST_WINDOW (window));
2856 }
2857
2858 void     
2859 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
2860                                            ModestWindow *window)
2861 {
2862         ModestWindowMgr *mgr;
2863         gboolean fullscreen, active;
2864         g_return_if_fail (MODEST_IS_WINDOW (window));
2865
2866         mgr = modest_runtime_get_window_mgr ();
2867
2868         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
2869         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2870
2871         if (active != fullscreen) {
2872                 modest_window_mgr_set_fullscreen_mode (mgr, active);
2873                 gtk_window_present (GTK_WINDOW (window));
2874         }
2875 }
2876
2877 void
2878 modest_ui_actions_on_change_fullscreen (GtkAction *action,
2879                                         ModestWindow *window)
2880 {
2881         ModestWindowMgr *mgr;
2882         gboolean fullscreen;
2883
2884         g_return_if_fail (MODEST_IS_WINDOW (window));
2885
2886         mgr = modest_runtime_get_window_mgr ();
2887         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2888         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
2889
2890         gtk_window_present (GTK_WINDOW (window));
2891 }
2892
2893 /* 
2894  * Used by modest_ui_actions_on_details to call do_headers_action 
2895  */
2896 static void
2897 headers_action_show_details (TnyHeader *header, 
2898                              ModestWindow *window,
2899                              gpointer user_data)
2900
2901 {
2902         GtkWidget *dialog;
2903         
2904         /* Create dialog */
2905         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
2906
2907         /* Run dialog */
2908         gtk_widget_show_all (dialog);
2909         gtk_dialog_run (GTK_DIALOG (dialog));
2910
2911         gtk_widget_destroy (dialog);
2912 }
2913
2914 /*
2915  * Show the folder details in a ModestDetailsDialog widget
2916  */
2917 static void
2918 show_folder_details (TnyFolder *folder, 
2919                      GtkWindow *window)
2920 {
2921         GtkWidget *dialog;
2922         
2923         /* Create dialog */
2924         dialog = modest_details_dialog_new_with_folder (window, folder);
2925
2926         /* Run dialog */
2927         gtk_widget_show_all (dialog);
2928         gtk_dialog_run (GTK_DIALOG (dialog));
2929
2930         gtk_widget_destroy (dialog);
2931 }
2932
2933 /*
2934  * Show the header details in a ModestDetailsDialog widget
2935  */
2936 void     
2937 modest_ui_actions_on_details (GtkAction *action, 
2938                               ModestWindow *win)
2939 {
2940         TnyList * headers_list;
2941         TnyIterator *iter;
2942         TnyHeader *header;              
2943
2944         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
2945                 TnyMsg *msg;
2946
2947                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
2948                 if (!msg)
2949                         return;
2950                 g_object_unref (msg);           
2951
2952                 headers_list = get_selected_headers (win);
2953                 if (!headers_list)
2954                         return;
2955
2956                 iter = tny_list_create_iterator (headers_list);
2957
2958                 header = TNY_HEADER (tny_iterator_get_current (iter));
2959                 headers_action_show_details (header, win, NULL);
2960                 g_object_unref (header);
2961
2962                 g_object_unref (iter);
2963                 g_object_unref (headers_list);
2964
2965         } else if (MODEST_IS_MAIN_WINDOW (win)) {
2966                 GtkWidget *folder_view, *header_view;
2967
2968                 /* Check which widget has the focus */
2969                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2970                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
2971                 if (gtk_widget_is_focus (folder_view)) {
2972                         TnyFolderStore *folder_store
2973                                 = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2974                         if (!folder_store) {
2975                                 g_warning ("%s: No item was selected.\n", __FUNCTION__);
2976                                 return; 
2977                         }
2978                         /* Show only when it's a folder */
2979                         /* This function should not be called for account items, 
2980                          * because we dim the menu item for them. */
2981                         if (TNY_IS_FOLDER (folder_store)) {
2982                                 show_folder_details (TNY_FOLDER (folder_store), GTK_WINDOW (win));
2983                         }
2984
2985                         g_object_unref (folder_store);
2986
2987                 } else {
2988                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2989                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2990                         /* Show details of each header */
2991                         do_headers_action (win, headers_action_show_details, header_view);
2992                 }
2993         }
2994 }
2995
2996 void     
2997 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
2998                                      ModestMsgEditWindow *window)
2999 {
3000         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3001
3002         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
3003 }
3004
3005 void     
3006 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
3007                                       ModestMsgEditWindow *window)
3008 {
3009         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3010
3011         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
3012 }
3013
3014 void
3015 modest_ui_actions_toggle_folders_view (GtkAction *action, 
3016                                        ModestMainWindow *main_window)
3017 {
3018         ModestConf *conf;
3019         
3020         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
3021
3022         conf = modest_runtime_get_conf ();
3023         
3024         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
3025                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
3026         else
3027                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
3028 }
3029
3030 void 
3031 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
3032                                      ModestWindow *window)
3033 {
3034         gboolean active, fullscreen = FALSE;
3035         ModestWindowMgr *mgr;
3036
3037         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
3038
3039         /* Check if we want to toggle the toolbar vuew in fullscreen
3040            or normal mode */
3041         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
3042                      "ViewShowToolbarFullScreen")) {
3043                 fullscreen = TRUE;
3044         }
3045
3046         /* Toggle toolbar */
3047         mgr = modest_runtime_get_window_mgr ();
3048         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
3049 }
3050
3051 void     
3052 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
3053                                            ModestMsgEditWindow *window)
3054 {
3055         modest_msg_edit_window_select_font (window);
3056 }
3057
3058 void
3059 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
3060                                                   const gchar *display_name,
3061                                                   GtkWindow *window)
3062 {
3063         /* Do not change the application name if the widget has not
3064            the focus. This callback could be called even if the folder
3065            view has not the focus, because the handled signal could be
3066            emitted when the folder view is redrawn */
3067         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
3068                 if (display_name)
3069                         gtk_window_set_title (window, display_name);
3070                 else
3071                         gtk_window_set_title (window, " ");
3072         }
3073 }
3074
3075 void
3076 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
3077 {
3078         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3079         modest_msg_edit_window_select_contacts (window);
3080 }
3081
3082 void
3083 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
3084 {
3085         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3086         modest_msg_edit_window_check_names (window);
3087 }
3088
3089
3090 static GtkWidget*
3091 create_move_to_dialog (ModestWindow *win,
3092                        GtkWidget *folder_view,
3093                        GtkWidget **tree_view)
3094 {
3095         GtkWidget *dialog, *scroll;
3096
3097         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
3098                                               GTK_WINDOW (win),
3099                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
3100                                               GTK_STOCK_OK,
3101                                               GTK_RESPONSE_ACCEPT,
3102                                               GTK_STOCK_CANCEL,
3103                                               GTK_RESPONSE_REJECT,
3104                                               NULL);
3105
3106         /* Create scrolled window */
3107         scroll = gtk_scrolled_window_new (NULL, NULL);
3108         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
3109                                          GTK_POLICY_AUTOMATIC,
3110                                          GTK_POLICY_AUTOMATIC);
3111
3112         /* Create folder view */
3113         *tree_view = modest_platform_create_folder_view (NULL);
3114
3115         /* It could happen that we're trying to move a message from a
3116            window (msg window for example) after the main window was
3117            closed, so we can not just get the model of the folder
3118            view */
3119         if (MODEST_IS_FOLDER_VIEW (folder_view))
3120                 gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
3121                                          gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
3122         else
3123                 modest_folder_view_update_model (MODEST_FOLDER_VIEW (*tree_view), 
3124                                                  TNY_ACCOUNT_STORE (modest_runtime_get_account_store ()));
3125
3126         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
3127
3128         /* Add scroll to dialog */
3129         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
3130                             scroll, FALSE, FALSE, 0);
3131
3132         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
3133
3134         /* Select INBOX or local account */
3135         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (*tree_view));
3136
3137         return dialog;
3138 }
3139
3140 /*
3141  * Returns TRUE if at least one of the headers of the list belongs to
3142  * a message that has been fully retrieved.
3143  */
3144 static gboolean
3145 has_retrieved_msgs (TnyList *list)
3146 {
3147         TnyIterator *iter;
3148         gboolean found = FALSE;
3149
3150         iter = tny_list_create_iterator (list);
3151         while (tny_iterator_is_done (iter) && !found) {
3152                 TnyHeader *header;
3153                 TnyHeaderFlags flags;
3154
3155                 header = TNY_HEADER (tny_iterator_get_current (iter));
3156                 flags = tny_header_get_flags (header);
3157                 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
3158                         found = TRUE;
3159
3160                 if (!found)
3161                         tny_iterator_next (iter);
3162         }
3163         g_object_unref (iter);
3164
3165         return found;
3166 }
3167
3168 /*
3169  * Shows a confirmation dialog to the user when we're moving messages
3170  * from a remote server to the local storage. Returns the dialog
3171  * response. If it's other kind of movement the it always returns
3172  * GTK_RESPONSE_OK
3173  */
3174 static gint
3175 msgs_move_to_confirmation (GtkWindow *win,
3176                            TnyFolder *dest_folder,
3177                            TnyList *headers)
3178 {
3179         gint response = GTK_RESPONSE_OK;
3180
3181         /* If the destination is a local folder */
3182         if (modest_tny_folder_is_local_folder (dest_folder)) {
3183                 TnyFolder *src_folder;
3184                 TnyIterator *iter;
3185                 TnyHeader *header;
3186
3187                 /* Get source folder */
3188                 iter = tny_list_create_iterator (headers);
3189                 header = TNY_HEADER (tny_iterator_get_current (iter));
3190                 src_folder = tny_header_get_folder (header);
3191                 g_object_unref (header);
3192                 g_object_unref (iter);
3193
3194                 /* if no src_folder, message may be an attahcment */
3195                 if (src_folder == NULL) 
3196                         return GTK_RESPONSE_CANCEL;
3197
3198                 /* If the source is a remote folder */
3199                 if (!modest_tny_folder_is_local_folder (src_folder)) {
3200                         const gchar *message;
3201                         
3202                         if (has_retrieved_msgs (headers))
3203                                 message = ngettext ("mcen_nc_move_retrieve", "mcen_nc_move_retrieves",
3204                                                     tny_list_get_length (headers));
3205                         else 
3206                                 message = ngettext ("mcen_nc_move_header", "mcen_nc_move_headers",
3207                                                     tny_list_get_length (headers));
3208
3209                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
3210                                                                             (const gchar *) message);
3211                 }
3212                 g_object_unref (src_folder);
3213         }
3214         return response;
3215 }
3216
3217
3218
3219 static void
3220 transfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
3221 {
3222         ModestMsgViewWindow *self = NULL;
3223         gboolean last, first;
3224
3225         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
3226         self = MODEST_MSG_VIEW_WINDOW (object);
3227         
3228         last = modest_msg_view_window_last_message_selected (self);
3229         first = modest_msg_view_window_first_message_selected (self);   
3230         if (last & first) {
3231                 /* No more messages to view, so close this window */
3232 /*              gboolean ret_value; */
3233 /*              g_signal_emit_by_name (G_OBJECT (self), "delete-event", NULL, &ret_value); */
3234                 modest_ui_actions_on_close_window (NULL, MODEST_WINDOW(self));
3235         } else if (last)
3236                 modest_msg_view_window_select_previous_message (self);
3237         else 
3238                 modest_msg_view_window_select_next_message (self);
3239 }
3240
3241 void
3242 modest_ui_actions_move_folder_error_handler (ModestMailOperation *mail_op, 
3243                                              gpointer user_data)
3244 {
3245         GObject *win = modest_mail_operation_get_source (mail_op);
3246         const GError *error = NULL;
3247         const gchar *message = NULL;
3248         
3249         /* Get error message */
3250         error = modest_mail_operation_get_error (mail_op);
3251         if (error != NULL && error->message != NULL) {
3252                 message = error->message;
3253         } else {
3254                 message = _("mail_in_ui_folder_move_target_error");
3255         }
3256         
3257         /* Show notification dialog */
3258         modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, message);
3259         g_object_unref (win);
3260 }
3261
3262 void
3263 modest_ui_actions_send_receive_error_handler (ModestMailOperation *mail_op, 
3264                                               gpointer user_data)
3265 {
3266         GObject *win = modest_mail_operation_get_source (mail_op);
3267         const GError *error = modest_mail_operation_get_error (mail_op);
3268
3269         g_return_if_fail (error != NULL);
3270         if (error->message != NULL)             
3271                 g_printerr ("modest: %s\n", error->message);
3272         else
3273                 g_printerr ("modest: unkonw error on send&receive operation");
3274
3275         /* Show error message */
3276 /*      if (modest_mail_operation_get_id (mail_op) == MODEST_MAIL_OPERATION_TYPE_RECEIVE) */
3277 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3278 /*                                                      _CS("sfil_ib_unable_to_receive")); */
3279 /*      else  */
3280 /*              modest_platform_run_information_dialog ((win) ? GTK_WINDOW (win) : NULL, */
3281 /*                                                      _CS("sfil_ib_unable_to_send")); */
3282         g_object_unref (win);
3283 }
3284
3285 static void
3286 open_msg_for_purge_cb (ModestMailOperation *mail_op, 
3287                        TnyHeader *header, 
3288                        TnyMsg *msg, 
3289                        gpointer user_data)
3290 {
3291         TnyList *parts;
3292         TnyIterator *iter;
3293         gint pending_purges = 0;
3294         gboolean some_purged = FALSE;
3295         ModestWindow *win = MODEST_WINDOW (user_data);
3296
3297         /* If there was any error */
3298         if (!modest_ui_actions_msg_retrieval_check (mail_op, header, msg))
3299                 return;
3300
3301         /* Once the message has been retrieved for purging, we check if
3302          * it's all ok for purging */
3303
3304         parts = tny_simple_list_new ();
3305         tny_mime_part_get_parts (TNY_MIME_PART (msg), parts);
3306         iter = tny_list_create_iterator (parts);
3307
3308         while (!tny_iterator_is_done (iter)) {
3309                 TnyMimePart *part;
3310                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3311                 if (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part)) {
3312                         if (tny_mime_part_is_purged (part))
3313                                 some_purged = TRUE;
3314                         else
3315                                 pending_purges++;
3316                 }
3317                 tny_iterator_next (iter);
3318         }
3319
3320         if (pending_purges>0) {
3321                 gint response;
3322                 response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),_("mcen_nc_purge_file_text_inbox"));
3323
3324                 if (response == GTK_RESPONSE_OK) {
3325                         modest_platform_information_banner (NULL, NULL, _("mcen_ib_removing_attachment"));
3326                         tny_iterator_first (iter);
3327                         while (!tny_iterator_is_done (iter)) {
3328                                 TnyMimePart *part;
3329                                 
3330                                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3331                                 if (tny_mime_part_is_attachment (part) || TNY_IS_MSG (part))
3332                                         tny_mime_part_set_purged (part);
3333                                 tny_iterator_next (iter);
3334                         }
3335                         
3336                         tny_msg_rewrite_cache (msg);
3337                 }
3338         } else {
3339                 modest_platform_information_banner (NULL, NULL, _("mail_ib_attachment_already_purged"));
3340         }
3341
3342         /* remove attachments */
3343         tny_iterator_first (iter);
3344         while (!tny_iterator_is_done (iter)) {
3345                 TnyMimePart *part;
3346                         
3347                 part = TNY_MIME_PART (tny_iterator_get_current (iter));
3348                 g_object_unref (part);
3349                 tny_iterator_next (iter);
3350         }
3351
3352         g_object_unref (iter);
3353         g_object_unref (parts);
3354 }
3355
3356 static void
3357 modest_ui_actions_on_main_window_remove_attachments (GtkAction *action,
3358                                                      ModestMainWindow *win)
3359 {
3360         GtkWidget *header_view;
3361         TnyList *header_list;
3362         TnyIterator *iter;
3363         TnyHeader *header;
3364         TnyHeaderFlags flags;
3365         ModestWindow *msg_view_window =  NULL;
3366         gboolean found;
3367
3368         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3369
3370         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3371                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3372
3373         header_list = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
3374
3375         if (tny_list_get_length (header_list) == 1) {
3376                 iter = tny_list_create_iterator (header_list);
3377                 header = TNY_HEADER (tny_iterator_get_current (iter));
3378                 g_object_unref (iter);
3379         } else {
3380                 return;
3381         }
3382
3383         found = modest_window_mgr_find_registered_header (modest_runtime_get_window_mgr (),
3384                                                           header, &msg_view_window);
3385         flags = tny_header_get_flags (header);
3386         if (!(flags & TNY_HEADER_FLAG_CACHED))
3387                 return;
3388         if (found) {
3389                 if (msg_view_window != NULL) 
3390                         modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (msg_view_window), TRUE);
3391                 else {
3392                         /* do nothing; uid was registered before, so window is probably on it's way */
3393                         g_warning ("debug: header %p has already been registered", header);
3394                 }
3395         } else {
3396                 ModestMailOperation *mail_op = NULL;
3397                 modest_window_mgr_register_header (modest_runtime_get_window_mgr (), header);
3398                 mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE,
3399                                                                          G_OBJECT (win),
3400                                                                          modest_ui_actions_get_msgs_full_error_handler,
3401                                                                          NULL);
3402                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3403                 modest_mail_operation_get_msg (mail_op, header, open_msg_for_purge_cb, win);
3404                 
3405                 g_object_unref (mail_op);
3406         }
3407         if (header)
3408                 g_object_unref (header);
3409         if (header_list)
3410                 g_object_unref (header_list);
3411 }
3412
3413 /*
3414  * UI handler for the "Move to" action when invoked from the
3415  * ModestMainWindow
3416  */
3417 static void 
3418 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
3419                                           ModestMainWindow *win)
3420 {
3421         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
3422         GtkWidget *header_view = NULL;
3423         gint result = 0;
3424         TnyFolderStore *folder_store = NULL;
3425         ModestMailOperation *mail_op = NULL;
3426
3427         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
3428
3429         /* Get the folder view */
3430         folder_view = modest_main_window_get_child_widget (win,
3431                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
3432                                                            
3433         TnyFolderStore *src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3434         
3435         /* Offer the connection dialog if necessary, if the source folder is in a networked account: */
3436         if (!modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), src_folder)) {
3437                 if (src_folder) {
3438                         g_object_unref (src_folder);
3439                 }
3440                 
3441                 return;
3442         }
3443
3444         /* Get header view */
3445         header_view = modest_main_window_get_child_widget (win,
3446                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
3447
3448         /* Create and run the dialog */
3449         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);
3450         modest_folder_view_select_first_inbox_or_local (MODEST_FOLDER_VIEW (tree_view));
3451         result = gtk_dialog_run (GTK_DIALOG(dialog));
3452         g_object_ref (tree_view);
3453
3454         /* We do this to save an indentation level ;-) */
3455         if (result != GTK_RESPONSE_ACCEPT)
3456                 goto end;
3457
3458         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
3459
3460         if (TNY_IS_ACCOUNT (folder_store) && 
3461             !MODEST_IS_TNY_LOCAL_FOLDERS_ACCOUNT (folder_store))
3462                 goto end;
3463
3464         /* Offer the connection dialog if necessary: */
3465         if (!modest_platform_connect_and_wait_if_network_folderstore (GTK_WINDOW (win), folder_store)) {
3466                         goto end;
3467         }
3468
3469         /* Get folder or messages to transfer */
3470         if (gtk_widget_is_focus (folder_view)) {
3471                 
3472                 /* Clean folder on header view before moving it */
3473                 modest_header_view_clear (MODEST_HEADER_VIEW (header_view)); 
3474
3475                 if (TNY_IS_FOLDER (src_folder)) {
3476                         mail_op = 
3477                                 modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3478                                                                        G_OBJECT(win),
3479                                                                        modest_ui_actions_move_folder_error_handler,
3480                                                                        NULL);
3481                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3482
3483                         modest_mail_operation_xfer_folder (mail_op, 
3484                                                            TNY_FOLDER (src_folder),
3485                                                            folder_store,
3486                                                            TRUE, NULL, NULL);
3487                         /* Unref mail operation */
3488                         g_object_unref (G_OBJECT (mail_op));
3489                 } else {
3490                         g_warning ("%s: src_folder is not a TnyFolder.\n", __FUNCTION__);       
3491                 }
3492         } else {
3493                 if (gtk_widget_is_focus (header_view)) {
3494                         TnyList *headers = NULL;
3495                         gint response = 0;
3496
3497                         /* TODO: Check for connection if the headers are on a network account. */
3498                         headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
3499
3500                         /* Ask for user confirmation */
3501                         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
3502                                                               TNY_FOLDER (folder_store), 
3503                                                               headers);
3504
3505                         /* Transfer messages */
3506                         if (response == GTK_RESPONSE_OK) {
3507                                 mail_op = 
3508                                         modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3509                                                                                        G_OBJECT(win),
3510                                                                                        modest_ui_actions_move_folder_error_handler,
3511                                                                                        NULL);
3512                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3513                                                                  mail_op);
3514
3515                                 modest_mail_operation_xfer_msgs (mail_op, 
3516                                                                  headers,
3517                                                                  TNY_FOLDER (folder_store),
3518                                                                  TRUE,
3519                                                                  NULL,
3520                                                                  NULL);
3521
3522                                 g_object_unref (G_OBJECT (mail_op));
3523                         }
3524                         g_object_unref (headers);
3525                 }
3526         }
3527         
3528  end:
3529     if (src_folder)
3530         g_object_unref (src_folder);
3531                         
3532         if (folder_store)
3533                 g_object_unref (folder_store);
3534
3535         gtk_widget_destroy (dialog);
3536 }
3537
3538
3539 /*
3540  * UI handler for the "Move to" action when invoked from the
3541  * ModestMsgViewWindow
3542  */
3543 static void 
3544 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
3545                                               ModestMsgViewWindow *win)
3546 {
3547         GtkWidget *dialog, *folder_view, *tree_view = NULL;
3548         gint result = 0;
3549         ModestMainWindow *main_window = NULL;
3550         TnyHeader *header = NULL;
3551         TnyList *headers = NULL;
3552
3553         /* Get the folder view */
3554         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
3555         if (main_window)
3556                 folder_view = modest_main_window_get_child_widget (main_window,
3557                                                                    MODEST_WIDGET_TYPE_FOLDER_VIEW);
3558         else
3559                 folder_view = NULL;
3560
3561         /* Create and run the dialog */
3562         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);  
3563         result = gtk_dialog_run (GTK_DIALOG(dialog));
3564
3565         if (result == GTK_RESPONSE_ACCEPT) {
3566                 TnyFolderStore *folder_store;
3567                 gint response;
3568
3569                 /* Create header list */
3570                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
3571                 g_return_if_fail (header != NULL);
3572
3573                 /* Offer the connection dialog if necessary: */
3574                 /* TODO: What's the extra g_object_ref() for? Isn't this leaking a ref? */
3575                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (g_object_ref (tree_view)));
3576                 TnyFolder *header_folder = tny_header_get_folder(header);
3577                 if (modest_platform_connect_and_wait_if_network_folderstore (NULL, folder_store) &&
3578                     modest_platform_connect_and_wait_if_network_folderstore (NULL, TNY_FOLDER_STORE (header_folder))) {
3579                         
3580                         headers = tny_simple_list_new ();
3581                         tny_list_prepend (headers, G_OBJECT (header));
3582                         g_object_unref (header);
3583
3584                         /* Ask user for confirmation. MSG-NOT404 */
3585                         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
3586                                                       TNY_FOLDER (folder_store), 
3587                                                       headers);
3588
3589                         /* Transfer current msg */
3590                         if (response == GTK_RESPONSE_OK) {
3591                                 ModestMailOperation *mail_op;
3592
3593                                 /* Create mail op */
3594                                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_TYPE_RECEIVE, G_OBJECT(win));
3595                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
3596                                                          mail_op);
3597                         
3598                                 /* Transfer messages */
3599                                 modest_mail_operation_xfer_msgs (mail_op, 
3600                                                          headers,
3601                                                          TNY_FOLDER (folder_store),
3602                                                          TRUE,
3603                                                          transfer_msgs_from_viewer_cb,
3604                                                          NULL);
3605                                 g_object_unref (G_OBJECT (mail_op));
3606                         }
3607                 }
3608                 
3609                 if (header_folder)
3610                         g_object_unref (header_folder);
3611
3612                 if (headers)
3613                         g_object_unref (headers);
3614                         
3615                 if (folder_store)
3616                         g_object_unref (folder_store);
3617         }
3618         
3619         gtk_widget_destroy (dialog);
3620 }
3621
3622 void 
3623 modest_ui_actions_on_move_to (GtkAction *action, 
3624                               ModestWindow *win)
3625 {
3626         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
3627                           MODEST_IS_MSG_VIEW_WINDOW (win));
3628
3629         if (MODEST_IS_MAIN_WINDOW (win)) 
3630                 modest_ui_actions_on_main_window_move_to (action, 
3631                                                           MODEST_MAIN_WINDOW (win));
3632         else
3633                 modest_ui_actions_on_msg_view_window_move_to (action, 
3634                                                               MODEST_MSG_VIEW_WINDOW (win));
3635 }
3636
3637 /*
3638  * Calls #HeadersFunc for each header already selected in the main
3639  * window or the message currently being shown in the msg view window
3640  */
3641 static void
3642 do_headers_action (ModestWindow *win, 
3643                    HeadersFunc func,
3644                    gpointer user_data)
3645 {
3646         TnyList *headers_list;
3647         TnyIterator *iter;
3648         TnyHeader *header;
3649         TnyFolder *folder;
3650
3651         /* Get headers */
3652         headers_list = get_selected_headers (win);
3653         if (!headers_list)
3654                 return;
3655
3656         /* Get the folder */
3657         iter = tny_list_create_iterator (headers_list);
3658         header = TNY_HEADER (tny_iterator_get_current (iter));
3659         folder = tny_header_get_folder (header);
3660         g_object_unref (header);
3661
3662         /* Call the function for each header */
3663         while (!tny_iterator_is_done (iter)) {
3664                 header = TNY_HEADER (tny_iterator_get_current (iter));
3665                 func (header, win, user_data);
3666                 g_object_unref (header);
3667                 tny_iterator_next (iter);
3668         }
3669
3670         /* Trick: do a poke status in order to speed up the signaling
3671            of observers */
3672         tny_folder_poke_status (folder);
3673
3674         /* Frees */
3675         g_object_unref (folder);
3676         g_object_unref (iter);
3677         g_object_unref (headers_list);
3678 }
3679
3680 void 
3681 modest_ui_actions_view_attachment (GtkAction *action,
3682                                    ModestWindow *window)
3683 {
3684         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3685                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
3686         } else {
3687                 /* not supported window for this action */
3688                 g_return_if_reached ();
3689         }
3690 }
3691
3692 void
3693 modest_ui_actions_save_attachments (GtkAction *action,
3694                                     ModestWindow *window)
3695 {
3696         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3697                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
3698         } else {
3699                 /* not supported window for this action */
3700                 g_return_if_reached ();
3701         }
3702 }
3703
3704 void
3705 modest_ui_actions_remove_attachments (GtkAction *action,
3706                                       ModestWindow *window)
3707 {
3708         if (MODEST_IS_MAIN_WINDOW (window)) {
3709                 modest_ui_actions_on_main_window_remove_attachments (action, MODEST_MAIN_WINDOW (window));
3710         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
3711                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), FALSE);
3712         } else {
3713                 /* not supported window for this action */
3714                 g_return_if_reached ();
3715         }
3716 }
3717
3718 void 
3719 modest_ui_actions_on_settings (GtkAction *action, 
3720                                ModestWindow *win)
3721 {
3722         GtkWidget *dialog;
3723
3724         dialog = modest_platform_get_global_settings_dialog ();
3725         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
3726         gtk_widget_show_all (dialog);
3727
3728         gtk_dialog_run (GTK_DIALOG (dialog));
3729
3730         gtk_widget_destroy (dialog);
3731 }
3732
3733 void 
3734 modest_ui_actions_on_help (GtkAction *action, 
3735                            ModestWindow *win)
3736 {
3737         const gchar *help_id = NULL;
3738
3739         if (MODEST_IS_MAIN_WINDOW (win)) {
3740                 const gchar *action_name;
3741                 action_name = gtk_action_get_name (action);
3742
3743                 if (!strcmp (action_name, "FolderViewCSMHelp") ||
3744                     !strcmp (action_name, "HeaderViewCSMHelp")) {
3745                         GtkWidget *folder_view;
3746                         TnyFolderStore *folder_store;
3747                         /* Get selected folder */
3748                         folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
3749                                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
3750                         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
3751
3752                         /* Switch help_id */
3753                         if (TNY_IS_FOLDER (folder_store)) {
3754                                 switch (tny_folder_get_folder_type (TNY_FOLDER (folder_store))) {
3755                                 case TNY_FOLDER_TYPE_NORMAL:
3756                                         help_id = "applications_email_userfolder";
3757                                         break;
3758                                 case TNY_FOLDER_TYPE_INBOX:
3759                                         help_id = "applications_email_inbox";
3760                                         break;
3761                                 case TNY_FOLDER_TYPE_OUTBOX:
3762                                         help_id = "applications_email_outbox";
3763                                         break;
3764                                 case TNY_FOLDER_TYPE_SENT:
3765                                         help_id = "applications_email_sent";
3766                                         break;
3767                                 case TNY_FOLDER_TYPE_DRAFTS:
3768                                         help_id = "applications_email_drafts";
3769                                         break;
3770                                 case TNY_FOLDER_TYPE_ARCHIVE:
3771                                         help_id = "applications_email_archive";
3772                                         break;
3773                                 default:
3774                                         help_id = "applications_email_mainview";
3775                                 }
3776                         } else {
3777                                 help_id = "applications_email_mainview";        
3778                         }
3779                         g_object_unref (folder_store);
3780                 } else {
3781                         help_id = "applications_email_mainview";        
3782                 }
3783         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
3784                 help_id = "applications_email_viewer";
3785         } else if (MODEST_IS_MSG_EDIT_WINDOW (win))
3786                 help_id = "applications_email_editor";
3787
3788         modest_platform_show_help (GTK_WINDOW (win), help_id);
3789 }
3790
3791 void 
3792 modest_ui_actions_on_retrieve_msg_contents (GtkAction *action,
3793                                             ModestWindow *window)
3794 {
3795         ModestMailOperation *mail_op;
3796         TnyList *headers;
3797
3798         /* Get headers */
3799         headers = get_selected_headers (window);
3800         if (!headers)
3801                 return;
3802
3803         /* Create mail operation */
3804         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_TYPE_RECEIVE, 
3805                                                                  G_OBJECT (window),
3806                                                                  modest_ui_actions_get_msgs_full_error_handler, 
3807                                                                  NULL);
3808         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
3809         modest_mail_operation_get_msgs_full (mail_op, headers, NULL, NULL, NULL);
3810
3811         /* Frees */
3812         g_object_unref (headers);
3813         g_object_unref (mail_op);
3814 }
3815
3816 void
3817 modest_ui_actions_on_email_menu_activated (GtkAction *action,
3818                                           ModestWindow *window)
3819 {
3820         g_return_if_fail (MODEST_IS_WINDOW (window));
3821
3822         /* Update dimmed */     
3823         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3824 }
3825
3826 void
3827 modest_ui_actions_on_edit_menu_activated (GtkAction *action,
3828                                           ModestWindow *window)
3829 {
3830         g_return_if_fail (MODEST_IS_WINDOW (window));
3831
3832         /* Update dimmed */     
3833         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3834 }
3835
3836 void
3837 modest_ui_actions_on_view_menu_activated (GtkAction *action,
3838                                           ModestWindow *window)
3839 {
3840         g_return_if_fail (MODEST_IS_WINDOW (window));
3841
3842         /* Update dimmed */     
3843         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3844 }
3845
3846 void
3847 modest_ui_actions_on_tools_menu_activated (GtkAction *action,
3848                                           ModestWindow *window)
3849 {
3850         g_return_if_fail (MODEST_IS_WINDOW (window));
3851
3852         /* Update dimmed */     
3853         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3854 }
3855
3856 void
3857 modest_ui_actions_on_attachment_menu_activated (GtkAction *action,
3858                                           ModestWindow *window)
3859 {
3860         g_return_if_fail (MODEST_IS_WINDOW (window));
3861
3862         /* Update dimmed */     
3863         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3864 }
3865
3866 void
3867 modest_ui_actions_on_toolbar_csm_menu_activated (GtkAction *action,
3868                                                  ModestWindow *window)
3869 {
3870         g_return_if_fail (MODEST_IS_WINDOW (window));
3871
3872         /* Update dimmed */     
3873         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3874 }
3875
3876 void
3877 modest_ui_actions_on_folder_view_csm_menu_activated (GtkAction *action,
3878                                                      ModestWindow *window)
3879 {
3880         g_return_if_fail (MODEST_IS_WINDOW (window));
3881
3882         /* Update dimmed */     
3883         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3884 }
3885
3886 void
3887 modest_ui_actions_on_header_view_csm_menu_activated (GtkAction *action,
3888                                                      ModestWindow *window)
3889 {
3890         g_return_if_fail (MODEST_IS_WINDOW (window));
3891
3892         /* Update dimmed */     
3893         modest_window_check_dimming_rules_group (window, "ModestMenuDimmingRules");     
3894 }
3895
3896 void
3897 modest_ui_actions_check_toolbar_dimming_rules (ModestWindow *window)
3898 {
3899         g_return_if_fail (MODEST_IS_WINDOW (window));
3900
3901         /* Update dimmed */     
3902         modest_window_check_dimming_rules_group (window, "ModestToolbarDimmingRules");  
3903 }
3904
3905 void
3906 modest_ui_actions_on_search_messages (GtkAction *action, ModestWindow *window)
3907 {
3908         g_return_if_fail (MODEST_IS_WINDOW (window));
3909
3910         modest_platform_show_search_messages (GTK_WINDOW (window));
3911 }
3912
3913 void     
3914 modest_ui_actions_on_open_addressbook (GtkAction *action, ModestWindow *win)
3915 {
3916         g_return_if_fail (MODEST_IS_WINDOW (win));
3917         modest_platform_show_addressbook (GTK_WINDOW (win));
3918 }
3919
3920
3921 void
3922 modest_ui_actions_on_toggle_find_in_page (GtkToggleAction *action,
3923                                           ModestWindow *window)
3924 {
3925         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
3926
3927         modest_msg_edit_window_toggle_find_toolbar (MODEST_MSG_EDIT_WINDOW (window), gtk_toggle_action_get_active (action));
3928 }
3929
3930 static void 
3931 _on_send_receive_progress_changed (ModestMailOperation  *mail_op, 
3932                                    ModestMailOperationState *state,
3933                                    gpointer user_data)
3934 {
3935         g_return_if_fail (MODEST_IS_MAIN_WINDOW(user_data));
3936
3937         /* Set send/receive operation finished */       
3938         if (state->status != MODEST_MAIL_OPERATION_STATUS_IN_PROGRESS)
3939                 modest_main_window_notify_send_receive_completed (MODEST_MAIN_WINDOW(user_data));
3940         
3941 }
3942
3943