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