* modest-mail-operation.c: Set FAILED status if an exception is received.
[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 <string.h>
36 #include <modest-runtime.h>
37 #include <modest-tny-folder.h>
38 #include <modest-tny-msg.h>
39 #include <modest-tny-account.h>
40 #include <modest-address-book.h>
41
42 #include "modest-ui-actions.h"
43
44 #include "modest-tny-platform-factory.h"
45 #include "modest-platform.h"
46
47 #ifdef MODEST_PLATFORM_MAEMO
48 #include "maemo/modest-osso-state-saving.h"
49 #endif /* MODEST_PLATFORM_MAEMO */
50
51 #include "widgets/modest-ui-constants.h"
52 #include <widgets/modest-main-window.h>
53 #include <widgets/modest-msg-view-window.h>
54 #include <widgets/modest-account-view-window.h>
55 #include <widgets/modest-details-dialog.h>
56 #include <widgets/modest-attachments-view.h>
57 #include "widgets/modest-global-settings-dialog.h"
58 #include "modest-connection-specific-smtp-window.h"
59 #include "modest-account-mgr-helpers.h"
60 #include "modest-mail-operation.h"
61 #include "modest-text-utils.h"
62
63 #ifdef MODEST_HAVE_EASYSETUP
64 #include "easysetup/modest-easysetup-wizard.h"
65 #endif /* MODEST_HAVE_EASYSETUP */
66
67 #include <modest-widget-memory.h>
68 #include <tny-error.h>
69 #include <tny-simple-list.h>
70 #include <tny-msg-view.h>
71 #include <tny-device.h>
72
73 typedef struct _GetMsgAsyncHelper {     
74         ModestWindow *window;
75         ModestMailOperation *mail_op;
76         TnyIterator *iter;
77         guint num_ops;
78         GFunc func;     
79         gpointer user_data;
80 } GetMsgAsyncHelper;
81
82 typedef enum _ReplyForwardAction {
83         ACTION_REPLY,
84         ACTION_REPLY_TO_ALL,
85         ACTION_FORWARD
86 } ReplyForwardAction;
87
88 typedef struct _ReplyForwardHelper {
89         guint reply_forward_type;
90         ReplyForwardAction action;
91         gchar *account_name;
92 } ReplyForwardHelper;
93
94 typedef struct _HeaderActivatedHelper {
95         GtkTreeModel *model;
96         GtkTreeRowReference *row_reference;
97         TnyFolder *folder;
98         TnyHeader *header;
99 } HeaderActivatedHelper;
100
101 /*
102  * The do_headers_action uses this kind of functions to perform some
103  * action to each member of a list of headers
104  */
105 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
106
107 static void
108 do_headers_action (ModestWindow *win, 
109                    HeadersFunc func,
110                    gpointer user_data);
111
112
113 static void     open_msg_func          (const GObject *obj, TnyMsg *msg, gpointer user_data);
114
115 static void     reply_forward_func     (const GObject *obj, TnyMsg *msg, gpointer user_data);
116
117 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
118
119 static gchar*   ask_for_folder_name    (GtkWindow *parent_window, const gchar *title);
120
121 void   
122 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
123 {
124         GtkWidget *about;
125         const gchar *authors[] = {
126                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
127                 NULL
128         };
129         about = gtk_about_dialog_new ();
130         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
131         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
132         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
133                                         _("Copyright (c) 2006, Nokia Corporation\n"
134                                           "All rights reserved."));
135         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
136                                        _("a modest e-mail client\n\n"
137                                          "design and implementation: Dirk-Jan C. Binnema\n"
138                                          "contributions from the fine people at KC and Ig\n"
139                                          "uses the tinymail email framework written by Philip van Hoof"));
140         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
141         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
142         
143         gtk_dialog_run (GTK_DIALOG (about));
144         gtk_widget_destroy(about);
145 }
146
147
148 static TnyList *
149 get_selected_headers (ModestWindow *win)
150 {
151         if (MODEST_IS_MAIN_WINDOW(win)) {
152                 GtkWidget *header_view;         
153                 
154                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
155                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
156                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
157                 
158         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
159                 /* for MsgViewWindows, we simply return a list with one element */
160                 TnyHeader *header;
161                 TnyList *list = NULL;
162                 
163                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));
164                 if (header != NULL) {
165                         list = tny_simple_list_new ();
166                         tny_list_prepend (list, G_OBJECT(header));
167                         g_object_unref (G_OBJECT(header));
168                 }
169
170                 return list;
171
172         } else
173                 return NULL;
174 }
175
176 static void
177 headers_action_mark_as_read (TnyHeader *header,
178                              ModestWindow *win,
179                              gpointer user_data)
180 {
181         TnyHeaderFlags flags;
182
183         g_return_if_fail (TNY_IS_HEADER(header));
184
185         flags = tny_header_get_flags (header);
186         if (flags & TNY_HEADER_FLAG_SEEN) return;
187         tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
188 }
189
190 static void
191 headers_action_mark_as_unread (TnyHeader *header,
192                                ModestWindow *win,
193                                gpointer user_data)
194 {
195         TnyHeaderFlags flags;
196
197         g_return_if_fail (TNY_IS_HEADER(header));
198
199         flags = tny_header_get_flags (header);
200         if (flags & TNY_HEADER_FLAG_SEEN)  {
201                 tny_header_unset_flags (header, TNY_HEADER_FLAG_SEEN);
202         }
203 }
204
205
206 static void
207 headers_action_delete (TnyHeader *header,
208                        ModestWindow *win,
209                        gpointer user_data)
210 {
211         ModestMailOperation *mail_op = NULL;
212
213         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_DELETE, G_OBJECT(win));
214         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
215                                          mail_op);
216         
217         /* Always delete. TODO: Move to trash still not supported */
218         modest_mail_operation_remove_msg (mail_op, header, FALSE);
219         g_object_unref (G_OBJECT (mail_op));
220 }
221
222 void
223 modest_ui_actions_on_delete (GtkAction *action, ModestWindow *win)
224 {
225         TnyList *header_list = NULL;
226         TnyIterator *iter = NULL;
227         TnyHeader *header = NULL;
228         gchar *message = NULL;
229         gchar *desc = NULL;
230         gint response;
231
232         g_return_if_fail (MODEST_IS_WINDOW(win));
233
234         header_list = get_selected_headers (win);
235         if (!header_list) return;
236
237         /* Select message */
238         if (tny_list_get_length(header_list) > 1)
239                 message = g_strdup(_("emev_nc_delete_messages"));
240         else {
241                 iter = tny_list_create_iterator (header_list);
242                 header = TNY_HEADER (tny_iterator_get_current (iter));
243                 desc = g_strdup_printf ("%s", tny_header_get_subject (header)); 
244                 message = g_strdup_printf(_("emev_nc_delete_message"), desc);
245         }
246
247         /* Confirmation dialog */               
248         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
249                                                             message);
250         
251
252         if (response == GTK_RESPONSE_OK) {
253                 if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
254                         gboolean ret_value;
255                         g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
256                         return;
257                 }
258                 
259                 /* Remove each header */
260                 do_headers_action (win, headers_action_delete, NULL);
261
262                 if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
263                         gtk_widget_destroy (GTK_WIDGET(win));
264                 } 
265         }
266
267         /* free */
268         g_free(message);
269         g_free(desc);
270         g_object_unref (header_list);
271         g_object_unref (iter);
272 }
273
274
275 void
276 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
277 {
278         #ifdef MODEST_PLATFORM_MAEMO
279         modest_osso_save_state();
280         #endif /* MODEST_PLATFORM_MAEMO */
281         
282         gtk_main_quit ();
283 }
284
285 void
286 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
287 {
288         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
289                 gtk_widget_destroy (GTK_WIDGET (win));
290         } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
291                 gboolean ret_value;
292                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
293         } else if (MODEST_IS_WINDOW (win)) {
294                 gtk_widget_destroy (GTK_WIDGET (win));
295         } else {
296                 g_return_if_reached ();
297         }
298 }
299
300 void
301 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
302 {
303         GtkClipboard *clipboard = NULL;
304         gchar *selection = NULL;
305
306         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
307         selection = gtk_clipboard_wait_for_text (clipboard);
308
309         modest_address_book_add_address (selection);
310         g_free (selection);
311 }
312
313 void
314 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
315 {
316         /* This is currently only implemented for Maemo,
317          * because it requires a providers preset file which is not publically available.
318          */
319 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
320         GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
321                                 TRUE /* enabled accounts only */);
322         gboolean accounts_exist = account_names != NULL;
323         g_slist_free (account_names);
324         
325         if (!accounts_exist) {
326                 /* If there are no accounts yet, just show the easy-setup wizard, as per the UI spec: */
327                 ModestEasysetupWizardDialog *wizard = modest_easysetup_wizard_dialog_new ();
328                 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
329                 gtk_dialog_run (GTK_DIALOG (wizard));
330                 gtk_widget_destroy (GTK_WIDGET (wizard));
331         } else  {
332                 /* Show the list of accounts: */
333                 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
334                 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW(win));
335                 gtk_dialog_run (account_win);
336                 gtk_widget_destroy (GTK_WIDGET(account_win));
337         }
338 #else
339         GtkWidget *dialog, *label;
340         
341         /* Create the widgets */
342         
343         dialog = gtk_dialog_new_with_buttons ("Message",
344                                               GTK_WINDOW(win),
345                                               GTK_DIALOG_DESTROY_WITH_PARENT,
346                                               GTK_STOCK_OK,
347                                               GTK_RESPONSE_NONE,
348                                               NULL);
349         label = gtk_label_new ("Hello World!");
350         
351         /* Ensure that the dialog box is destroyed when the user responds. */
352         
353         g_signal_connect_swapped (dialog, "response", 
354                                   G_CALLBACK (gtk_widget_destroy),
355                                   dialog);
356         
357         /* Add the label, and show everything we've added to the dialog. */
358         
359         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
360                            label);
361         gtk_widget_show_all (dialog);
362 #endif /* MODEST_PLATFORM_MAEMO */
363 }
364
365 static void
366 on_smtp_servers_window_hide (GtkWindow* window, gpointer user_data)
367 {
368         ModestWindow *main_window = MODEST_WINDOW (user_data);
369         
370         /* Save any changes. */
371         modest_connection_specific_smtp_window_save_server_accounts (
372                         MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (window), 
373                         modest_window_get_active_account (main_window));
374         gtk_widget_destroy (GTK_WIDGET (window));
375 }
376
377 void
378 modest_ui_actions_on_smtp_servers (GtkAction *action, ModestWindow *win)
379 {
380         /* This is currently only implemented for Maemo,
381          * because it requires an API (libconic) to detect different connection 
382          * possiblities.
383          */
384 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
385         
386         /* Create the window if necessary: */
387         GtkWidget *specific_window = GTK_WIDGET (modest_connection_specific_smtp_window_new ());
388         modest_connection_specific_smtp_window_fill_with_connections (
389                 MODEST_CONNECTION_SPECIFIC_SMTP_WINDOW (specific_window), 
390                 modest_runtime_get_account_mgr(), 
391                 modest_window_get_active_account (win));
392
393         /* Show the window: */  
394         gtk_window_set_transient_for (GTK_WINDOW (specific_window), GTK_WINDOW (win));
395         gtk_window_set_modal (GTK_WINDOW (specific_window), TRUE);
396     gtk_widget_show (specific_window);
397     
398     /* Save changes when the window is hidden: */
399         g_signal_connect (specific_window, "hide", 
400                 G_CALLBACK (on_smtp_servers_window_hide), win);
401 #endif /* MODEST_PLATFORM_MAEMO */
402 }
403
404 void
405 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
406 {
407         ModestWindow *msg_win;
408         TnyMsg *msg = NULL;
409         TnyFolder *folder = NULL;
410         gchar *account_name = NULL;
411         gchar *from_str = NULL;
412 /*      GError *err = NULL; */
413         TnyAccount *account = NULL;
414         ModestWindowMgr *mgr;
415         gchar *signature = NULL;
416         
417         account_name = g_strdup(modest_window_get_active_account (win));
418         if (!account_name)
419                 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
420         if (!account_name) {
421                 g_printerr ("modest: no account found\n");
422                 goto cleanup;
423         }
424         
425         account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
426                                                                        account_name,
427                                                                        TNY_ACCOUNT_TYPE_STORE);
428         if (!account) {
429                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
430                 goto cleanup;
431         }
432
433         from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
434         if (!from_str) {
435                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
436                 goto cleanup;
437         }
438
439         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr (), account_name,
440                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
441                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), account_name,
442                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
443         } else {
444                 signature = g_strdup ("");
445         }
446
447         msg = modest_tny_msg_new ("", from_str, "", "", "", signature, NULL);
448         if (!msg) {
449                 g_printerr ("modest: failed to create new msg\n");
450                 goto cleanup;
451         }
452         
453         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
454         if (!folder) {
455                 g_printerr ("modest: failed to find Drafts folder\n");
456                 goto cleanup;
457         }
458         
459 /*      tny_folder_add_msg (folder, msg, &err); */
460 /*      if (err) { */
461 /*              g_printerr ("modest: error adding msg to Drafts folder: %s", */
462 /*                          err->message); */
463 /*              g_error_free (err); */
464 /*              goto cleanup; */
465 /*      } */
466
467         /* Create and register edit window */
468         msg_win = modest_msg_edit_window_new (msg, account_name);
469         mgr = modest_runtime_get_window_mgr ();
470         modest_window_mgr_register_window (mgr, msg_win);
471
472         if (win)
473                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
474                                               GTK_WINDOW (win));        
475         gtk_widget_show_all (GTK_WIDGET (msg_win));
476
477 cleanup:
478         g_free (account_name);
479         g_free (from_str);
480         g_free (signature);
481         if (account)
482                 g_object_unref (G_OBJECT(account));
483         if (msg)
484                 g_object_unref (G_OBJECT(msg));
485         if (folder)
486                 g_object_unref (G_OBJECT(folder));
487 }
488
489 static void
490 headers_action_open (TnyHeader *header, 
491                      ModestWindow *win, 
492                      gpointer user_data)
493 {
494         modest_ui_actions_on_header_activated (MODEST_HEADER_VIEW (user_data), 
495                                                header,
496                                                MODEST_MAIN_WINDOW (win));
497 }
498
499 void
500 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
501 {
502         GtkWidget *header_view;
503
504         /* Get header view */
505         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
506                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
507
508         /* Open each message */
509         do_headers_action (win, headers_action_open, header_view);
510 }
511
512
513 static void
514 open_msg_func (const GObject *obj, TnyMsg *msg, gpointer user_data)
515 {
516         ModestWindowMgr *mgr = NULL;
517         ModestWindow *parent_win = NULL;
518         ModestWindow *win = NULL;
519         HeaderActivatedHelper *helper = NULL;
520         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
521         gchar *account = NULL;
522         
523         g_return_if_fail (MODEST_IS_WINDOW(obj));
524         g_return_if_fail (user_data != NULL);
525
526         /* TODO: Show an error? (review the specs) */
527         if (!msg)
528                 return;
529
530         parent_win = MODEST_WINDOW(obj);
531         helper = (HeaderActivatedHelper *) user_data;
532
533         /* Mark header as read */
534         headers_action_mark_as_read (helper->header, MODEST_WINDOW(parent_win), NULL);
535
536         /* Get account */
537         account =  g_strdup(modest_window_get_active_account(MODEST_WINDOW(parent_win)));
538         if (!account)
539                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
540         
541         /* Gets foldert type (OUTBOX headers will be opened in edit window */
542         if (modest_tny_folder_is_local_folder (helper->folder))
543                 folder_type = modest_tny_folder_get_local_folder_type (helper->folder);
544
545         switch (folder_type) {
546         case TNY_FOLDER_TYPE_DRAFTS:
547                 win = modest_msg_edit_window_new ((TnyMsg *) msg, account);
548                 break;
549         default:
550                 if (helper->model != NULL)
551                         win = modest_msg_view_window_new_with_header_model ((TnyMsg *) msg, account, helper->model, helper->row_reference);
552                 else
553                         win = modest_msg_view_window_new ((TnyMsg *) msg, account);
554         }
555         
556         /* Register and show new window */
557         if (win != NULL) {
558                 mgr = modest_runtime_get_window_mgr ();
559                 modest_window_mgr_register_window (mgr, win);
560                 gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent_win));
561                 gtk_widget_show_all (GTK_WIDGET(win));
562         }
563
564         /* Free */
565         g_free(account);
566 /*      g_object_unref (G_OBJECT(msg)); */
567         g_object_unref (G_OBJECT(helper->folder));
568         g_object_unref (G_OBJECT(helper->header));
569         gtk_tree_row_reference_free (helper->row_reference);
570         g_slice_free (HeaderActivatedHelper, helper);
571 }
572
573 static void
574 free_reply_forward_helper (gpointer data)
575 {
576         ReplyForwardHelper *helper;
577
578         helper = (ReplyForwardHelper *) data;
579         g_free (helper->account_name);
580         g_slice_free (ReplyForwardHelper, helper);
581 }
582
583 static void
584 reply_forward_func (const GObject *obj, TnyMsg *msg, gpointer user_data)
585 {
586         TnyMsg *new_msg;
587         ReplyForwardHelper *rf_helper;
588         ModestWindow *msg_win;
589         ModestEditType edit_type;
590         gchar *from;
591         GError *err = NULL;
592         TnyFolder *folder = NULL;
593         TnyAccount *account = NULL;
594         ModestWindowMgr *mgr;
595         gchar *signature = NULL;
596                         
597         g_return_if_fail (user_data != NULL);
598         rf_helper = (ReplyForwardHelper *) user_data;
599
600         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
601                                                    rf_helper->account_name);
602         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
603                                          rf_helper->account_name,
604                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
605                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
606                                                            rf_helper->account_name,
607                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
608         }
609
610         /* Create reply mail */
611         switch (rf_helper->action) {
612         case ACTION_REPLY:
613                 new_msg = 
614                         modest_tny_msg_create_reply_msg ((TnyMsg *) msg,  from, signature,
615                                                          rf_helper->reply_forward_type,
616                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
617                 break;
618         case ACTION_REPLY_TO_ALL:
619                 new_msg = 
620                         modest_tny_msg_create_reply_msg ((TnyMsg *) msg, from, signature, rf_helper->reply_forward_type,
621                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
622                 edit_type = MODEST_EDIT_TYPE_REPLY;
623                 break;
624         case ACTION_FORWARD:
625                 new_msg = 
626                         modest_tny_msg_create_forward_msg ((TnyMsg *) msg, from, signature, rf_helper->reply_forward_type);
627                 edit_type = MODEST_EDIT_TYPE_FORWARD;
628                 break;
629         default:
630                 g_return_if_reached ();
631                 return;
632         }
633
634         g_free (signature);
635
636         if (!new_msg) {
637                 g_printerr ("modest: failed to create message\n");
638                 goto cleanup;
639         }
640
641         account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
642                                                                        rf_helper->account_name,
643                                                                        TNY_ACCOUNT_TYPE_STORE);
644         if (!account) {
645                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
646                 goto cleanup;
647         }
648
649         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
650         if (!folder) {
651                 g_printerr ("modest: failed to find Drafts folder\n");
652                 goto cleanup;
653         }
654         
655         tny_folder_add_msg (folder, (TnyMsg *) msg, &err);
656         g_object_unref (msg);
657         if (err) {
658                 g_printerr ("modest: error adding msg to Drafts folder: %s",
659                             err->message);
660                 g_error_free (err);
661                 goto cleanup;
662         }       
663
664         /* Create and register the windows */                   
665         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
666         mgr = modest_runtime_get_window_mgr ();
667         modest_window_mgr_register_window (mgr, msg_win);
668
669         /* Show edit window */
670         gtk_widget_show_all (GTK_WIDGET (msg_win));
671
672 cleanup:
673         if (new_msg)
674                 g_object_unref (G_OBJECT (new_msg));
675         if (folder)
676                 g_object_unref (G_OBJECT (folder));
677         if (account)
678                 g_object_unref (G_OBJECT (account));    
679 }
680
681 /*
682  * Common code for the reply and forward actions
683  */
684 static void
685 reply_forward (ReplyForwardAction action, ModestWindow *win)
686 {
687         ModestMailOperation *mail_op = NULL;
688         TnyList *header_list = NULL;
689         ReplyForwardHelper *rf_helper = NULL;
690         guint reply_forward_type;
691         
692         g_return_if_fail (MODEST_IS_WINDOW(win));
693
694         header_list = get_selected_headers (win);
695         if (!header_list)
696                 return;
697         
698         reply_forward_type = modest_conf_get_int (modest_runtime_get_conf (),
699                                                   (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
700                                                   NULL);
701         /* We assume that we can only select messages of the
702            same folder and that we reply all of them from the
703            same account. In fact the interface currently only
704            allows single selection */
705         
706         /* Fill helpers */
707         rf_helper = g_slice_new0 (ReplyForwardHelper);
708         rf_helper->reply_forward_type = reply_forward_type;
709         rf_helper->action = action;
710         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
711         if (!rf_helper->account_name)
712                 rf_helper->account_name =
713                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
714
715         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
716                 TnyMsg *msg;
717                 msg = modest_msg_view_window_get_message(MODEST_MSG_VIEW_WINDOW(win));
718                 if (!msg) {
719                         g_printerr ("modest: no message found\n");
720                         return;
721                 } else
722                         reply_forward_func (G_OBJECT(win), g_object_ref (msg), rf_helper);
723         } else {
724                 /* Retrieve messages */
725                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
726                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
727                 modest_mail_operation_get_msgs_full (mail_op, 
728                                                      header_list, 
729                                                      reply_forward_func, 
730                                                      rf_helper, 
731                                                      free_reply_forward_helper);
732
733                 /* Clean */
734                 g_object_unref(mail_op);
735         }
736 }
737
738 void
739 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
740 {
741         g_return_if_fail (MODEST_IS_WINDOW(win));
742
743         reply_forward (ACTION_REPLY, win);
744 }
745
746 void
747 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
748 {
749         g_return_if_fail (MODEST_IS_WINDOW(win));
750
751         reply_forward (ACTION_FORWARD, win);
752 }
753
754 void
755 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
756 {
757         g_return_if_fail (MODEST_IS_WINDOW(win));
758
759         reply_forward (ACTION_REPLY_TO_ALL, win);
760 }
761
762 void 
763 modest_ui_actions_on_next (GtkAction *action, 
764                            ModestWindow *window)
765 {
766         if (MODEST_IS_MAIN_WINDOW (window)) {
767                 GtkWidget *header_view;
768
769                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
770                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
771                 if (!header_view)
772                         return;
773         
774                 modest_header_view_select_next (MODEST_HEADER_VIEW(header_view)); 
775         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
776                 modest_msg_view_window_select_next_message (MODEST_MSG_VIEW_WINDOW (window));
777         } else {
778                 g_return_if_reached ();
779         }
780 }
781
782 void 
783 modest_ui_actions_on_prev (GtkAction *action, 
784                            ModestWindow *window)
785 {
786         g_return_if_fail (MODEST_IS_WINDOW(window));
787
788         if (MODEST_IS_MAIN_WINDOW (window)) {
789                 GtkWidget *header_view;
790                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
791                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
792                 if (!header_view)
793                         return;
794                 
795                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
796         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
797                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
798         } else {
799                 g_return_if_reached ();
800         }
801 }
802
803 void 
804 modest_ui_actions_on_sort (GtkAction *action, 
805                            ModestWindow *window)
806 {
807         g_return_if_fail (MODEST_IS_WINDOW(window));
808
809         if (MODEST_IS_MAIN_WINDOW (window)) {
810                 GtkWidget *header_view;
811                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
812                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
813                 if (!header_view)
814                         return;
815
816                 /* Show sorting dialog */
817                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
818         }
819 }
820
821 /** Check that an appropriate connection is open.
822  */
823 gboolean check_for_connection (const gchar *account_name)
824 {
825         TnyDevice *device = modest_runtime_get_device ();
826
827 /*
828         g_assert (TNY_IS_MAEMO_CONIC_DEVICE (device));
829         
830         TnyMaemoConicDevice *maemo_device = TNY_MAEMO_CONIC_DEVICE (device);
831 */
832         
833         if (tny_device_is_online (device))
834                 return TRUE;
835         else {
836                 modest_platform_connect_and_wait (NULL);
837                 
838                 /* TODO: Wait until a result. */
839                 return TRUE;
840         }
841 }
842
843 /*
844  * This function performs the send & receive required actions. The
845  * window it's used to create the mail operation. Tipically it should
846  * be allways the main window, but we pass it as argument in order to
847  * be more flexible.
848  */
849 void
850 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
851 {
852         gchar *acc_name = NULL;
853
854         /* If no account name was provided get the current account, if
855            there is none either then pick the default one */
856         if (!account_name) {
857                 acc_name = g_strdup (modest_window_get_active_account(win));
858                 if (!acc_name)
859                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
860                 if (!acc_name) {
861                         g_printerr ("modest: cannot get default account\n");
862                         return;
863                 }
864         } else {
865                 acc_name = g_strdup (account_name);
866         }
867
868         /* Send & receive. Do not continue if no suitable connection
869            is open */
870         if (check_for_connection (acc_name)) {
871                 /* As per the UI spec,
872                  * for POP accounts, we should receive,
873                  * for IMAP we should synchronize everything, including receiving,
874                  * for SMTP we should send,
875                  * first receiving, then sending:
876                  */
877                 /* Create the mail operation */
878                 /* TODO: The spec wants us to first do any pending deletions, before receiving. */
879                 ModestMailOperation *mail_op;
880                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
881                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
882                 modest_mail_operation_update_account (mail_op, acc_name);
883                 g_object_unref (G_OBJECT (mail_op));
884         }
885         /* Free */
886         g_free (acc_name);
887 }
888
889 /*
890  * Refreshes all accounts. This function will be used by automatic
891  * updates
892  */
893 void
894 modest_ui_actions_do_send_receive_all (ModestWindow *win)
895 {
896         GSList *account_names, *iter;
897
898         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
899                                                           TRUE);
900
901         iter = account_names;
902         while (iter) {                  
903                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
904                 iter = g_slist_next (iter);
905         }
906         
907         g_slist_foreach (account_names, (GFunc) g_free, NULL);
908         g_slist_free (account_names);
909 }
910
911 /*
912  * Handler of the click on Send&Receive button in the main toolbar
913  */
914 void
915 modest_ui_actions_on_send_receive (GtkAction *action,  ModestWindow *win)
916 {
917         /* Check that at least one account exists: */
918         GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
919                                 TRUE /* enabled accounts only */);
920         gboolean accounts_exist = account_names != NULL;
921         g_slist_free (account_names);
922         
923         /* If not, allow the user to create an account before trying to send/receive. */
924         if (!accounts_exist)
925                 modest_ui_actions_on_accounts (NULL, win);
926         
927         /* Refresh the active account */
928         modest_ui_actions_do_send_receive (NULL, win);
929 }
930
931
932 void
933 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
934 {
935         ModestConf *conf;
936         GtkWidget *header_view;
937         
938         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
939
940         header_view = modest_main_window_get_child_widget (main_window,
941                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
942         if (!header_view)
943                 return;
944
945         conf = modest_runtime_get_conf ();
946         
947         /* what is saved/restored is depending on the style; thus; we save with
948          * old style, then update the style, and restore for this new style
949          */
950         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
951         
952         if (modest_header_view_get_style
953             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
954                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
955                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
956         else
957                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
958                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
959
960         modest_widget_memory_restore (conf, G_OBJECT(header_view),
961                                       MODEST_CONF_HEADER_VIEW_KEY);
962 }
963
964
965 void 
966 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
967                                       TnyHeader *header,
968                                       ModestMainWindow *main_window)
969 {
970         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
971
972         /* If no header has been selected then exit */
973         if (!header)
974                 return;
975
976         /* Update Main window title */
977         if (GTK_WIDGET_HAS_FOCUS (header_view)) {
978                 const gchar *subject = tny_header_get_subject (header);
979                 if (subject && strcmp (subject, ""))
980                         gtk_window_set_title (GTK_WINDOW (main_window), subject);
981                 else
982                         gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
983         }
984 }
985
986 void
987 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
988                                        TnyHeader *header,
989                                        ModestMainWindow *main_window)
990 {
991         ModestMailOperation *mail_op = NULL;
992         HeaderActivatedHelper *helper = NULL;
993         ModestWindowMgr *mgr = NULL;
994         ModestWindow *win = NULL;
995         GtkTreeModel *model = NULL;
996         GtkTreeSelection *sel = NULL;
997         GList *sel_list = NULL;
998         
999         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1000         
1001         if (!header)
1002                 return;
1003
1004         /* Look if we already have a message view for that header */
1005         mgr = modest_runtime_get_window_mgr ();
1006         win = modest_window_mgr_find_window_by_msguid (mgr, tny_header_get_uid (header));
1007         if (win) return;
1008
1009         /* Build helper */
1010         helper = g_slice_new0 (HeaderActivatedHelper);
1011         helper->folder = tny_header_get_folder (header);
1012         helper->header = g_object_ref(header);
1013         helper->model = NULL;
1014
1015         /* Get headers tree model and selected row reference to build message view */
1016         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
1017         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
1018         if (sel_list != NULL) {
1019                 
1020                 /* Fill helpers */
1021                 helper->model = model;
1022                 helper->row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
1023
1024                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
1025                 g_list_free (sel_list);
1026         }
1027
1028         /* New mail operation */
1029         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(main_window));
1030         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1031         modest_mail_operation_get_msg (mail_op, header, open_msg_func, helper);
1032
1033         /* Free */
1034         g_object_unref (mail_op);
1035 }
1036
1037 static void
1038 set_active_account_from_tny_account (TnyAccount *account,
1039                                      ModestWindow *window)
1040 {
1041         TnyAccount *modest_server_account;
1042         const gchar *server_acc_name;
1043         gchar *modest_acc_name;
1044
1045         server_acc_name = tny_account_get_id (account);
1046         /* We need the TnyAccount provided by the
1047            account store because that is the one that
1048            knows the name of the Modest account */
1049         modest_server_account = 
1050                 modest_tny_account_store_get_tny_account_by_id  (modest_runtime_get_account_store (), 
1051                                                                  server_acc_name);
1052         modest_acc_name = (gchar *) g_object_get_data (G_OBJECT (modest_server_account), "modest_account");
1053         modest_window_set_active_account (window, modest_acc_name);
1054         g_object_unref (modest_server_account);
1055 }
1056
1057 void 
1058 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1059                                                TnyFolderStore *folder_store, 
1060                                                gboolean selected,
1061                                                ModestMainWindow *main_window)
1062 {
1063         ModestConf *conf;
1064         GtkWidget *header_view;
1065         TnyAccount *account;
1066         
1067         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1068
1069         header_view = modest_main_window_get_child_widget(main_window,
1070                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
1071         if (!header_view)
1072                 return;
1073         
1074         conf = modest_runtime_get_conf ();
1075
1076         if (TNY_IS_FOLDER (folder_store)) {
1077
1078                 if (selected) {
1079                         /* Update the active account */
1080                         account = tny_folder_get_account (TNY_FOLDER (folder_store));
1081                         set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1082                         g_object_unref (account);
1083
1084                         /* Set folder on header view */
1085                         modest_main_window_set_contents_style (main_window, 
1086                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1087                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1088                                                        TNY_FOLDER (folder_store));
1089                         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1090                                                       MODEST_CONF_HEADER_VIEW_KEY);
1091                 } else {
1092                         /* Update the active account */
1093                         modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
1094                         /* Do not show folder */
1095                         modest_widget_memory_save (conf, G_OBJECT (header_view), MODEST_CONF_HEADER_VIEW_KEY);
1096                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
1097                 }
1098         } else if (TNY_IS_ACCOUNT (folder_store)) {
1099                 /* Update active account */
1100                 set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1101                 /* Show account details */
1102                 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1103         }
1104 }
1105
1106 void 
1107 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1108                                      ModestWindow *win)
1109 {
1110         GtkWidget *dialog;
1111         gchar *txt, *item;
1112         gboolean online;
1113
1114         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1115         
1116         if (g_main_depth > 0)   
1117                 gdk_threads_enter ();
1118         online = tny_device_is_online (modest_runtime_get_device());
1119
1120         if (online) {
1121                 /* already online -- the item is simply not there... */
1122                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1123                                                  GTK_DIALOG_MODAL,
1124                                                  GTK_MESSAGE_WARNING,
1125                                                  GTK_BUTTONS_OK,
1126                                                  _("The %s you selected cannot be found"),
1127                                                  item);
1128                 gtk_dialog_run (GTK_DIALOG(dialog));
1129         } else {
1130                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1131                                                       GTK_WINDOW (win),
1132                                                       GTK_DIALOG_MODAL,
1133                                                       GTK_STOCK_CANCEL,
1134                                                       GTK_RESPONSE_REJECT,
1135                                                       GTK_STOCK_OK,
1136                                                       GTK_RESPONSE_ACCEPT,
1137                                                       NULL);
1138                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1139                                          "Do you want to get online?"), item);
1140                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1141                                     gtk_label_new (txt), FALSE, FALSE, 0);
1142                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1143                 g_free (txt);
1144
1145                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1146                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1147 //                      modest_platform_connect_and_wait ();;
1148                 }
1149         }
1150         gtk_widget_destroy (dialog);
1151         if (g_main_depth > 0)   
1152                 gdk_threads_leave ();
1153 }
1154
1155 void
1156 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1157                                      ModestWindow *win)
1158 {
1159         /* g_message ("%s %s", __FUNCTION__, link); */
1160 }       
1161
1162
1163 void
1164 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1165                                         ModestWindow *win)
1166 {
1167         modest_platform_activate_uri (link);
1168 }
1169
1170 void
1171 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1172                                           ModestWindow *win)
1173 {
1174         modest_platform_show_uri_popup (link);
1175 }
1176
1177 void
1178 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1179                                              ModestWindow *win)
1180 {
1181         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
1182 }
1183
1184 void
1185 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1186                                           const gchar *address,
1187                                           ModestWindow *win)
1188 {
1189         /* g_message ("%s %s", __FUNCTION__, address); */
1190 }
1191
1192 void
1193 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1194 {
1195         TnyTransportAccount *transport_account;
1196         ModestMailOperation *mail_operation;
1197         MsgData *data;
1198         gchar *account_name, *from;
1199         ModestAccountMgr *account_mgr;
1200
1201         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1202         
1203         data = modest_msg_edit_window_get_msg_data (edit_window);
1204
1205         account_mgr = modest_runtime_get_account_mgr();
1206         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1207         if (!account_name) 
1208                 account_name = modest_account_mgr_get_default_account (account_mgr);
1209         if (!account_name) {
1210                 g_printerr ("modest: no account found\n");
1211                 modest_msg_edit_window_free_msg_data (edit_window, data);
1212                 return;
1213         }
1214         transport_account =
1215                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
1216                                       (modest_runtime_get_account_store(),
1217                                        account_name,
1218                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1219         if (!transport_account) {
1220                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1221                 g_free (account_name);
1222                 modest_msg_edit_window_free_msg_data (edit_window, data);
1223                 return;
1224         }
1225         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1226
1227         /* Create the mail operation */         
1228         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO, G_OBJECT(edit_window));
1229         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1230
1231         modest_mail_operation_save_to_drafts (mail_operation,
1232                                               transport_account,
1233                                               from,
1234                                               data->to, 
1235                                               data->cc, 
1236                                               data->bcc,
1237                                               data->subject, 
1238                                               data->plain_body, 
1239                                               data->html_body,
1240                                               data->attachments,
1241                                               data->priority_flags);
1242         /* Frees */
1243         g_free (from);
1244         g_free (account_name);
1245         g_object_unref (G_OBJECT (transport_account));
1246         g_object_unref (G_OBJECT (mail_operation));
1247
1248         modest_msg_edit_window_free_msg_data (edit_window, data);
1249
1250         /* Save settings and close the window */
1251         gtk_widget_destroy (GTK_WIDGET (edit_window));
1252 }
1253 void
1254 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1255 {
1256         TnyTransportAccount *transport_account;
1257         ModestMailOperation *mail_operation;
1258         MsgData *data;
1259         gchar *account_name, *from;
1260         ModestAccountMgr *account_mgr;
1261
1262         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1263
1264         if (!modest_msg_edit_window_check_names (edit_window))
1265                 return;
1266         
1267         data = modest_msg_edit_window_get_msg_data (edit_window);
1268
1269         /* FIXME: Code added just for testing. The final version will
1270            use the send queue provided by tinymail and some
1271            classifier */
1272         account_mgr = modest_runtime_get_account_mgr();
1273         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1274         if (!account_name) 
1275                 account_name = modest_account_mgr_get_default_account (account_mgr);
1276         if (!account_name) {
1277                 g_printerr ("modest: no account found\n");
1278                 modest_msg_edit_window_free_msg_data (edit_window, data);
1279                 return;
1280         }
1281         transport_account =
1282                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
1283                                       (modest_runtime_get_account_store(),
1284                                        account_name));
1285         if (!transport_account) {
1286                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1287                 g_free (account_name);
1288                 modest_msg_edit_window_free_msg_data (edit_window, data);
1289                 return;
1290         }
1291         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1292
1293         /* Create the mail operation */         
1294         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_SEND, G_OBJECT(edit_window));
1295         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1296
1297         modest_mail_operation_send_new_mail (mail_operation,
1298                                              transport_account,
1299                                              from,
1300                                              data->to, 
1301                                              data->cc, 
1302                                              data->bcc,
1303                                              data->subject, 
1304                                              data->plain_body, 
1305                                              data->html_body,
1306                                              data->attachments,
1307                                              data->priority_flags);
1308         /* Frees */
1309         g_free (from);
1310         g_free (account_name);
1311         g_object_unref (G_OBJECT (transport_account));
1312         g_object_unref (G_OBJECT (mail_operation));
1313
1314         modest_msg_edit_window_free_msg_data (edit_window, data);
1315
1316         /* Save settings and close the window */
1317         gtk_widget_destroy (GTK_WIDGET (edit_window));
1318 }
1319
1320 void 
1321 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1322                                   ModestMsgEditWindow *window)
1323 {
1324         ModestMsgEditFormatState *format_state = NULL;
1325
1326         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1327         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1328
1329         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1330                 return;
1331
1332         format_state = modest_msg_edit_window_get_format_state (window);
1333         g_return_if_fail (format_state != NULL);
1334
1335         format_state->bold = gtk_toggle_action_get_active (action);
1336         modest_msg_edit_window_set_format_state (window, format_state);
1337         g_free (format_state);
1338         
1339 }
1340
1341 void 
1342 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1343                                      ModestMsgEditWindow *window)
1344 {
1345         ModestMsgEditFormatState *format_state = NULL;
1346
1347         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1348         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1349
1350         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1351                 return;
1352
1353         format_state = modest_msg_edit_window_get_format_state (window);
1354         g_return_if_fail (format_state != NULL);
1355
1356         format_state->italics = gtk_toggle_action_get_active (action);
1357         modest_msg_edit_window_set_format_state (window, format_state);
1358         g_free (format_state);
1359         
1360 }
1361
1362 void 
1363 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
1364                                      ModestMsgEditWindow *window)
1365 {
1366         ModestMsgEditFormatState *format_state = NULL;
1367
1368         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1369         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1370
1371         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1372                 return;
1373
1374         format_state = modest_msg_edit_window_get_format_state (window);
1375         g_return_if_fail (format_state != NULL);
1376
1377         format_state->bullet = gtk_toggle_action_get_active (action);
1378         modest_msg_edit_window_set_format_state (window, format_state);
1379         g_free (format_state);
1380         
1381 }
1382
1383 void 
1384 modest_ui_actions_on_change_justify (GtkRadioAction *action,
1385                                      GtkRadioAction *selected,
1386                                      ModestMsgEditWindow *window)
1387 {
1388         ModestMsgEditFormatState *format_state = NULL;
1389         GtkJustification value;
1390
1391         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1392
1393         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1394                 return;
1395
1396         value = gtk_radio_action_get_current_value (selected);
1397
1398         format_state = modest_msg_edit_window_get_format_state (window);
1399         g_return_if_fail (format_state != NULL);
1400
1401         format_state->justification = value;
1402         modest_msg_edit_window_set_format_state (window, format_state);
1403         g_free (format_state);
1404 }
1405
1406 void 
1407 modest_ui_actions_on_select_editor_color (GtkAction *action,
1408                                           ModestMsgEditWindow *window)
1409 {
1410         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1411         g_return_if_fail (GTK_IS_ACTION (action));
1412
1413         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1414                 return;
1415
1416         modest_msg_edit_window_select_color (window);
1417 }
1418
1419 void 
1420 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
1421                                                      ModestMsgEditWindow *window)
1422 {
1423         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1424         g_return_if_fail (GTK_IS_ACTION (action));
1425
1426         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1427                 return;
1428
1429         modest_msg_edit_window_select_background_color (window);
1430 }
1431
1432 void 
1433 modest_ui_actions_on_insert_image (GtkAction *action,
1434                                    ModestMsgEditWindow *window)
1435 {
1436         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1437         g_return_if_fail (GTK_IS_ACTION (action));
1438
1439         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1440                 return;
1441
1442         modest_msg_edit_window_insert_image (window);
1443 }
1444
1445 void 
1446 modest_ui_actions_on_attach_file (GtkAction *action,
1447                                   ModestMsgEditWindow *window)
1448 {
1449         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1450         g_return_if_fail (GTK_IS_ACTION (action));
1451
1452         modest_msg_edit_window_attach_file (window);
1453 }
1454
1455 void 
1456 modest_ui_actions_on_remove_attachments (GtkAction *action,
1457                                          ModestMsgEditWindow *window)
1458 {
1459         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1460         g_return_if_fail (GTK_IS_ACTION (action));
1461
1462         modest_msg_edit_window_remove_attachments (window, NULL);
1463 }
1464
1465 /*
1466  * Shows a dialog with an entry that asks for some text. The returned
1467  * value must be freed by the caller. The dialog window title will be
1468  * set to @title.
1469  */
1470 static gchar *
1471 ask_for_folder_name (GtkWindow *parent_window,
1472                      const gchar *title)
1473 {
1474         GtkWidget *dialog, *entry;
1475         gchar *folder_name = NULL;
1476
1477         /* Ask for folder name */
1478         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1479                                               parent_window,
1480                                               GTK_DIALOG_MODAL,
1481                                               GTK_STOCK_CANCEL,
1482                                               GTK_RESPONSE_REJECT,
1483                                               GTK_STOCK_OK,
1484                                               GTK_RESPONSE_ACCEPT,
1485                                               NULL);
1486         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1487                             gtk_label_new(title),
1488                             FALSE, FALSE, 0);
1489                 
1490         entry = gtk_entry_new_with_max_length (40);
1491         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1492                             entry,
1493                             TRUE, FALSE, 0);    
1494         
1495         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1496         
1497         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
1498                 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1499
1500         gtk_widget_destroy (dialog);
1501
1502         return folder_name;
1503 }
1504
1505 void 
1506 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1507 {
1508         TnyFolderStore *parent_folder;
1509         GtkWidget *folder_view;
1510         
1511         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1512
1513         folder_view = modest_main_window_get_child_widget (main_window,
1514                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1515         if (!folder_view)
1516                 return;
1517
1518         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1519         
1520         if (parent_folder) {
1521                 gboolean finished = FALSE;
1522                 gint result;
1523                 gchar *folder_name = NULL, *suggested_name = NULL;
1524
1525                 /* Run the new folder dialog */
1526                 while (!finished) {
1527                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (main_window),
1528                                                                         parent_folder,
1529                                                                         suggested_name,
1530                                                                         &folder_name);
1531
1532                         if (result == GTK_RESPONSE_REJECT) {
1533                                 finished = TRUE;
1534                         } else {
1535                                 ModestMailOperation *mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO, G_OBJECT(main_window));
1536                                 TnyFolder *new_folder = NULL;
1537
1538                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
1539                                                                  mail_op);
1540                 
1541                                 new_folder = modest_mail_operation_create_folder (mail_op,
1542                                                                                   parent_folder,
1543                                                                                   (const gchar *) folder_name);
1544                                 if (new_folder) {
1545                                         g_object_unref (new_folder);
1546                                         finished = TRUE;
1547                                 } 
1548 /*                              else { */
1549 /*                                      /\* TODO: check error and follow proper actions *\/ */
1550 /* /\*                                  suggested_name = X; *\/ */
1551 /*                                      /\* Show error to the user *\/ */
1552 /*                                      modest_platform_run_information_dialog (GTK_WINDOW (main_window), */
1553 /*                                                                              _("mail_in_ui_folder_create_error")); */
1554 /*                              } */
1555                                 g_object_unref (mail_op);
1556                         }
1557                         g_free (folder_name);
1558                         folder_name = NULL;
1559                 }
1560
1561                 g_object_unref (parent_folder);
1562         }
1563 }
1564
1565 void 
1566 modest_ui_actions_on_rename_folder (GtkAction *action,
1567                                      ModestMainWindow *main_window)
1568 {
1569         TnyFolderStore *folder;
1570         GtkWidget *folder_view;
1571         GtkWidget *header_view; 
1572
1573         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1574
1575         folder_view = modest_main_window_get_child_widget (main_window,
1576                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1577         if (!folder_view)
1578                 return;
1579
1580         header_view = modest_main_window_get_child_widget (main_window,
1581                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1582         
1583         if (!header_view)
1584                 return;
1585
1586         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1587         
1588         if (folder && TNY_IS_FOLDER (folder)) {
1589                 gchar *folder_name;
1590                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1591                                                    _("Please enter a new name for the folder"));
1592
1593                 if (folder_name != NULL && strlen (folder_name) > 0) {
1594                         ModestMailOperation *mail_op;
1595
1596                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO, G_OBJECT(main_window));
1597                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1598                                                          mail_op);
1599
1600                         modest_header_view_set_folder (MODEST_HEADER_VIEW (header_view), NULL);
1601
1602                         modest_mail_operation_rename_folder (mail_op,
1603                                                              TNY_FOLDER (folder),
1604                                                              (const gchar *) folder_name);
1605
1606                         g_object_unref (mail_op);
1607                         g_free (folder_name);
1608                 }
1609                 g_object_unref (folder);
1610         }
1611 }
1612
1613 static void
1614 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
1615 {
1616         TnyFolderStore *folder;
1617         GtkWidget *folder_view;
1618         gint response;
1619         gchar *message;
1620         
1621         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1622
1623         folder_view = modest_main_window_get_child_widget (main_window,
1624                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1625         if (!folder_view)
1626                 return;
1627
1628         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1629
1630         /* Show an error if it's an account */
1631         if (!TNY_IS_FOLDER (folder)) {
1632                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
1633                                                         _("mail_in_ui_folder_delete_error"));
1634                 return ;
1635         }
1636
1637         /* Ask the user */      
1638         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
1639                                     tny_folder_get_name (TNY_FOLDER (folder)));
1640         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window), 
1641                                                             (const gchar *) message);
1642         g_free (message);
1643
1644         if (response == GTK_RESPONSE_OK) {
1645                 ModestMailOperation *mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_DELETE, G_OBJECT(main_window));
1646
1647                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1648                                                  mail_op);
1649                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
1650
1651                 /* Show error if happened */
1652                 if (modest_mail_operation_get_error (mail_op))
1653                         modest_platform_run_information_dialog (GTK_WINDOW (main_window),
1654                                                                 _("mail_in_ui_folder_delete_error"));
1655
1656                 g_object_unref (G_OBJECT (mail_op));
1657         }
1658
1659         g_object_unref (G_OBJECT (folder));
1660 }
1661
1662 void 
1663 modest_ui_actions_on_delete_folder (GtkAction *action,
1664                                      ModestMainWindow *main_window)
1665 {
1666         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1667
1668         delete_folder (main_window, FALSE);
1669 }
1670
1671 void 
1672 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1673 {
1674         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1675         
1676         delete_folder (main_window, TRUE);
1677 }
1678
1679 void
1680 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
1681                                          const gchar* server_account_name,
1682                                          gchar **username,
1683                                          gchar **password, 
1684                                          gboolean *cancel, 
1685                                          gboolean *remember,
1686                                          ModestMainWindow *main_window)
1687 {
1688         g_return_if_fail(server_account_name);
1689         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
1690         
1691 #ifdef MODEST_PLATFORM_MAEMO
1692         /* Maemo uses a different (awkward) button order,
1693          * It should probably just use gtk_alternative_dialog_button_order ().
1694          */
1695         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
1696                                               NULL,
1697                                               GTK_DIALOG_MODAL,
1698                                               GTK_STOCK_OK,
1699                                               GTK_RESPONSE_ACCEPT,
1700                                               GTK_STOCK_CANCEL,
1701                                               GTK_RESPONSE_REJECT,
1702                                               NULL);
1703 #else
1704         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
1705                                               NULL,
1706                                               GTK_DIALOG_MODAL,
1707                                               GTK_STOCK_CANCEL,
1708                                               GTK_RESPONSE_REJECT,
1709                                               GTK_STOCK_OK,
1710                                               GTK_RESPONSE_ACCEPT,
1711                                               NULL);
1712 #endif /* MODEST_PLATFORM_MAEMO */
1713
1714         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1715         
1716         gchar *server_name = modest_server_account_get_hostname (
1717                 modest_runtime_get_account_mgr(), server_account_name);
1718         
1719         /* This causes a warning because the logical ID has no %s in it, 
1720          * though the translation does, but there is not much we can do about that: */
1721         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
1722         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1723                             FALSE, FALSE, 0);
1724         g_free (txt);
1725         g_free (server_name);
1726         server_name = NULL;
1727
1728         /* username: */
1729         gchar *initial_username = modest_server_account_get_username (
1730                 modest_runtime_get_account_mgr(), server_account_name);
1731         
1732         GtkWidget *entry_username = gtk_entry_new ();
1733         if (initial_username)
1734                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
1735         /* Dim this if a connection has ever succeeded with this username,
1736          * as per the UI spec: */
1737         const gboolean username_known = 
1738                 modest_server_account_get_username_has_succeeded(
1739                         modest_runtime_get_account_mgr(), server_account_name);
1740         gtk_widget_set_sensitive (entry_username, !username_known);
1741         
1742 #ifdef MODEST_PLATFORM_MAEMO
1743         /* Auto-capitalization is the default, so let's turn it off: */
1744         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
1745         
1746         /* Create a size group to be used by all captions.
1747          * Note that HildonCaption does not create a default size group if we do not specify one.
1748          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
1749         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
1750         
1751         GtkWidget *caption = hildon_caption_new (sizegroup, 
1752                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
1753         gtk_widget_show (entry_username);
1754         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
1755                 FALSE, FALSE, MODEST_MARGIN_HALF);
1756         gtk_widget_show (caption);
1757 #else 
1758         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
1759                             TRUE, FALSE, 0);
1760 #endif /* MODEST_PLATFORM_MAEMO */      
1761                             
1762         /* password: */
1763         GtkWidget *entry_password = gtk_entry_new ();
1764         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
1765         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
1766         
1767 #ifdef MODEST_PLATFORM_MAEMO
1768         /* Auto-capitalization is the default, so let's turn it off: */
1769         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
1770                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
1771         
1772         caption = hildon_caption_new (sizegroup, 
1773                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
1774         gtk_widget_show (entry_password);
1775         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
1776                 FALSE, FALSE, MODEST_MARGIN_HALF);
1777         gtk_widget_show (caption);
1778         g_object_unref (sizegroup);
1779 #else 
1780         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
1781                             TRUE, FALSE, 0);
1782 #endif /* MODEST_PLATFORM_MAEMO */      
1783                                 
1784 /* This is not in the Maemo UI spec:
1785         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1786         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1787                             TRUE, FALSE, 0);
1788 */
1789
1790         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1791         
1792         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1793                 if (username) {
1794                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
1795                         
1796                         modest_server_account_set_username (
1797                                  modest_runtime_get_account_mgr(), server_account_name, 
1798                                  *username);
1799                                  
1800                         const gboolean username_was_changed = 
1801                                 (strcmp (*username, initial_username) != 0);
1802                         if (username_was_changed) {
1803                                 /* To actually use a changed username, 
1804                                  * we must reset the connection, according to pvanhoof.
1805                                  * This _might_ be a sensible way to do that: */
1806                                  TnyDevice *device = modest_runtime_get_device();
1807                                  tny_device_force_offline (device);
1808                                  tny_device_force_online (device);
1809                         }
1810                 }
1811                         
1812                 if (password) {
1813                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
1814                         
1815                         /* We do not save the password in the configuration, 
1816                          * because this function is only called for passwords that should 
1817                          * not be remembered:
1818                         modest_server_account_set_password (
1819                                  modest_runtime_get_account_mgr(), server_account_name, 
1820                                  *password);
1821                         */
1822                 }
1823                 
1824                 if (cancel)
1825                         *cancel   = FALSE;
1826                         
1827         } else {
1828                 if (username)
1829                         *username = NULL;
1830                         
1831                 if (password)
1832                         *password = NULL;
1833                         
1834                 if (cancel)
1835                         *cancel   = TRUE;
1836         }
1837
1838 /* This is not in the Maemo UI spec:
1839         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
1840                 *remember = TRUE;
1841         else
1842                 *remember = FALSE;
1843 */
1844
1845         gtk_widget_destroy (dialog);
1846 }
1847
1848 void
1849 modest_ui_actions_on_cut (GtkAction *action,
1850                           ModestWindow *window)
1851 {
1852         GtkWidget *focused_widget;
1853
1854         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1855         if (GTK_IS_EDITABLE (focused_widget)) {
1856                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
1857         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1858                 GtkTextBuffer *buffer;
1859                 GtkClipboard *clipboard;
1860
1861                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1862                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1863                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
1864         }
1865 }
1866
1867 void
1868 modest_ui_actions_on_copy (GtkAction *action,
1869                            ModestWindow *window)
1870 {
1871         GtkClipboard *clipboard;
1872         GtkWidget *focused_widget;
1873
1874         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1875         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1876         if (GTK_IS_LABEL (focused_widget)) {
1877                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
1878         } else if (GTK_IS_EDITABLE (focused_widget)) {
1879                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
1880         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1881                 GtkTextBuffer *buffer;
1882
1883                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1884                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
1885         }
1886 }
1887
1888 void
1889 modest_ui_actions_on_undo (GtkAction *action,
1890                            ModestWindow *window)
1891 {
1892         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
1893                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
1894         } else {
1895                 g_return_if_reached ();
1896         }
1897 }
1898
1899 void
1900 modest_ui_actions_on_paste (GtkAction *action,
1901                             ModestWindow *window)
1902 {
1903         GtkWidget *focused_widget;
1904
1905         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1906         if (GTK_IS_EDITABLE (focused_widget)) {
1907                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
1908         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1909                 GtkTextBuffer *buffer;
1910                 GtkClipboard *clipboard;
1911
1912                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1913                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1914                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
1915         }
1916 }
1917
1918 void
1919 modest_ui_actions_on_select_all (GtkAction *action,
1920                                  ModestWindow *window)
1921 {
1922         GtkWidget *focused_widget;
1923
1924         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1925         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
1926                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
1927         } else if (GTK_IS_LABEL (focused_widget)) {
1928                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
1929         } else if (GTK_IS_EDITABLE (focused_widget)) {
1930                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
1931         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1932                 GtkTextBuffer *buffer;
1933                 GtkTextIter start, end;
1934
1935                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1936                 gtk_text_buffer_get_start_iter (buffer, &start);
1937                 gtk_text_buffer_get_end_iter (buffer, &end);
1938                 gtk_text_buffer_select_range (buffer, &start, &end);
1939         }
1940 }
1941
1942 void
1943 modest_ui_actions_on_mark_as_read (GtkAction *action,
1944                                    ModestWindow *window)
1945 {       
1946         g_return_if_fail (MODEST_IS_WINDOW(window));
1947                 
1948         /* Mark each header as read */
1949         do_headers_action (window, headers_action_mark_as_read, NULL);
1950 }
1951
1952 void
1953 modest_ui_actions_on_mark_as_unread (GtkAction *action,
1954                                      ModestWindow *window)
1955 {       
1956         g_return_if_fail (MODEST_IS_WINDOW(window));
1957                 
1958         /* Mark each header as read */
1959         do_headers_action (window, headers_action_mark_as_unread, NULL);
1960 }
1961
1962 void
1963 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
1964                                   GtkRadioAction *selected,
1965                                   ModestWindow *window)
1966 {
1967         gint value;
1968
1969         value = gtk_radio_action_get_current_value (selected);
1970         if (MODEST_IS_WINDOW (window)) {
1971                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
1972         }
1973 }
1974
1975 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
1976                                                         GtkRadioAction *selected,
1977                                                         ModestWindow *window)
1978 {
1979         TnyHeaderFlags flags;
1980         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1981
1982         flags = gtk_radio_action_get_current_value (selected);
1983         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
1984 }
1985
1986 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
1987                                                            GtkRadioAction *selected,
1988                                                            ModestWindow *window)
1989 {
1990         gint file_format;
1991
1992         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1993
1994         file_format = gtk_radio_action_get_current_value (selected);
1995         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
1996 }
1997
1998
1999 void     
2000 modest_ui_actions_on_zoom_plus (GtkAction *action,
2001                                 ModestWindow *window)
2002 {
2003         g_return_if_fail (MODEST_IS_WINDOW (window));
2004
2005         modest_window_zoom_plus (MODEST_WINDOW (window));
2006 }
2007
2008 void     
2009 modest_ui_actions_on_zoom_minus (GtkAction *action,
2010                                  ModestWindow *window)
2011 {
2012         g_return_if_fail (MODEST_IS_WINDOW (window));
2013
2014         modest_window_zoom_minus (MODEST_WINDOW (window));
2015 }
2016
2017 void     
2018 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
2019                                            ModestWindow *window)
2020 {
2021         ModestWindowMgr *mgr;
2022         gboolean fullscreen, active;
2023         g_return_if_fail (MODEST_IS_WINDOW (window));
2024
2025         mgr = modest_runtime_get_window_mgr ();
2026
2027         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
2028         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2029
2030         if (active != fullscreen) {
2031                 modest_window_mgr_set_fullscreen_mode (mgr, active);
2032                 gtk_window_present (GTK_WINDOW (window));
2033         }
2034 }
2035
2036 void
2037 modest_ui_actions_on_change_fullscreen (GtkAction *action,
2038                                         ModestWindow *window)
2039 {
2040         ModestWindowMgr *mgr;
2041         gboolean fullscreen;
2042
2043         g_return_if_fail (MODEST_IS_WINDOW (window));
2044
2045         mgr = modest_runtime_get_window_mgr ();
2046         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2047         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
2048
2049         gtk_window_present (GTK_WINDOW (window));
2050 }
2051
2052 /* 
2053  * Used by modest_ui_actions_on_details to call do_headers_action 
2054  */
2055 static void
2056 headers_action_show_details (TnyHeader *header, 
2057                              ModestWindow *window,
2058                              gpointer user_data)
2059
2060 {
2061         GtkWidget *dialog;
2062         
2063         /* Create dialog */
2064         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
2065
2066         /* Run dialog */
2067         gtk_widget_show_all (dialog);
2068         gtk_dialog_run (GTK_DIALOG (dialog));
2069
2070         gtk_widget_destroy (dialog);
2071 }
2072
2073 /*
2074  * Show the folder details in a ModestDetailsDialog widget
2075  */
2076 static void
2077 show_folder_details (TnyFolder *folder, 
2078                      GtkWindow *window)
2079 {
2080         GtkWidget *dialog;
2081         
2082         /* Create dialog */
2083         dialog = modest_details_dialog_new_with_folder (window, folder);
2084
2085         /* Run dialog */
2086         gtk_widget_show_all (dialog);
2087         gtk_dialog_run (GTK_DIALOG (dialog));
2088
2089         gtk_widget_destroy (dialog);
2090 }
2091
2092 /*
2093  * Show the header details in a ModestDetailsDialog widget
2094  */
2095 void     
2096 modest_ui_actions_on_details (GtkAction *action, 
2097                               ModestWindow *win)
2098 {
2099         TnyList * headers_list;
2100         TnyIterator *iter;
2101         TnyHeader *header;              
2102
2103         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
2104                 TnyMsg *msg;
2105
2106                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
2107                 if (!msg) {
2108                         return;
2109                 } else {
2110                         headers_list = get_selected_headers (win);
2111                         if (!headers_list)
2112                                 return;
2113
2114                         iter = tny_list_create_iterator (headers_list);
2115
2116                         header = TNY_HEADER (tny_iterator_get_current (iter));
2117                         headers_action_show_details (header, win, NULL);
2118                         g_object_unref (header);
2119
2120                         g_object_unref (iter);
2121                 }
2122         } else if (MODEST_IS_MAIN_WINDOW (win)) {
2123                 GtkWidget *folder_view, *header_view;
2124
2125                 /* Check which widget has the focus */
2126                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2127                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
2128                 if (gtk_widget_is_focus (folder_view)) {
2129                         TnyFolder *folder;
2130
2131                         folder = (TnyFolder *) modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2132
2133                         /* Show only when it's a folder */
2134                         if (!folder || !TNY_IS_FOLDER (folder))
2135                                 return;
2136
2137                         show_folder_details (folder, GTK_WINDOW (win));
2138
2139                 } else {
2140                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2141                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2142                         /* Show details of each header */
2143                         do_headers_action (win, headers_action_show_details, header_view);
2144                 }
2145         }
2146 }
2147
2148 void     
2149 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
2150                                      ModestMsgEditWindow *window)
2151 {
2152         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2153
2154         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
2155 }
2156
2157 void     
2158 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
2159                                       ModestMsgEditWindow *window)
2160 {
2161         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2162
2163         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
2164 }
2165
2166 void
2167 modest_ui_actions_toggle_folders_view (GtkAction *action, 
2168                                        ModestMainWindow *main_window)
2169 {
2170         ModestConf *conf;
2171         
2172         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2173
2174         conf = modest_runtime_get_conf ();
2175         
2176         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
2177                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
2178         else
2179                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
2180 }
2181
2182 void 
2183 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
2184                                      ModestWindow *window)
2185 {
2186         gboolean active, fullscreen = FALSE;
2187         ModestWindowMgr *mgr;
2188
2189         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
2190
2191         /* Check if we want to toggle the toolbar vuew in fullscreen
2192            or normal mode */
2193         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
2194                      "ViewShowToolbarFullScreen")) {
2195                 fullscreen = TRUE;
2196         }
2197
2198         /* Toggle toolbar */
2199         mgr = modest_runtime_get_window_mgr ();
2200         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
2201 }
2202
2203 void     
2204 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
2205                                            ModestMsgEditWindow *window)
2206 {
2207         modest_msg_edit_window_select_font (window);
2208 }
2209
2210 void
2211 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
2212                                                   const gchar *display_name,
2213                                                   GtkWindow *window)
2214 {
2215         /* Do not change the application name if the widget has not
2216            the focus. This callback could be called even if the folder
2217            view has not the focus, because the handled signal could be
2218            emitted when the folder view is redrawn */
2219         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
2220                 if (display_name)
2221                         gtk_window_set_title (window, display_name);
2222                 else
2223                         gtk_window_set_title (window, " ");
2224         }
2225 }
2226
2227 void
2228 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
2229 {
2230         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2231         modest_msg_edit_window_select_contacts (window);
2232 }
2233
2234 void
2235 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
2236 {
2237         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2238         modest_msg_edit_window_check_names (window);
2239 }
2240
2241
2242 static GtkWidget*
2243 create_move_to_dialog (ModestWindow *win,
2244                        GtkWidget *folder_view,
2245                        GtkWidget **tree_view)
2246 {
2247         GtkWidget *dialog, *scroll;
2248
2249         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2250                                               GTK_WINDOW (win),
2251                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
2252                                               GTK_STOCK_OK,
2253                                               GTK_RESPONSE_ACCEPT,
2254                                               GTK_STOCK_CANCEL,
2255                                               GTK_RESPONSE_REJECT,
2256                                               NULL);
2257
2258         /* Create scrolled window */
2259         scroll = gtk_scrolled_window_new (NULL, NULL);
2260         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
2261                                          GTK_POLICY_AUTOMATIC,
2262                                          GTK_POLICY_AUTOMATIC);
2263
2264         /* Create folder view */
2265         *tree_view = modest_folder_view_new (NULL);
2266         gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
2267                                  gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
2268         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
2269
2270         /* Add scroll to dialog */
2271         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
2272                             scroll, FALSE, FALSE, 0);
2273
2274         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2275
2276         return dialog;
2277 }
2278
2279 /*
2280  * Returns TRUE if at least one of the headers of the list belongs to
2281  * a message that has been fully retrieved.
2282  */
2283 static gboolean
2284 has_retrieved_msgs (TnyList *list)
2285 {
2286         TnyIterator *iter;
2287         gboolean found = FALSE;
2288
2289         iter = tny_list_create_iterator (list);
2290         while (tny_iterator_is_done (iter) && !found) {
2291                 TnyHeader *header;
2292                 TnyHeaderFlags flags;
2293
2294                 header = TNY_HEADER (tny_iterator_get_current (iter));
2295                 flags = tny_header_get_flags (header);
2296                 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
2297                         found = TRUE;
2298
2299                 if (!found)
2300                         tny_iterator_next (iter);
2301         }
2302         g_object_unref (iter);
2303
2304         return found;
2305 }
2306
2307 /*
2308  * Shows a confirmation dialog to the user when we're moving messages
2309  * from a remote server to the local storage. Returns the dialog
2310  * response. If it's other kind of movement the it always returns
2311  * GTK_RESPONSE_OK
2312  */
2313 static gint
2314 msgs_move_to_confirmation (GtkWindow *win,
2315                            TnyFolder *dest_folder,
2316                            TnyList *headers)
2317 {
2318         gint response = GTK_RESPONSE_OK;
2319
2320         /* If the destination is a local folder */
2321         if (modest_tny_folder_is_local_folder (dest_folder)) {
2322                 TnyFolder *src_folder;
2323                 TnyIterator *iter;
2324                 TnyHeader *header;
2325
2326                 /* Get source folder */
2327                 iter = tny_list_create_iterator (headers);
2328                 header = TNY_HEADER (tny_iterator_get_current (iter));
2329                 src_folder = tny_header_get_folder (header);
2330                 g_object_unref (header);
2331                 g_object_unref (iter);
2332
2333                 /* If the source is a remote folder */
2334                 if (!modest_tny_folder_is_local_folder (src_folder)) {
2335                         const gchar *message;
2336                         
2337                         if (tny_list_get_length (headers) == 1)
2338                                 if (has_retrieved_msgs (headers))
2339                                         message = _("mcen_nc_move_retrieve");
2340                                 else
2341                                         message = _("mcen_nc_move_header");
2342                         else
2343                                 if (has_retrieved_msgs (headers))
2344                                         message = _("mcen_nc_move_retrieves");
2345                                 else
2346                                         message = _("mcen_nc_move_headers");
2347                         
2348                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
2349                                                                             (const gchar *) message);
2350                 }
2351         }
2352         return response;
2353 }
2354
2355
2356 static void
2357 tranasfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
2358 {
2359         ModestMsgViewWindow *self = NULL;
2360         gboolean found = FALSE;
2361
2362         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
2363         self = MODEST_MSG_VIEW_WINDOW (object);
2364
2365         found = modest_msg_view_window_select_first_message (self);
2366         g_return_if_fail (found);
2367 }
2368
2369 static void
2370 move_to_error_checking (const GObject *obj, gpointer user_data)
2371 {
2372         ModestWindow *win = NULL;
2373         
2374         g_return_if_fail (MODEST_IS_WINDOW (obj));
2375         win = MODEST_WINDOW (obj);
2376
2377         /* TODO: show error message */
2378 /*      modest_platform_run_information_dialog (GTK_WINDOW (win), */
2379 /*                                              _("mail_in_ui_folder_move_target_error")); */
2380 }
2381
2382 /*
2383  * UI handler for the "Move to" action when invoked from the
2384  * ModestMainWindow
2385  */
2386 static void 
2387 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
2388                                           ModestMainWindow *win)
2389 {
2390         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
2391         GtkWidget *header_view = NULL;
2392         gint result;
2393         TnyFolderStore *folder_store = NULL;
2394         ModestMailOperation *mail_op = NULL;
2395
2396         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
2397
2398         /* Get the folder view */
2399         folder_view = modest_main_window_get_child_widget (win,
2400                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2401
2402         /* Get header view */
2403         header_view = modest_main_window_get_child_widget (win,
2404                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2405
2406         /* Create and run the dialog */
2407         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);
2408         result = gtk_dialog_run (GTK_DIALOG(dialog));
2409         g_object_ref (tree_view);
2410
2411         /* We do this to save an indentation level ;-) */
2412         if (result != GTK_RESPONSE_ACCEPT)
2413                 goto end;
2414
2415         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2416
2417         if (TNY_IS_ACCOUNT (folder_store))
2418                 goto end;
2419
2420         /* Get folder or messages to transfer */
2421         if (gtk_widget_is_focus (folder_view)) {
2422                 TnyFolderStore *src_folder;
2423                 src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2424
2425                 /* Clean folder on header view before moving it */
2426                 modest_header_view_set_folder (MODEST_HEADER_VIEW (header_view), NULL); 
2427
2428                 if (TNY_IS_FOLDER (src_folder)) {
2429                         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_ID_RECEIVE, 
2430                                                                                  G_OBJECT(win),
2431                                                                                  move_to_error_checking);
2432                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2433                                                          mail_op);
2434
2435                         modest_mail_operation_xfer_folder_async (mail_op, 
2436                                                                  TNY_FOLDER (src_folder),
2437                                                                  folder_store,
2438                                                                  TRUE);
2439                         g_object_unref (G_OBJECT (mail_op));
2440                         
2441                 }
2442
2443                 /* Frees */
2444                 g_object_unref (G_OBJECT (src_folder));
2445         } else {
2446                 if (gtk_widget_is_focus (header_view)) {
2447                         TnyList *headers;
2448                         gint response;
2449
2450                         headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
2451
2452                         /* Ask for user confirmation */
2453                         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2454                                                               TNY_FOLDER (folder_store), 
2455                                                               headers);
2456
2457                         /* Transfer messages */
2458                         if (response == GTK_RESPONSE_OK) {
2459                                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
2460                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2461                                                                  mail_op);
2462
2463                                 modest_mail_operation_xfer_msgs (mail_op, 
2464                                                                  headers,
2465                                                                  TNY_FOLDER (folder_store),
2466                                                                  TRUE,
2467                                                                  NULL,
2468                                                                  NULL);
2469                                 g_object_unref (G_OBJECT (mail_op));
2470                         }
2471                         g_object_unref (headers);
2472                 }
2473         }
2474         g_object_unref (folder_store);
2475
2476         /* Check errors */
2477         if (modest_mail_operation_get_status (mail_op) == MODEST_MAIL_OPERATION_STATUS_FAILED)
2478                 /* Notify the queue */
2479                 modest_mail_operation_queue_remove (modest_runtime_get_mail_operation_queue (), mail_op);
2480         
2481  end:
2482         gtk_widget_destroy (dialog);
2483 }
2484
2485
2486 /*
2487  * UI handler for the "Move to" action when invoked from the
2488  * ModestMsgViewWindow
2489  */
2490 static void 
2491 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
2492                                               ModestMsgViewWindow *win)
2493 {
2494         GtkWidget *dialog, *folder_view, *tree_view = NULL;
2495         gint result;
2496         ModestMainWindow *main_window;
2497         TnyHeader *header;
2498         TnyList *headers;
2499
2500         /* Get the folder view */
2501         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2502         folder_view = modest_main_window_get_child_widget (main_window,
2503                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2504
2505         /* Create and run the dialog */
2506         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);  
2507         result = gtk_dialog_run (GTK_DIALOG(dialog));
2508         g_object_ref (tree_view);
2509
2510         if (result == GTK_RESPONSE_ACCEPT) {
2511                 TnyFolderStore *folder_store;
2512                 gint response;
2513
2514                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2515
2516                 /* Create header list */
2517                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
2518                 headers = tny_simple_list_new ();
2519                 tny_list_prepend (headers, G_OBJECT (header));
2520                 g_object_unref (header);
2521
2522                 /* Ask user for confirmation. MSG-NOT404 */
2523                 response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2524                                                       TNY_FOLDER (folder_store), 
2525                                                       headers);
2526
2527                 /* Transfer current msg */
2528                 if (response == GTK_RESPONSE_OK) {
2529                         ModestMailOperation *mail_op;
2530
2531                         /* Create mail op */
2532                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
2533                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2534                                                          mail_op);
2535                         
2536                         /* Transfer messages */
2537                         modest_mail_operation_xfer_msgs (mail_op, 
2538                                                          headers,
2539                                                          TNY_FOLDER (folder_store),
2540                                                          TRUE,
2541                                                          tranasfer_msgs_from_viewer_cb,
2542                                                          NULL);
2543                         g_object_unref (G_OBJECT (mail_op));
2544                 } 
2545                 g_object_unref (headers);
2546                 g_object_unref (folder_store);
2547         }
2548         gtk_widget_destroy (dialog);
2549 }
2550
2551 void 
2552 modest_ui_actions_on_move_to (GtkAction *action, 
2553                               ModestWindow *win)
2554 {
2555         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
2556                           MODEST_IS_MSG_VIEW_WINDOW (win));
2557
2558         if (MODEST_IS_MAIN_WINDOW (win)) 
2559                 modest_ui_actions_on_main_window_move_to (action, 
2560                                                           MODEST_MAIN_WINDOW (win));
2561         else
2562                 modest_ui_actions_on_msg_view_window_move_to (action, 
2563                                                               MODEST_MSG_VIEW_WINDOW (win));
2564 }
2565
2566 /*
2567  * Calls #HeadersFunc for each header already selected in the main
2568  * window or the message currently being shown in the msg view window
2569  */
2570 static void
2571 do_headers_action (ModestWindow *win, 
2572                    HeadersFunc func,
2573                    gpointer user_data)
2574 {
2575         TnyList *headers_list;
2576         TnyIterator *iter;
2577
2578         /* Get headers */
2579         headers_list = get_selected_headers (win);
2580         if (!headers_list)
2581                 return;
2582
2583         /* Call the function for each header */
2584         iter = tny_list_create_iterator (headers_list);
2585         while (!tny_iterator_is_done (iter)) {
2586                 TnyHeader *header;
2587
2588                 header = TNY_HEADER (tny_iterator_get_current (iter));
2589                 func (header, win, user_data);
2590                 g_object_unref (header);
2591                 tny_iterator_next (iter);
2592         }
2593         g_object_unref (iter);
2594 }
2595
2596 void 
2597 modest_ui_actions_view_attachment (GtkAction *action,
2598                                    ModestWindow *window)
2599 {
2600         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2601                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
2602         } else {
2603                 /* not supported window for this action */
2604                 g_return_if_reached ();
2605         }
2606 }
2607
2608 void
2609 modest_ui_actions_save_attachments (GtkAction *action,
2610                                     ModestWindow *window)
2611 {
2612         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2613                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
2614         } else {
2615                 /* not supported window for this action */
2616                 g_return_if_reached ();
2617         }
2618 }
2619
2620 void
2621 modest_ui_actions_remove_attachments (GtkAction *action,
2622                                       ModestWindow *window)
2623 {
2624         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2625                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
2626         } else {
2627                 /* not supported window for this action */
2628                 g_return_if_reached ();
2629         }
2630 }
2631
2632 void 
2633 modest_ui_actions_on_settings (GtkAction *action, 
2634                                ModestWindow *win)
2635 {
2636         GtkWidget *dialog;
2637
2638         dialog = modest_platform_get_global_settings_dialog ();
2639         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
2640         gtk_widget_show (dialog);
2641
2642         gtk_dialog_run (GTK_DIALOG (dialog));
2643
2644         gtk_widget_destroy (dialog);
2645 }