* Removed xfer_folder_async, all the xfer_folder operations are now async
[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_ACCOUNT (folder_store)) {
1077                 /* Update active account */
1078                 set_active_account_from_tny_account (TNY_ACCOUNT (folder_store), MODEST_WINDOW (main_window));
1079                 /* Show account details */
1080                 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1081         } else {
1082                 if (TNY_IS_FOLDER (folder_store) && selected) {
1083                         /* Update the active account */
1084                         account = tny_folder_get_account (TNY_FOLDER (folder_store));
1085                         set_active_account_from_tny_account (account, MODEST_WINDOW (main_window));
1086                         g_object_unref (account);
1087                         
1088                         /* Set folder on header view */
1089                         modest_main_window_set_contents_style (main_window, 
1090                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1091                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1092                                                        TNY_FOLDER (folder_store));
1093                         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1094                                                       MODEST_CONF_HEADER_VIEW_KEY);
1095                 } else {
1096                         /* Update the active account */
1097                         modest_window_set_active_account (MODEST_WINDOW (main_window), NULL);
1098                         /* Do not show folder */
1099                         modest_widget_memory_save (conf, G_OBJECT (header_view), MODEST_CONF_HEADER_VIEW_KEY);
1100                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
1101                 }
1102         }
1103 }
1104
1105 void 
1106 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1107                                      ModestWindow *win)
1108 {
1109         GtkWidget *dialog;
1110         gchar *txt, *item;
1111         gboolean online;
1112
1113         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1114         
1115         if (g_main_depth > 0)   
1116                 gdk_threads_enter ();
1117         online = tny_device_is_online (modest_runtime_get_device());
1118
1119         if (online) {
1120                 /* already online -- the item is simply not there... */
1121                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1122                                                  GTK_DIALOG_MODAL,
1123                                                  GTK_MESSAGE_WARNING,
1124                                                  GTK_BUTTONS_OK,
1125                                                  _("The %s you selected cannot be found"),
1126                                                  item);
1127                 gtk_dialog_run (GTK_DIALOG(dialog));
1128         } else {
1129                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1130                                                       GTK_WINDOW (win),
1131                                                       GTK_DIALOG_MODAL,
1132                                                       GTK_STOCK_CANCEL,
1133                                                       GTK_RESPONSE_REJECT,
1134                                                       GTK_STOCK_OK,
1135                                                       GTK_RESPONSE_ACCEPT,
1136                                                       NULL);
1137                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1138                                          "Do you want to get online?"), item);
1139                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1140                                     gtk_label_new (txt), FALSE, FALSE, 0);
1141                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1142                 g_free (txt);
1143
1144                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1145                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1146 //                      modest_platform_connect_and_wait ();;
1147                 }
1148         }
1149         gtk_widget_destroy (dialog);
1150         if (g_main_depth > 0)   
1151                 gdk_threads_leave ();
1152 }
1153
1154 void
1155 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1156                                      ModestWindow *win)
1157 {
1158         /* g_message ("%s %s", __FUNCTION__, link); */
1159 }       
1160
1161
1162 void
1163 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1164                                         ModestWindow *win)
1165 {
1166         modest_platform_activate_uri (link);
1167 }
1168
1169 void
1170 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1171                                           ModestWindow *win)
1172 {
1173         modest_platform_show_uri_popup (link);
1174 }
1175
1176 void
1177 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1178                                              ModestWindow *win)
1179 {
1180         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
1181 }
1182
1183 void
1184 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1185                                           const gchar *address,
1186                                           ModestWindow *win)
1187 {
1188         /* g_message ("%s %s", __FUNCTION__, address); */
1189 }
1190
1191 void
1192 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1193 {
1194         TnyTransportAccount *transport_account;
1195         ModestMailOperation *mail_operation;
1196         MsgData *data;
1197         gchar *account_name, *from;
1198         ModestAccountMgr *account_mgr;
1199
1200         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1201         
1202         data = modest_msg_edit_window_get_msg_data (edit_window);
1203
1204         account_mgr = modest_runtime_get_account_mgr();
1205         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1206         if (!account_name) 
1207                 account_name = modest_account_mgr_get_default_account (account_mgr);
1208         if (!account_name) {
1209                 g_printerr ("modest: no account found\n");
1210                 modest_msg_edit_window_free_msg_data (edit_window, data);
1211                 return;
1212         }
1213         transport_account =
1214                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
1215                                       (modest_runtime_get_account_store(),
1216                                        account_name,
1217                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1218         if (!transport_account) {
1219                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1220                 g_free (account_name);
1221                 modest_msg_edit_window_free_msg_data (edit_window, data);
1222                 return;
1223         }
1224         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1225
1226         /* Create the mail operation */         
1227         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO, G_OBJECT(edit_window));
1228         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1229
1230         modest_mail_operation_save_to_drafts (mail_operation,
1231                                               transport_account,
1232                                               from,
1233                                               data->to, 
1234                                               data->cc, 
1235                                               data->bcc,
1236                                               data->subject, 
1237                                               data->plain_body, 
1238                                               data->html_body,
1239                                               data->attachments,
1240                                               data->priority_flags);
1241         /* Frees */
1242         g_free (from);
1243         g_free (account_name);
1244         g_object_unref (G_OBJECT (transport_account));
1245         g_object_unref (G_OBJECT (mail_operation));
1246
1247         modest_msg_edit_window_free_msg_data (edit_window, data);
1248
1249         /* Save settings and close the window */
1250         gtk_widget_destroy (GTK_WIDGET (edit_window));
1251 }
1252 void
1253 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1254 {
1255         TnyTransportAccount *transport_account;
1256         ModestMailOperation *mail_operation;
1257         MsgData *data;
1258         gchar *account_name, *from;
1259         ModestAccountMgr *account_mgr;
1260
1261         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1262
1263         if (!modest_msg_edit_window_check_names (edit_window))
1264                 return;
1265         
1266         data = modest_msg_edit_window_get_msg_data (edit_window);
1267
1268         /* FIXME: Code added just for testing. The final version will
1269            use the send queue provided by tinymail and some
1270            classifier */
1271         account_mgr = modest_runtime_get_account_mgr();
1272         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1273         if (!account_name) 
1274                 account_name = modest_account_mgr_get_default_account (account_mgr);
1275         if (!account_name) {
1276                 g_printerr ("modest: no account found\n");
1277                 modest_msg_edit_window_free_msg_data (edit_window, data);
1278                 return;
1279         }
1280         transport_account =
1281                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
1282                                       (modest_runtime_get_account_store(),
1283                                        account_name));
1284         if (!transport_account) {
1285                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1286                 g_free (account_name);
1287                 modest_msg_edit_window_free_msg_data (edit_window, data);
1288                 return;
1289         }
1290         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1291
1292         /* Create the mail operation */         
1293         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_SEND, G_OBJECT(edit_window));
1294         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1295
1296         modest_mail_operation_send_new_mail (mail_operation,
1297                                              transport_account,
1298                                              from,
1299                                              data->to, 
1300                                              data->cc, 
1301                                              data->bcc,
1302                                              data->subject, 
1303                                              data->plain_body, 
1304                                              data->html_body,
1305                                              data->attachments,
1306                                              data->priority_flags);
1307         /* Frees */
1308         g_free (from);
1309         g_free (account_name);
1310         g_object_unref (G_OBJECT (transport_account));
1311         g_object_unref (G_OBJECT (mail_operation));
1312
1313         modest_msg_edit_window_free_msg_data (edit_window, data);
1314
1315         /* Save settings and close the window */
1316         gtk_widget_destroy (GTK_WIDGET (edit_window));
1317 }
1318
1319 void 
1320 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1321                                   ModestMsgEditWindow *window)
1322 {
1323         ModestMsgEditFormatState *format_state = NULL;
1324
1325         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1326         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1327
1328         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1329                 return;
1330
1331         format_state = modest_msg_edit_window_get_format_state (window);
1332         g_return_if_fail (format_state != NULL);
1333
1334         format_state->bold = gtk_toggle_action_get_active (action);
1335         modest_msg_edit_window_set_format_state (window, format_state);
1336         g_free (format_state);
1337         
1338 }
1339
1340 void 
1341 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1342                                      ModestMsgEditWindow *window)
1343 {
1344         ModestMsgEditFormatState *format_state = NULL;
1345
1346         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1347         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1348
1349         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1350                 return;
1351
1352         format_state = modest_msg_edit_window_get_format_state (window);
1353         g_return_if_fail (format_state != NULL);
1354
1355         format_state->italics = gtk_toggle_action_get_active (action);
1356         modest_msg_edit_window_set_format_state (window, format_state);
1357         g_free (format_state);
1358         
1359 }
1360
1361 void 
1362 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
1363                                      ModestMsgEditWindow *window)
1364 {
1365         ModestMsgEditFormatState *format_state = NULL;
1366
1367         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1368         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1369
1370         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1371                 return;
1372
1373         format_state = modest_msg_edit_window_get_format_state (window);
1374         g_return_if_fail (format_state != NULL);
1375
1376         format_state->bullet = gtk_toggle_action_get_active (action);
1377         modest_msg_edit_window_set_format_state (window, format_state);
1378         g_free (format_state);
1379         
1380 }
1381
1382 void 
1383 modest_ui_actions_on_change_justify (GtkRadioAction *action,
1384                                      GtkRadioAction *selected,
1385                                      ModestMsgEditWindow *window)
1386 {
1387         ModestMsgEditFormatState *format_state = NULL;
1388         GtkJustification value;
1389
1390         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1391
1392         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1393                 return;
1394
1395         value = gtk_radio_action_get_current_value (selected);
1396
1397         format_state = modest_msg_edit_window_get_format_state (window);
1398         g_return_if_fail (format_state != NULL);
1399
1400         format_state->justification = value;
1401         modest_msg_edit_window_set_format_state (window, format_state);
1402         g_free (format_state);
1403 }
1404
1405 void 
1406 modest_ui_actions_on_select_editor_color (GtkAction *action,
1407                                           ModestMsgEditWindow *window)
1408 {
1409         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1410         g_return_if_fail (GTK_IS_ACTION (action));
1411
1412         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1413                 return;
1414
1415         modest_msg_edit_window_select_color (window);
1416 }
1417
1418 void 
1419 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
1420                                                      ModestMsgEditWindow *window)
1421 {
1422         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1423         g_return_if_fail (GTK_IS_ACTION (action));
1424
1425         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1426                 return;
1427
1428         modest_msg_edit_window_select_background_color (window);
1429 }
1430
1431 void 
1432 modest_ui_actions_on_insert_image (GtkAction *action,
1433                                    ModestMsgEditWindow *window)
1434 {
1435         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1436         g_return_if_fail (GTK_IS_ACTION (action));
1437
1438         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1439                 return;
1440
1441         modest_msg_edit_window_insert_image (window);
1442 }
1443
1444 void 
1445 modest_ui_actions_on_attach_file (GtkAction *action,
1446                                   ModestMsgEditWindow *window)
1447 {
1448         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1449         g_return_if_fail (GTK_IS_ACTION (action));
1450
1451         modest_msg_edit_window_attach_file (window);
1452 }
1453
1454 void 
1455 modest_ui_actions_on_remove_attachments (GtkAction *action,
1456                                          ModestMsgEditWindow *window)
1457 {
1458         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1459         g_return_if_fail (GTK_IS_ACTION (action));
1460
1461         modest_msg_edit_window_remove_attachments (window, NULL);
1462 }
1463
1464 /*
1465  * Shows a dialog with an entry that asks for some text. The returned
1466  * value must be freed by the caller. The dialog window title will be
1467  * set to @title.
1468  */
1469 static gchar *
1470 ask_for_folder_name (GtkWindow *parent_window,
1471                      const gchar *title)
1472 {
1473         GtkWidget *dialog, *entry;
1474         gchar *folder_name = NULL;
1475
1476         /* Ask for folder name */
1477         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1478                                               parent_window,
1479                                               GTK_DIALOG_MODAL,
1480                                               GTK_STOCK_CANCEL,
1481                                               GTK_RESPONSE_REJECT,
1482                                               GTK_STOCK_OK,
1483                                               GTK_RESPONSE_ACCEPT,
1484                                               NULL);
1485         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1486                             gtk_label_new(title),
1487                             FALSE, FALSE, 0);
1488                 
1489         entry = gtk_entry_new_with_max_length (40);
1490         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1491                             entry,
1492                             TRUE, FALSE, 0);    
1493         
1494         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1495         
1496         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
1497                 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1498
1499         gtk_widget_destroy (dialog);
1500
1501         return folder_name;
1502 }
1503
1504 void 
1505 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1506 {
1507         TnyFolderStore *parent_folder;
1508         GtkWidget *folder_view;
1509         
1510         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1511
1512         folder_view = modest_main_window_get_child_widget (main_window,
1513                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1514         if (!folder_view)
1515                 return;
1516
1517         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1518         
1519         if (parent_folder) {
1520                 gboolean finished = FALSE;
1521                 gint result;
1522                 gchar *folder_name = NULL, *suggested_name = NULL;
1523
1524                 /* Run the new folder dialog */
1525                 while (!finished) {
1526                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (main_window),
1527                                                                         parent_folder,
1528                                                                         suggested_name,
1529                                                                         &folder_name);
1530
1531                         if (result == GTK_RESPONSE_REJECT) {
1532                                 finished = TRUE;
1533                         } else {
1534                                 ModestMailOperation *mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO, G_OBJECT(main_window));
1535                                 TnyFolder *new_folder = NULL;
1536
1537                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
1538                                                                  mail_op);
1539                 
1540                                 new_folder = modest_mail_operation_create_folder (mail_op,
1541                                                                                   parent_folder,
1542                                                                                   (const gchar *) folder_name);
1543                                 if (new_folder) {
1544                                         g_object_unref (new_folder);
1545                                         finished = TRUE;
1546                                 } 
1547 /*                              else { */
1548 /*                                      /\* TODO: check error and follow proper actions *\/ */
1549 /* /\*                                  suggested_name = X; *\/ */
1550 /*                                      /\* Show error to the user *\/ */
1551 /*                                      modest_platform_run_information_dialog (GTK_WINDOW (main_window), */
1552 /*                                                                              _("mail_in_ui_folder_create_error")); */
1553 /*                              } */
1554                                 g_object_unref (mail_op);
1555                         }
1556                         g_free (folder_name);
1557                         folder_name = NULL;
1558                 }
1559
1560                 g_object_unref (parent_folder);
1561         }
1562 }
1563
1564 void 
1565 modest_ui_actions_on_rename_folder (GtkAction *action,
1566                                      ModestMainWindow *main_window)
1567 {
1568         TnyFolderStore *folder;
1569         GtkWidget *folder_view;
1570         GtkWidget *header_view; 
1571
1572         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1573
1574         folder_view = modest_main_window_get_child_widget (main_window,
1575                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1576         if (!folder_view)
1577                 return;
1578
1579         header_view = modest_main_window_get_child_widget (main_window,
1580                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1581         
1582         if (!header_view)
1583                 return;
1584
1585         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1586         
1587         if (folder && TNY_IS_FOLDER (folder)) {
1588                 gchar *folder_name;
1589                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1590                                                    _("Please enter a new name for the folder"));
1591
1592                 if (folder_name != NULL && strlen (folder_name) > 0) {
1593                         ModestMailOperation *mail_op;
1594
1595                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO, G_OBJECT(main_window));
1596                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1597                                                          mail_op);
1598
1599                         modest_header_view_set_folder (MODEST_HEADER_VIEW (header_view), NULL);
1600
1601                         modest_mail_operation_rename_folder (mail_op,
1602                                                              TNY_FOLDER (folder),
1603                                                              (const gchar *) folder_name);
1604
1605                         g_object_unref (mail_op);
1606                         g_free (folder_name);
1607                 }
1608                 g_object_unref (folder);
1609         }
1610 }
1611
1612 static void
1613 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
1614 {
1615         TnyFolderStore *folder;
1616         GtkWidget *folder_view;
1617         gint response;
1618         gchar *message;
1619         
1620         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1621
1622         folder_view = modest_main_window_get_child_widget (main_window,
1623                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1624         if (!folder_view)
1625                 return;
1626
1627         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1628
1629         /* Show an error if it's an account */
1630         if (!TNY_IS_FOLDER (folder)) {
1631                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
1632                                                         _("mail_in_ui_folder_delete_error"));
1633                 return ;
1634         }
1635
1636         /* Ask the user */      
1637         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
1638                                     tny_folder_get_name (TNY_FOLDER (folder)));
1639         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window), 
1640                                                             (const gchar *) message);
1641         g_free (message);
1642
1643         if (response == GTK_RESPONSE_OK) {
1644                 ModestMailOperation *mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_DELETE, G_OBJECT(main_window));
1645
1646                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1647                                                  mail_op);
1648                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
1649
1650                 /* Show error if happened */
1651                 if (modest_mail_operation_get_error (mail_op))
1652                         modest_platform_run_information_dialog (GTK_WINDOW (main_window),
1653                                                                 _("mail_in_ui_folder_delete_error"));
1654
1655                 g_object_unref (G_OBJECT (mail_op));
1656         }
1657
1658         g_object_unref (G_OBJECT (folder));
1659 }
1660
1661 void 
1662 modest_ui_actions_on_delete_folder (GtkAction *action,
1663                                      ModestMainWindow *main_window)
1664 {
1665         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1666
1667         delete_folder (main_window, FALSE);
1668 }
1669
1670 void 
1671 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1672 {
1673         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1674         
1675         delete_folder (main_window, TRUE);
1676 }
1677
1678 void
1679 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
1680                                          const gchar* server_account_name,
1681                                          gchar **username,
1682                                          gchar **password, 
1683                                          gboolean *cancel, 
1684                                          gboolean *remember,
1685                                          ModestMainWindow *main_window)
1686 {
1687         g_return_if_fail(server_account_name);
1688         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
1689         
1690         /* Initalize output parameters: */
1691         if (cancel)
1692                 *cancel = FALSE;
1693                 
1694         if (remember)
1695                 *remember = TRUE;
1696                 
1697 #ifdef MODEST_PLATFORM_MAEMO
1698         /* Maemo uses a different (awkward) button order,
1699          * It should probably just use gtk_alternative_dialog_button_order ().
1700          */
1701         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
1702                                               NULL,
1703                                               GTK_DIALOG_MODAL,
1704                                               GTK_STOCK_OK,
1705                                               GTK_RESPONSE_ACCEPT,
1706                                               GTK_STOCK_CANCEL,
1707                                               GTK_RESPONSE_REJECT,
1708                                               NULL);
1709 #else
1710         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
1711                                               NULL,
1712                                               GTK_DIALOG_MODAL,
1713                                               GTK_STOCK_CANCEL,
1714                                               GTK_RESPONSE_REJECT,
1715                                               GTK_STOCK_OK,
1716                                               GTK_RESPONSE_ACCEPT,
1717                                               NULL);
1718 #endif /* MODEST_PLATFORM_MAEMO */
1719
1720         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1721         
1722         gchar *server_name = modest_server_account_get_hostname (
1723                 modest_runtime_get_account_mgr(), server_account_name);
1724         
1725         /* This causes a warning because the logical ID has no %s in it, 
1726          * though the translation does, but there is not much we can do about that: */
1727         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
1728         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1729                             FALSE, FALSE, 0);
1730         g_free (txt);
1731         g_free (server_name);
1732         server_name = NULL;
1733
1734         /* username: */
1735         gchar *initial_username = modest_server_account_get_username (
1736                 modest_runtime_get_account_mgr(), server_account_name);
1737         
1738         GtkWidget *entry_username = gtk_entry_new ();
1739         if (initial_username)
1740                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
1741         /* Dim this if a connection has ever succeeded with this username,
1742          * as per the UI spec: */
1743         const gboolean username_known = 
1744                 modest_server_account_get_username_has_succeeded(
1745                         modest_runtime_get_account_mgr(), server_account_name);
1746         gtk_widget_set_sensitive (entry_username, !username_known);
1747         
1748 #ifdef MODEST_PLATFORM_MAEMO
1749         /* Auto-capitalization is the default, so let's turn it off: */
1750         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
1751         
1752         /* Create a size group to be used by all captions.
1753          * Note that HildonCaption does not create a default size group if we do not specify one.
1754          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
1755         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
1756         
1757         GtkWidget *caption = hildon_caption_new (sizegroup, 
1758                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
1759         gtk_widget_show (entry_username);
1760         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
1761                 FALSE, FALSE, MODEST_MARGIN_HALF);
1762         gtk_widget_show (caption);
1763 #else 
1764         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
1765                             TRUE, FALSE, 0);
1766 #endif /* MODEST_PLATFORM_MAEMO */      
1767                             
1768         /* password: */
1769         GtkWidget *entry_password = gtk_entry_new ();
1770         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
1771         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
1772         
1773 #ifdef MODEST_PLATFORM_MAEMO
1774         /* Auto-capitalization is the default, so let's turn it off: */
1775         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
1776                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
1777         
1778         caption = hildon_caption_new (sizegroup, 
1779                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
1780         gtk_widget_show (entry_password);
1781         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
1782                 FALSE, FALSE, MODEST_MARGIN_HALF);
1783         gtk_widget_show (caption);
1784         g_object_unref (sizegroup);
1785 #else 
1786         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
1787                             TRUE, FALSE, 0);
1788 #endif /* MODEST_PLATFORM_MAEMO */      
1789                                 
1790 /* This is not in the Maemo UI spec:
1791         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1792         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1793                             TRUE, FALSE, 0);
1794 */
1795
1796         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1797         
1798         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1799                 if (username) {
1800                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
1801                         
1802                         modest_server_account_set_username (
1803                                  modest_runtime_get_account_mgr(), server_account_name, 
1804                                  *username);
1805                                  
1806                         const gboolean username_was_changed = 
1807                                 (strcmp (*username, initial_username) != 0);
1808                         if (username_was_changed) {
1809                                 /* To actually use a changed username, 
1810                                  * we must reset the connection, according to pvanhoof.
1811                                  * This _might_ be a sensible way to do that: */
1812                                  TnyDevice *device = modest_runtime_get_device();
1813                                  tny_device_force_offline (device);
1814                                  tny_device_force_online (device);
1815                         }
1816                 }
1817                         
1818                 if (password) {
1819                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
1820                         
1821                         /* We do not save the password in the configuration, 
1822                          * because this function is only called for passwords that should 
1823                          * not be remembered:
1824                         modest_server_account_set_password (
1825                                  modest_runtime_get_account_mgr(), server_account_name, 
1826                                  *password);
1827                         */
1828                 }
1829                 
1830                 if (cancel)
1831                         *cancel   = FALSE;
1832                         
1833         } else {
1834                 if (username)
1835                         *username = NULL;
1836                         
1837                 if (password)
1838                         *password = NULL;
1839                         
1840                 if (cancel)
1841                         *cancel   = TRUE;
1842         }
1843
1844 /* This is not in the Maemo UI spec:
1845         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
1846                 *remember = TRUE;
1847         else
1848                 *remember = FALSE;
1849 */
1850
1851         gtk_widget_destroy (dialog);
1852         
1853         printf ("DEBUG: %s: cancel=%d\n", __FUNCTION__, *cancel);
1854 }
1855
1856 void
1857 modest_ui_actions_on_cut (GtkAction *action,
1858                           ModestWindow *window)
1859 {
1860         GtkWidget *focused_widget;
1861
1862         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1863         if (GTK_IS_EDITABLE (focused_widget)) {
1864                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
1865         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1866                 GtkTextBuffer *buffer;
1867                 GtkClipboard *clipboard;
1868
1869                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1870                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1871                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
1872         }
1873 }
1874
1875 void
1876 modest_ui_actions_on_copy (GtkAction *action,
1877                            ModestWindow *window)
1878 {
1879         GtkClipboard *clipboard;
1880         GtkWidget *focused_widget;
1881
1882         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1883         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1884         if (GTK_IS_LABEL (focused_widget)) {
1885                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
1886         } else if (GTK_IS_EDITABLE (focused_widget)) {
1887                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
1888         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1889                 GtkTextBuffer *buffer;
1890
1891                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1892                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
1893         }
1894 }
1895
1896 void
1897 modest_ui_actions_on_undo (GtkAction *action,
1898                            ModestWindow *window)
1899 {
1900         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
1901                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
1902         } else {
1903                 g_return_if_reached ();
1904         }
1905 }
1906
1907 void
1908 modest_ui_actions_on_paste (GtkAction *action,
1909                             ModestWindow *window)
1910 {
1911         GtkWidget *focused_widget;
1912
1913         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1914         if (GTK_IS_EDITABLE (focused_widget)) {
1915                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
1916         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1917                 GtkTextBuffer *buffer;
1918                 GtkClipboard *clipboard;
1919
1920                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1921                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1922                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
1923         }
1924 }
1925
1926 void
1927 modest_ui_actions_on_select_all (GtkAction *action,
1928                                  ModestWindow *window)
1929 {
1930         GtkWidget *focused_widget;
1931
1932         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1933         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
1934                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
1935         } else if (GTK_IS_LABEL (focused_widget)) {
1936                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
1937         } else if (GTK_IS_EDITABLE (focused_widget)) {
1938                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
1939         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1940                 GtkTextBuffer *buffer;
1941                 GtkTextIter start, end;
1942
1943                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1944                 gtk_text_buffer_get_start_iter (buffer, &start);
1945                 gtk_text_buffer_get_end_iter (buffer, &end);
1946                 gtk_text_buffer_select_range (buffer, &start, &end);
1947         }
1948 }
1949
1950 void
1951 modest_ui_actions_on_mark_as_read (GtkAction *action,
1952                                    ModestWindow *window)
1953 {       
1954         g_return_if_fail (MODEST_IS_WINDOW(window));
1955                 
1956         /* Mark each header as read */
1957         do_headers_action (window, headers_action_mark_as_read, NULL);
1958 }
1959
1960 void
1961 modest_ui_actions_on_mark_as_unread (GtkAction *action,
1962                                      ModestWindow *window)
1963 {       
1964         g_return_if_fail (MODEST_IS_WINDOW(window));
1965                 
1966         /* Mark each header as read */
1967         do_headers_action (window, headers_action_mark_as_unread, NULL);
1968 }
1969
1970 void
1971 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
1972                                   GtkRadioAction *selected,
1973                                   ModestWindow *window)
1974 {
1975         gint value;
1976
1977         value = gtk_radio_action_get_current_value (selected);
1978         if (MODEST_IS_WINDOW (window)) {
1979                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
1980         }
1981 }
1982
1983 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
1984                                                         GtkRadioAction *selected,
1985                                                         ModestWindow *window)
1986 {
1987         TnyHeaderFlags flags;
1988         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1989
1990         flags = gtk_radio_action_get_current_value (selected);
1991         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
1992 }
1993
1994 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
1995                                                            GtkRadioAction *selected,
1996                                                            ModestWindow *window)
1997 {
1998         gint file_format;
1999
2000         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2001
2002         file_format = gtk_radio_action_get_current_value (selected);
2003         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
2004 }
2005
2006
2007 void     
2008 modest_ui_actions_on_zoom_plus (GtkAction *action,
2009                                 ModestWindow *window)
2010 {
2011         g_return_if_fail (MODEST_IS_WINDOW (window));
2012
2013         modest_window_zoom_plus (MODEST_WINDOW (window));
2014 }
2015
2016 void     
2017 modest_ui_actions_on_zoom_minus (GtkAction *action,
2018                                  ModestWindow *window)
2019 {
2020         g_return_if_fail (MODEST_IS_WINDOW (window));
2021
2022         modest_window_zoom_minus (MODEST_WINDOW (window));
2023 }
2024
2025 void     
2026 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
2027                                            ModestWindow *window)
2028 {
2029         ModestWindowMgr *mgr;
2030         gboolean fullscreen, active;
2031         g_return_if_fail (MODEST_IS_WINDOW (window));
2032
2033         mgr = modest_runtime_get_window_mgr ();
2034
2035         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
2036         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2037
2038         if (active != fullscreen) {
2039                 modest_window_mgr_set_fullscreen_mode (mgr, active);
2040                 gtk_window_present (GTK_WINDOW (window));
2041         }
2042 }
2043
2044 void
2045 modest_ui_actions_on_change_fullscreen (GtkAction *action,
2046                                         ModestWindow *window)
2047 {
2048         ModestWindowMgr *mgr;
2049         gboolean fullscreen;
2050
2051         g_return_if_fail (MODEST_IS_WINDOW (window));
2052
2053         mgr = modest_runtime_get_window_mgr ();
2054         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
2055         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
2056
2057         gtk_window_present (GTK_WINDOW (window));
2058 }
2059
2060 /* 
2061  * Used by modest_ui_actions_on_details to call do_headers_action 
2062  */
2063 static void
2064 headers_action_show_details (TnyHeader *header, 
2065                              ModestWindow *window,
2066                              gpointer user_data)
2067
2068 {
2069         GtkWidget *dialog;
2070         
2071         /* Create dialog */
2072         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
2073
2074         /* Run dialog */
2075         gtk_widget_show_all (dialog);
2076         gtk_dialog_run (GTK_DIALOG (dialog));
2077
2078         gtk_widget_destroy (dialog);
2079 }
2080
2081 /*
2082  * Show the folder details in a ModestDetailsDialog widget
2083  */
2084 static void
2085 show_folder_details (TnyFolder *folder, 
2086                      GtkWindow *window)
2087 {
2088         GtkWidget *dialog;
2089         
2090         /* Create dialog */
2091         dialog = modest_details_dialog_new_with_folder (window, folder);
2092
2093         /* Run dialog */
2094         gtk_widget_show_all (dialog);
2095         gtk_dialog_run (GTK_DIALOG (dialog));
2096
2097         gtk_widget_destroy (dialog);
2098 }
2099
2100 /*
2101  * Show the header details in a ModestDetailsDialog widget
2102  */
2103 void     
2104 modest_ui_actions_on_details (GtkAction *action, 
2105                               ModestWindow *win)
2106 {
2107         TnyList * headers_list;
2108         TnyIterator *iter;
2109         TnyHeader *header;              
2110
2111         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
2112                 TnyMsg *msg;
2113
2114                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
2115                 if (!msg) {
2116                         return;
2117                 } else {
2118                         headers_list = get_selected_headers (win);
2119                         if (!headers_list)
2120                                 return;
2121
2122                         iter = tny_list_create_iterator (headers_list);
2123
2124                         header = TNY_HEADER (tny_iterator_get_current (iter));
2125                         headers_action_show_details (header, win, NULL);
2126                         g_object_unref (header);
2127
2128                         g_object_unref (iter);
2129                 }
2130         } else if (MODEST_IS_MAIN_WINDOW (win)) {
2131                 GtkWidget *folder_view, *header_view;
2132
2133                 /* Check which widget has the focus */
2134                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2135                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
2136                 if (gtk_widget_is_focus (folder_view)) {
2137                         TnyFolder *folder;
2138
2139                         folder = (TnyFolder *) modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2140
2141                         /* Show only when it's a folder */
2142                         if (!folder || !TNY_IS_FOLDER (folder))
2143                                 return;
2144
2145                         show_folder_details (folder, GTK_WINDOW (win));
2146
2147                 } else {
2148                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2149                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2150                         /* Show details of each header */
2151                         do_headers_action (win, headers_action_show_details, header_view);
2152                 }
2153         }
2154 }
2155
2156 void     
2157 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
2158                                      ModestMsgEditWindow *window)
2159 {
2160         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2161
2162         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
2163 }
2164
2165 void     
2166 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
2167                                       ModestMsgEditWindow *window)
2168 {
2169         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2170
2171         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
2172 }
2173
2174 void
2175 modest_ui_actions_toggle_folders_view (GtkAction *action, 
2176                                        ModestMainWindow *main_window)
2177 {
2178         ModestConf *conf;
2179         
2180         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2181
2182         conf = modest_runtime_get_conf ();
2183         
2184         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
2185                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
2186         else
2187                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
2188 }
2189
2190 void 
2191 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
2192                                      ModestWindow *window)
2193 {
2194         gboolean active, fullscreen = FALSE;
2195         ModestWindowMgr *mgr;
2196
2197         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
2198
2199         /* Check if we want to toggle the toolbar vuew in fullscreen
2200            or normal mode */
2201         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
2202                      "ViewShowToolbarFullScreen")) {
2203                 fullscreen = TRUE;
2204         }
2205
2206         /* Toggle toolbar */
2207         mgr = modest_runtime_get_window_mgr ();
2208         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
2209 }
2210
2211 void     
2212 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
2213                                            ModestMsgEditWindow *window)
2214 {
2215         modest_msg_edit_window_select_font (window);
2216 }
2217
2218 void
2219 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
2220                                                   const gchar *display_name,
2221                                                   GtkWindow *window)
2222 {
2223         /* Do not change the application name if the widget has not
2224            the focus. This callback could be called even if the folder
2225            view has not the focus, because the handled signal could be
2226            emitted when the folder view is redrawn */
2227         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
2228                 if (display_name)
2229                         gtk_window_set_title (window, display_name);
2230                 else
2231                         gtk_window_set_title (window, " ");
2232         }
2233 }
2234
2235 void
2236 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
2237 {
2238         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2239         modest_msg_edit_window_select_contacts (window);
2240 }
2241
2242 void
2243 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
2244 {
2245         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2246         modest_msg_edit_window_check_names (window);
2247 }
2248
2249
2250 static GtkWidget*
2251 create_move_to_dialog (ModestWindow *win,
2252                        GtkWidget *folder_view,
2253                        GtkWidget **tree_view)
2254 {
2255         GtkWidget *dialog, *scroll;
2256
2257         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2258                                               GTK_WINDOW (win),
2259                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
2260                                               GTK_STOCK_OK,
2261                                               GTK_RESPONSE_ACCEPT,
2262                                               GTK_STOCK_CANCEL,
2263                                               GTK_RESPONSE_REJECT,
2264                                               NULL);
2265
2266         /* Create scrolled window */
2267         scroll = gtk_scrolled_window_new (NULL, NULL);
2268         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
2269                                          GTK_POLICY_AUTOMATIC,
2270                                          GTK_POLICY_AUTOMATIC);
2271
2272         /* Create folder view */
2273         *tree_view = modest_folder_view_new (NULL);
2274         gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
2275                                  gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
2276         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
2277
2278         /* Add scroll to dialog */
2279         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
2280                             scroll, FALSE, FALSE, 0);
2281
2282         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2283
2284         return dialog;
2285 }
2286
2287 /*
2288  * Returns TRUE if at least one of the headers of the list belongs to
2289  * a message that has been fully retrieved.
2290  */
2291 static gboolean
2292 has_retrieved_msgs (TnyList *list)
2293 {
2294         TnyIterator *iter;
2295         gboolean found = FALSE;
2296
2297         iter = tny_list_create_iterator (list);
2298         while (tny_iterator_is_done (iter) && !found) {
2299                 TnyHeader *header;
2300                 TnyHeaderFlags flags;
2301
2302                 header = TNY_HEADER (tny_iterator_get_current (iter));
2303                 flags = tny_header_get_flags (header);
2304                 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
2305                         found = TRUE;
2306
2307                 if (!found)
2308                         tny_iterator_next (iter);
2309         }
2310         g_object_unref (iter);
2311
2312         return found;
2313 }
2314
2315 /*
2316  * Shows a confirmation dialog to the user when we're moving messages
2317  * from a remote server to the local storage. Returns the dialog
2318  * response. If it's other kind of movement the it always returns
2319  * GTK_RESPONSE_OK
2320  */
2321 static gint
2322 msgs_move_to_confirmation (GtkWindow *win,
2323                            TnyFolder *dest_folder,
2324                            TnyList *headers)
2325 {
2326         gint response = GTK_RESPONSE_OK;
2327
2328         /* If the destination is a local folder */
2329         if (modest_tny_folder_is_local_folder (dest_folder)) {
2330                 TnyFolder *src_folder;
2331                 TnyIterator *iter;
2332                 TnyHeader *header;
2333
2334                 /* Get source folder */
2335                 iter = tny_list_create_iterator (headers);
2336                 header = TNY_HEADER (tny_iterator_get_current (iter));
2337                 src_folder = tny_header_get_folder (header);
2338                 g_object_unref (header);
2339                 g_object_unref (iter);
2340
2341                 /* If the source is a remote folder */
2342                 if (!modest_tny_folder_is_local_folder (src_folder)) {
2343                         const gchar *message;
2344                         
2345                         if (tny_list_get_length (headers) == 1)
2346                                 if (has_retrieved_msgs (headers))
2347                                         message = _("mcen_nc_move_retrieve");
2348                                 else
2349                                         message = _("mcen_nc_move_header");
2350                         else
2351                                 if (has_retrieved_msgs (headers))
2352                                         message = _("mcen_nc_move_retrieves");
2353                                 else
2354                                         message = _("mcen_nc_move_headers");
2355                         
2356                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
2357                                                                             (const gchar *) message);
2358                 }
2359         }
2360         return response;
2361 }
2362
2363
2364 static void
2365 tranasfer_msgs_from_viewer_cb (const GObject *object, gpointer user_data)
2366 {
2367         ModestMsgViewWindow *self = NULL;
2368         gboolean found = FALSE;
2369
2370         g_return_if_fail (MODEST_IS_MSG_VIEW_WINDOW (object));
2371         self = MODEST_MSG_VIEW_WINDOW (object);
2372
2373         found = modest_msg_view_window_select_first_message (self);
2374         g_return_if_fail (found);
2375 }
2376
2377 static void
2378 move_to_error_checking (const GObject *obj, gpointer user_data)
2379 {
2380         ModestWindow *win = NULL;
2381         
2382         g_return_if_fail (MODEST_IS_WINDOW (obj));
2383         win = MODEST_WINDOW (obj);
2384
2385         /* TODO: show error message */
2386 /*      modest_platform_run_information_dialog (GTK_WINDOW (win), */
2387 /*                                              _("mail_in_ui_folder_move_target_error")); */
2388 }
2389
2390 /*
2391  * UI handler for the "Move to" action when invoked from the
2392  * ModestMainWindow
2393  */
2394 static void 
2395 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
2396                                           ModestMainWindow *win)
2397 {
2398         GtkWidget *dialog = NULL, *folder_view = NULL, *tree_view = NULL;
2399         GtkWidget *header_view = NULL;
2400         gint result;
2401         TnyFolderStore *folder_store = NULL;
2402         ModestMailOperation *mail_op = NULL;
2403
2404         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
2405
2406         /* Get the folder view */
2407         folder_view = modest_main_window_get_child_widget (win,
2408                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2409
2410         /* Get header view */
2411         header_view = modest_main_window_get_child_widget (win,
2412                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2413
2414         /* Create and run the dialog */
2415         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);
2416         result = gtk_dialog_run (GTK_DIALOG(dialog));
2417         g_object_ref (tree_view);
2418
2419         /* We do this to save an indentation level ;-) */
2420         if (result != GTK_RESPONSE_ACCEPT)
2421                 goto end;
2422
2423         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2424
2425         if (TNY_IS_ACCOUNT (folder_store))
2426                 goto end;
2427
2428         /* Get folder or messages to transfer */
2429         if (gtk_widget_is_focus (folder_view)) {
2430                 TnyFolderStore *src_folder;
2431                 src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2432
2433                 /* Clean folder on header view before moving it */
2434                 modest_header_view_set_folder (MODEST_HEADER_VIEW (header_view), NULL); 
2435
2436                 if (TNY_IS_FOLDER (src_folder)) {
2437                         mail_op = modest_mail_operation_new_with_error_handling (MODEST_MAIL_OPERATION_ID_RECEIVE, 
2438                                                                                  G_OBJECT(win),
2439                                                                                  move_to_error_checking);
2440                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2441                                                          mail_op);
2442
2443                         modest_mail_operation_xfer_folder (mail_op, 
2444                                                            TNY_FOLDER (src_folder),
2445                                                            folder_store,
2446                                                            TRUE);
2447                         g_object_unref (G_OBJECT (mail_op));
2448                         
2449                 }
2450
2451                 /* Frees */
2452                 g_object_unref (G_OBJECT (src_folder));
2453         } else {
2454                 if (gtk_widget_is_focus (header_view)) {
2455                         TnyList *headers;
2456                         gint response;
2457
2458                         headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
2459
2460                         /* Ask for user confirmation */
2461                         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2462                                                               TNY_FOLDER (folder_store), 
2463                                                               headers);
2464
2465                         /* Transfer messages */
2466                         if (response == GTK_RESPONSE_OK) {
2467                                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
2468                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2469                                                                  mail_op);
2470
2471                                 modest_mail_operation_xfer_msgs (mail_op, 
2472                                                                  headers,
2473                                                                  TNY_FOLDER (folder_store),
2474                                                                  TRUE,
2475                                                                  NULL,
2476                                                                  NULL);
2477                                 g_object_unref (G_OBJECT (mail_op));
2478                         }
2479                         g_object_unref (headers);
2480                 }
2481         }
2482         g_object_unref (folder_store);
2483         
2484  end:
2485         gtk_widget_destroy (dialog);
2486 }
2487
2488
2489 /*
2490  * UI handler for the "Move to" action when invoked from the
2491  * ModestMsgViewWindow
2492  */
2493 static void 
2494 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
2495                                               ModestMsgViewWindow *win)
2496 {
2497         GtkWidget *dialog, *folder_view, *tree_view = NULL;
2498         gint result;
2499         ModestMainWindow *main_window;
2500         TnyHeader *header;
2501         TnyList *headers;
2502
2503         /* Get the folder view */
2504         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2505         folder_view = modest_main_window_get_child_widget (main_window,
2506                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2507
2508         /* Create and run the dialog */
2509         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);  
2510         result = gtk_dialog_run (GTK_DIALOG(dialog));
2511         g_object_ref (tree_view);
2512
2513         if (result == GTK_RESPONSE_ACCEPT) {
2514                 TnyFolderStore *folder_store;
2515                 gint response;
2516
2517                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2518
2519                 /* Create header list */
2520                 header = modest_msg_view_window_get_header (MODEST_MSG_VIEW_WINDOW (win));              
2521                 headers = tny_simple_list_new ();
2522                 tny_list_prepend (headers, G_OBJECT (header));
2523                 g_object_unref (header);
2524
2525                 /* Ask user for confirmation. MSG-NOT404 */
2526                 response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2527                                                       TNY_FOLDER (folder_store), 
2528                                                       headers);
2529
2530                 /* Transfer current msg */
2531                 if (response == GTK_RESPONSE_OK) {
2532                         ModestMailOperation *mail_op;
2533
2534                         /* Create mail op */
2535                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
2536                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2537                                                          mail_op);
2538                         
2539                         /* Transfer messages */
2540                         modest_mail_operation_xfer_msgs (mail_op, 
2541                                                          headers,
2542                                                          TNY_FOLDER (folder_store),
2543                                                          TRUE,
2544                                                          tranasfer_msgs_from_viewer_cb,
2545                                                          NULL);
2546                         g_object_unref (G_OBJECT (mail_op));
2547                 } 
2548                 g_object_unref (headers);
2549                 g_object_unref (folder_store);
2550         }
2551         gtk_widget_destroy (dialog);
2552 }
2553
2554 void 
2555 modest_ui_actions_on_move_to (GtkAction *action, 
2556                               ModestWindow *win)
2557 {
2558         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
2559                           MODEST_IS_MSG_VIEW_WINDOW (win));
2560
2561         if (MODEST_IS_MAIN_WINDOW (win)) 
2562                 modest_ui_actions_on_main_window_move_to (action, 
2563                                                           MODEST_MAIN_WINDOW (win));
2564         else
2565                 modest_ui_actions_on_msg_view_window_move_to (action, 
2566                                                               MODEST_MSG_VIEW_WINDOW (win));
2567 }
2568
2569 /*
2570  * Calls #HeadersFunc for each header already selected in the main
2571  * window or the message currently being shown in the msg view window
2572  */
2573 static void
2574 do_headers_action (ModestWindow *win, 
2575                    HeadersFunc func,
2576                    gpointer user_data)
2577 {
2578         TnyList *headers_list;
2579         TnyIterator *iter;
2580
2581         /* Get headers */
2582         headers_list = get_selected_headers (win);
2583         if (!headers_list)
2584                 return;
2585
2586         /* Call the function for each header */
2587         iter = tny_list_create_iterator (headers_list);
2588         while (!tny_iterator_is_done (iter)) {
2589                 TnyHeader *header;
2590
2591                 header = TNY_HEADER (tny_iterator_get_current (iter));
2592                 func (header, win, user_data);
2593                 g_object_unref (header);
2594                 tny_iterator_next (iter);
2595         }
2596         g_object_unref (iter);
2597 }
2598
2599 void 
2600 modest_ui_actions_view_attachment (GtkAction *action,
2601                                    ModestWindow *window)
2602 {
2603         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2604                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
2605         } else {
2606                 /* not supported window for this action */
2607                 g_return_if_reached ();
2608         }
2609 }
2610
2611 void
2612 modest_ui_actions_save_attachments (GtkAction *action,
2613                                     ModestWindow *window)
2614 {
2615         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2616                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
2617         } else {
2618                 /* not supported window for this action */
2619                 g_return_if_reached ();
2620         }
2621 }
2622
2623 void
2624 modest_ui_actions_remove_attachments (GtkAction *action,
2625                                       ModestWindow *window)
2626 {
2627         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2628                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
2629         } else {
2630                 /* not supported window for this action */
2631                 g_return_if_reached ();
2632         }
2633 }
2634
2635 void 
2636 modest_ui_actions_on_settings (GtkAction *action, 
2637                                ModestWindow *win)
2638 {
2639         GtkWidget *dialog;
2640
2641         dialog = modest_platform_get_global_settings_dialog ();
2642         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
2643         gtk_widget_show (dialog);
2644
2645         gtk_dialog_run (GTK_DIALOG (dialog));
2646
2647         gtk_widget_destroy (dialog);
2648 }