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