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