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