77886d76be0bf0939e17000357b273a9ce69b090
[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         GtkTreeIter iter;
97         TnyFolder *folder;
98 } HeaderActivatedHelper;
99
100 /*
101  * The do_headers_action uses this kind of functions to perform some
102  * action to each member of a list of headers
103  */
104 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
105
106 static void
107 do_headers_action (ModestWindow *win, 
108                    HeadersFunc func,
109                    gpointer user_data);
110
111
112 static void     open_msg_func          (const GObject *obj, const TnyMsg *msg, gpointer user_data);
113
114 static void     reply_forward_func     (const GObject *obj, const TnyMsg *msg, gpointer user_data);
115
116 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
117
118 static gchar*   ask_for_folder_name    (GtkWindow *parent_window, const gchar *title);
119
120 void   
121 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
122 {
123         GtkWidget *about;
124         const gchar *authors[] = {
125                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
126                 NULL
127         };
128         about = gtk_about_dialog_new ();
129         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
130         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
131         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
132                                         _("Copyright (c) 2006, Nokia Corporation\n"
133                                           "All rights reserved."));
134         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
135                                        _("a modest e-mail client\n\n"
136                                          "design and implementation: Dirk-Jan C. Binnema\n"
137                                          "contributions from the fine people at KC and Ig\n"
138                                          "uses the tinymail email framework written by Philip van Hoof"));
139         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
140         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
141         
142         gtk_dialog_run (GTK_DIALOG (about));
143         gtk_widget_destroy(about);
144 }
145
146
147 static TnyList *
148 get_selected_headers (ModestWindow *win)
149 {
150         if (MODEST_IS_MAIN_WINDOW(win)) {
151                 GtkWidget *header_view;         
152                 
153                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
154                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
155                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
156                 
157         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
158                 /* for MsgViewWindows, we simply return a list with one element */
159                 TnyMsg *msg;
160                 TnyHeader *header;
161                 TnyList *list = NULL;
162                 
163                 msg  = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
164                 if (msg) {
165                         header = tny_msg_get_header (msg);
166                         list = tny_simple_list_new ();
167                         tny_list_prepend (list, G_OBJECT(header));
168                         g_object_unref (G_OBJECT(header));
169                 }
170                 return list;
171
172         } else
173                 return NULL;
174 }
175
176 static void
177 headers_action_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->iter);
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         g_slice_free (HeaderActivatedHelper, helper);
491 }
492
493 static void
494 reply_forward_func (const GObject *obj, const TnyMsg *msg, gpointer user_data)
495 {
496         TnyMsg *new_msg;
497         ReplyForwardHelper *rf_helper;
498         ModestWindow *msg_win;
499         ModestEditType edit_type;
500         gchar *from;
501         GError *err = NULL;
502         TnyFolder *folder = NULL;
503         TnyAccount *account = NULL;
504         ModestWindowMgr *mgr;
505         gchar *signature = NULL;
506                         
507         g_return_if_fail (user_data != NULL);
508         rf_helper = (ReplyForwardHelper *) user_data;
509
510         rf_helper->pending_ops--;
511
512         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
513                                                    rf_helper->account_name);
514         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
515                                          rf_helper->account_name,
516                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
517                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
518                                                            rf_helper->account_name,
519                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
520         }
521
522         /* Create reply mail */
523         switch (rf_helper->action) {
524         case ACTION_REPLY:
525                 new_msg = 
526                         modest_tny_msg_create_reply_msg ((TnyMsg *) msg,  from, signature,
527                                                          rf_helper->reply_forward_type,
528                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
529                 break;
530         case ACTION_REPLY_TO_ALL:
531                 new_msg = 
532                         modest_tny_msg_create_reply_msg ((TnyMsg *) msg, from, signature, rf_helper->reply_forward_type,
533                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
534                 edit_type = MODEST_EDIT_TYPE_REPLY;
535                 break;
536         case ACTION_FORWARD:
537                 new_msg = 
538                         modest_tny_msg_create_forward_msg ((TnyMsg *) msg, from, signature, rf_helper->reply_forward_type);
539                 edit_type = MODEST_EDIT_TYPE_FORWARD;
540                 break;
541         default:
542                 g_return_if_reached ();
543                 return;
544         }
545
546         g_free (signature);
547
548         if (!new_msg) {
549                 g_printerr ("modest: failed to create message\n");
550                 goto cleanup;
551         }
552
553         account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
554                                                                        rf_helper->account_name,
555                                                                        TNY_ACCOUNT_TYPE_STORE);
556         if (!account) {
557                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
558                 goto cleanup;
559         }
560
561         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
562         if (!folder) {
563                 g_printerr ("modest: failed to find Drafts folder\n");
564                 goto cleanup;
565         }
566         
567         tny_folder_add_msg (folder, (TnyMsg *) msg, &err);
568         if (err) {
569                 g_printerr ("modest: error adding msg to Drafts folder: %s",
570                             err->message);
571                 g_error_free (err);
572                 goto cleanup;
573         }       
574
575         /* Create and register the windows */                   
576         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
577         mgr = modest_runtime_get_window_mgr ();
578         modest_window_mgr_register_window (mgr, msg_win);
579
580         /* Show edit window */
581         gtk_widget_show_all (GTK_WIDGET (msg_win));
582
583 cleanup:
584         if (new_msg)
585                 g_object_unref (G_OBJECT (new_msg));
586         if (folder)
587                 g_object_unref (G_OBJECT (folder));
588         if (account)
589                 g_object_unref (G_OBJECT (account));
590         
591         if (rf_helper->pending_ops == 0) {
592                 g_free (rf_helper->account_name);
593                 g_slice_free (ReplyForwardHelper, rf_helper);
594         }
595 }
596 /*
597  * Common code for the reply and forward actions
598  */
599 static void
600 reply_forward (ReplyForwardAction action, ModestWindow *win)
601 {
602         ModestMailOperation *mail_op = NULL;
603         TnyList *header_list = NULL;
604         ReplyForwardHelper *rf_helper = NULL;
605         guint reply_forward_type;
606         
607         g_return_if_fail (MODEST_IS_WINDOW(win));
608
609         header_list = get_selected_headers (win);
610         if (!header_list)
611                 return;
612         
613         reply_forward_type = modest_conf_get_int (modest_runtime_get_conf (),
614                                                   (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
615                                                   NULL);
616         /* We assume that we can only select messages of the
617            same folder and that we reply all of them from the
618            same account. In fact the interface currently only
619            allows single selection */
620         
621         /* Fill helpers */
622         rf_helper = g_slice_new0 (ReplyForwardHelper);
623         rf_helper->reply_forward_type = reply_forward_type;
624         rf_helper->action = action;
625         rf_helper->pending_ops = tny_list_get_length (header_list);
626         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
627         if (!rf_helper->account_name)
628                 rf_helper->account_name =
629                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
630
631         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
632                 TnyMsg *msg;
633                 msg = modest_msg_view_window_get_message(MODEST_MSG_VIEW_WINDOW(win));
634                 if (!msg) {
635                         g_printerr ("modest: no message found\n");
636                         return;
637                 } else
638                         reply_forward_func (G_OBJECT(win), msg, rf_helper);
639         } else {
640                                 
641                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
642                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
643                 modest_mail_operation_process_msg (mail_op, header_list, reply_forward_func, rf_helper);
644
645                 /* Clean */
646                 g_object_unref(mail_op);
647         }
648 }
649
650 void
651 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
652 {
653         g_return_if_fail (MODEST_IS_WINDOW(win));
654
655         reply_forward (ACTION_REPLY, win);
656 }
657
658 void
659 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
660 {
661         g_return_if_fail (MODEST_IS_WINDOW(win));
662
663         reply_forward (ACTION_FORWARD, win);
664 }
665
666 void
667 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
668 {
669         g_return_if_fail (MODEST_IS_WINDOW(win));
670
671         reply_forward (ACTION_REPLY_TO_ALL, win);
672 }
673
674 void 
675 modest_ui_actions_on_next (GtkAction *action, 
676                            ModestWindow *window)
677 {
678         if (MODEST_IS_MAIN_WINDOW (window)) {
679                 GtkWidget *header_view;
680
681                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
682                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
683                 if (!header_view)
684                         return;
685         
686                 modest_header_view_select_next (MODEST_HEADER_VIEW(header_view)); 
687         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
688                 modest_msg_view_window_select_next_message (MODEST_MSG_VIEW_WINDOW (window));
689         } else {
690                 g_return_if_reached ();
691         }
692 }
693
694 void 
695 modest_ui_actions_on_prev (GtkAction *action, 
696                            ModestWindow *window)
697 {
698         g_return_if_fail (MODEST_IS_WINDOW(window));
699
700         if (MODEST_IS_MAIN_WINDOW (window)) {
701                 GtkWidget *header_view;
702                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
703                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
704                 if (!header_view)
705                         return;
706                 
707                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
708         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
709                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
710         } else {
711                 g_return_if_reached ();
712         }
713 }
714
715 void 
716 modest_ui_actions_on_sort (GtkAction *action, 
717                            ModestWindow *window)
718 {
719         g_return_if_fail (MODEST_IS_WINDOW(window));
720
721         if (MODEST_IS_MAIN_WINDOW (window)) {
722                 GtkWidget *header_view;
723                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
724                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
725                 if (!header_view)
726                         return;
727
728                 /* Show sorting dialog */
729                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
730         }
731 }
732
733
734 static gboolean
735 action_send (const gchar* account_name)
736 {
737         TnyAccount *tny_account;
738         ModestTnySendQueue *send_queue;
739
740         g_return_val_if_fail (account_name, FALSE);
741
742         /* Get the transport account according to the open connection, 
743          * because the account might specify connection-specific SMTP servers.
744          */
745         tny_account = 
746                 modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
747                                                                      account_name);
748         if (!tny_account) {
749                 g_printerr ("modest: cannot get tny transport account for %s\n", account_name);
750                 return FALSE;
751         }
752         
753         send_queue = modest_tny_send_queue_new (TNY_CAMEL_TRANSPORT_ACCOUNT(tny_account));
754         if (!send_queue) {
755                 g_object_unref (G_OBJECT(tny_account));
756                 g_printerr ("modest: cannot get send queue for %s\n", account_name);
757                 return FALSE;
758         }
759         
760         modest_tny_send_queue_flush (send_queue);
761
762         g_object_unref (G_OBJECT(send_queue));
763         g_object_unref (G_OBJECT(tny_account));
764
765         return TRUE;
766 }
767
768
769 static gboolean
770 action_receive (const gchar* account_name, 
771                 ModestWindow *win)
772 {
773         TnyAccount *tny_account;
774         ModestMailOperation *mail_op;
775
776         g_return_val_if_fail (account_name, FALSE);
777
778         tny_account = 
779                 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
780                                                                      account_name,
781                                                                      TNY_ACCOUNT_TYPE_STORE);
782         if (!tny_account) {
783                 g_printerr ("modest: cannot get tny store account for %s\n", account_name);
784                 return FALSE;
785         }
786
787         /* Create the mail operation */
788         /* TODO: The spec wants us to first do any pending deletions, before receiving. */
789         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
790         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
791         modest_mail_operation_update_account (mail_op, TNY_STORE_ACCOUNT(tny_account));
792
793         g_object_unref (G_OBJECT(tny_account));
794         g_object_unref (G_OBJECT (mail_op));
795                 
796         return TRUE;
797 }
798
799 /** Check that an appropriate connection is open.
800  */
801 gboolean check_for_connection (const gchar *account_name)
802 {
803         TnyDevice *device = modest_runtime_get_device ();
804
805 /*
806         g_assert (TNY_IS_MAEMO_CONIC_DEVICE (device));
807         
808         TnyMaemoConicDevice *maemo_device = TNY_MAEMO_CONIC_DEVICE (device);
809 */
810         
811         if (tny_device_is_online (device))
812                 return TRUE;
813         else {
814                 modest_platform_connect_and_wait (NULL);
815                 
816                 /* TODO: Wait until a result. */
817                 return TRUE;
818         }
819 }
820
821 /*
822  * This function performs the send & receive required actions. The
823  * window it's used to create the mail operation. Tipically it should
824  * be allways the main window, but we pass it as argument in order to
825  * be more flexible.
826  */
827 void
828 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
829 {
830         gchar *acc_name = NULL;
831
832         /* If no account name was provided get the current account, if
833            there is none either then pick the default one */
834         if (!account_name) {
835                 acc_name = g_strdup (modest_window_get_active_account(win));
836                 if (!acc_name)
837                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
838                 if (!acc_name) {
839                         g_printerr ("modest: cannot get default account\n");
840                         return;
841                 }
842         } else {
843                 acc_name = g_strdup (account_name);
844         }
845
846         /* Send & receive. Do not continue if no suitable connection
847            is open */
848         if (check_for_connection (acc_name)) {
849                 /* As per the UI spec,
850                  * for POP accounts, we should receive,
851                  * for IMAP we should synchronize everything, including receiving,
852                  * for SMTP we should send,
853                  * first receiving, then sending:
854                  */
855                 if (!action_receive(acc_name, win))
856                         g_printerr ("modest: failed to receive\n");
857                 if (!action_send(acc_name))
858                         g_printerr ("modest: failed to send\n");
859         }
860         /* Free */
861         g_free (acc_name);
862 }
863
864 /*
865  * Refreshes all accounts. This function will be used by automatic
866  * updates
867  */
868 void
869 modest_ui_actions_do_send_receive_all (ModestWindow *win)
870 {
871         GSList *account_names, *iter;
872
873         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
874                                                           TRUE);
875
876         iter = account_names;
877         while (iter) {                  
878                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
879                 iter = g_slist_next (iter);
880         }
881         
882         g_slist_foreach (account_names, (GFunc) g_free, NULL);
883         g_slist_free (account_names);
884 }
885
886 /*
887  * Handler of the click on Send&Receive button in the main toolbar
888  */
889 void
890 modest_ui_actions_on_send_receive (GtkAction *action,  ModestWindow *win)
891 {
892         /* Check that at least one account exists: */
893         GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
894                                 TRUE /* enabled accounts only */);
895         gboolean accounts_exist = account_names != NULL;
896         g_slist_free (account_names);
897         
898         /* If not, allow the user to create an account before trying to send/receive. */
899         if (!accounts_exist)
900                 modest_ui_actions_on_accounts (NULL, win);
901         
902         /* Refresh the active account */
903         modest_ui_actions_do_send_receive (NULL, win);
904 }
905
906
907 void
908 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
909 {
910         ModestConf *conf;
911         GtkWidget *header_view;
912         
913         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
914
915         header_view = modest_main_window_get_child_widget (main_window,
916                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
917         if (!header_view)
918                 return;
919
920         conf = modest_runtime_get_conf ();
921         
922         /* what is saved/restored is depending on the style; thus; we save with
923          * old style, then update the style, and restore for this new style
924          */
925         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
926         
927         if (modest_header_view_get_style
928             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
929                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
930                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
931         else
932                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
933                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
934
935         modest_widget_memory_restore (conf, G_OBJECT(header_view),
936                                       MODEST_CONF_HEADER_VIEW_KEY);
937 }
938
939
940 void 
941 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
942                                       TnyHeader *header,
943                                       ModestMainWindow *main_window)
944 {
945         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
946
947         /* If no header has been selected then exit */
948         if (!header)
949                 return;
950
951         /* Update Main window title */
952         if (GTK_WIDGET_HAS_FOCUS (header_view)) {
953                 const gchar *subject = tny_header_get_subject (header);
954                 if (subject && strcmp (subject, ""))
955                         gtk_window_set_title (GTK_WINDOW (main_window), subject);
956                 else
957                         gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
958         }
959 }
960
961 void
962 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
963                                        TnyHeader *header,
964                                        ModestMainWindow *main_window)
965 {
966         ModestMailOperation *mail_op = NULL;
967         HeaderActivatedHelper *helper = NULL;
968         ModestWindowMgr *mgr = NULL;
969         ModestWindow *win = NULL;
970         GtkTreeModel *model = NULL;
971         GtkTreeIter iter;
972         GtkTreeSelection *sel = NULL;
973         GList *sel_list = NULL;
974         GList *tmp = NULL;
975         
976         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
977         
978         if (!header)
979                 return;
980
981         /* Look if we already have a message view for that header */
982         mgr = modest_runtime_get_window_mgr ();
983         win = modest_window_mgr_find_window_by_msguid (mgr, tny_header_get_uid (header));
984         if (win) return;
985
986         /* Build helper */
987         helper = g_slice_new0 (HeaderActivatedHelper);
988         helper->folder = tny_header_get_folder (header);
989         helper->model = NULL;
990
991         /* Get headers tree model and selected iter to build message view */
992         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
993         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
994         if (sel_list != NULL) {
995                 gtk_tree_model_get_iter (model, &iter, (GtkTreePath *) sel_list->data);
996                 
997                 /* Fill helpers */
998                 helper->model = model;
999                 helper->iter = iter;
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 /*                                                                              MODEST_INFORMATION_CREATE_FOLDER); */
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         /* Ask the user */      
1578         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
1579                                     tny_folder_get_name (TNY_FOLDER (folder)));
1580         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window), 
1581                                                             (const gchar *) message);
1582         g_free (message);
1583
1584         if (response == GTK_RESPONSE_OK) {
1585                 ModestMailOperation *mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_DELETE, G_OBJECT(main_window));
1586
1587                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1588                                                  mail_op);
1589                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
1590
1591                 /* Show error if happened */
1592                 if (modest_mail_operation_get_error (mail_op))
1593                         modest_platform_run_information_dialog (GTK_WINDOW (main_window),
1594                                                                 MODEST_INFORMATION_DELETE_FOLDER);
1595
1596                 g_object_unref (G_OBJECT (mail_op));
1597         }
1598
1599         g_object_unref (G_OBJECT (folder));
1600 }
1601
1602 void 
1603 modest_ui_actions_on_delete_folder (GtkAction *action,
1604                                      ModestMainWindow *main_window)
1605 {
1606         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1607
1608         delete_folder (main_window, FALSE);
1609 }
1610
1611 void 
1612 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1613 {
1614         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1615         
1616         delete_folder (main_window, TRUE);
1617 }
1618
1619 void
1620 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
1621                                          const gchar* server_account_name,
1622                                          gchar **username,
1623                                          gchar **password, 
1624                                          gboolean *cancel, 
1625                                          gboolean *remember,
1626                                          ModestMainWindow *main_window)
1627 {
1628         g_return_if_fail(server_account_name);
1629         /* printf("DEBUG: %s: server_account_name=%s\n", __FUNCTION__, server_account_name); */
1630         
1631 #ifdef MODEST_PLATFORM_MAEMO
1632         /* Maemo uses a different (awkward) button order,
1633          * It should probably just use gtk_alternative_dialog_button_order ().
1634          */
1635         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
1636                                               NULL,
1637                                               GTK_DIALOG_MODAL,
1638                                               GTK_STOCK_OK,
1639                                               GTK_RESPONSE_ACCEPT,
1640                                               GTK_STOCK_CANCEL,
1641                                               GTK_RESPONSE_REJECT,
1642                                               NULL);
1643 #else
1644         GtkWidget *dialog = gtk_dialog_new_with_buttons (_("mail_ti_password_protected"),
1645                                               NULL,
1646                                               GTK_DIALOG_MODAL,
1647                                               GTK_STOCK_CANCEL,
1648                                               GTK_RESPONSE_REJECT,
1649                                               GTK_STOCK_OK,
1650                                               GTK_RESPONSE_ACCEPT,
1651                                               NULL);
1652 #endif /* MODEST_PLATFORM_MAEMO */
1653
1654         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1655         
1656         gchar *server_name = modest_server_account_get_hostname (
1657                 modest_runtime_get_account_mgr(), server_account_name);
1658         
1659         /* This causes a warning because the logical ID has no %s in it, 
1660          * though the translation does, but there is not much we can do about that: */
1661         gchar *txt = g_strdup_printf (_("mail_ia_password_info"), server_name);
1662         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1663                             FALSE, FALSE, 0);
1664         g_free (txt);
1665         g_free (server_name);
1666         server_name = NULL;
1667
1668         /* username: */
1669         gchar *initial_username = modest_server_account_get_username (
1670                 modest_runtime_get_account_mgr(), server_account_name);
1671         
1672         GtkWidget *entry_username = gtk_entry_new ();
1673         if (initial_username)
1674                 gtk_entry_set_text (GTK_ENTRY (entry_username), initial_username);
1675         /* Dim this if a connection has ever succeeded with this username,
1676          * as per the UI spec: */
1677         const gboolean username_known = 
1678                 modest_server_account_get_username_has_succeeded(
1679                         modest_runtime_get_account_mgr(), server_account_name);
1680         gtk_widget_set_sensitive (entry_username, !username_known);
1681         
1682 #ifdef MODEST_PLATFORM_MAEMO
1683         /* Auto-capitalization is the default, so let's turn it off: */
1684         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_username), HILDON_GTK_INPUT_MODE_FULL);
1685         
1686         /* Create a size group to be used by all captions.
1687          * Note that HildonCaption does not create a default size group if we do not specify one.
1688          * We use GTK_SIZE_GROUP_HORIZONTAL, so that the widths are the same. */
1689         GtkSizeGroup *sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
1690         
1691         GtkWidget *caption = hildon_caption_new (sizegroup, 
1692                 _("mail_fi_username"), entry_username, NULL, HILDON_CAPTION_MANDATORY);
1693         gtk_widget_show (entry_username);
1694         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
1695                 FALSE, FALSE, MODEST_MARGIN_HALF);
1696         gtk_widget_show (caption);
1697 #else 
1698         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_username,
1699                             TRUE, FALSE, 0);
1700 #endif /* MODEST_PLATFORM_MAEMO */      
1701                             
1702         /* password: */
1703         GtkWidget *entry_password = gtk_entry_new ();
1704         gtk_entry_set_visibility (GTK_ENTRY(entry_password), FALSE);
1705         /* gtk_entry_set_invisible_char (GTK_ENTRY(entry_password), "*"); */
1706         
1707 #ifdef MODEST_PLATFORM_MAEMO
1708         /* Auto-capitalization is the default, so let's turn it off: */
1709         hildon_gtk_entry_set_input_mode (GTK_ENTRY (entry_password), 
1710                 HILDON_GTK_INPUT_MODE_FULL | HILDON_GTK_INPUT_MODE_INVISIBLE);
1711         
1712         caption = hildon_caption_new (sizegroup, 
1713                 _("mail_fi_password"), entry_password, NULL, HILDON_CAPTION_MANDATORY);
1714         gtk_widget_show (entry_password);
1715         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), caption, 
1716                 FALSE, FALSE, MODEST_MARGIN_HALF);
1717         gtk_widget_show (caption);
1718         g_object_unref (sizegroup);
1719 #else 
1720         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry_password,
1721                             TRUE, FALSE, 0);
1722 #endif /* MODEST_PLATFORM_MAEMO */      
1723                                 
1724 /* This is not in the Maemo UI spec:
1725         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1726         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1727                             TRUE, FALSE, 0);
1728 */
1729
1730         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1731         
1732         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1733                 if (username) {
1734                         *username = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_username)));
1735                         
1736                         modest_server_account_set_username (
1737                                  modest_runtime_get_account_mgr(), server_account_name, 
1738                                  *username);
1739                                  
1740                         const gboolean username_was_changed = 
1741                                 (strcmp (*username, initial_username) != 0);
1742                         if (username_was_changed) {
1743                                 /* To actually use a changed username, 
1744                                  * we must reset the connection, according to pvanhoof.
1745                                  * This _might_ be a sensible way to do that: */
1746                                  TnyDevice *device = modest_runtime_get_device();
1747                                  tny_device_force_offline (device);
1748                                  tny_device_force_online (device);
1749                         }
1750                 }
1751                         
1752                 if (password) {
1753                         *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry_password)));
1754                         
1755                         /* We do not save the password in the configuration, 
1756                          * because this function is only called for passwords that should 
1757                          * not be remembered:
1758                         modest_server_account_set_password (
1759                                  modest_runtime_get_account_mgr(), server_account_name, 
1760                                  *password);
1761                         */
1762                 }
1763                 
1764                 if (cancel)
1765                         *cancel   = FALSE;
1766                         
1767         } else {
1768                 if (username)
1769                         *username = NULL;
1770                         
1771                 if (password)
1772                         *password = NULL;
1773                         
1774                 if (cancel)
1775                         *cancel   = TRUE;
1776         }
1777
1778 /* This is not in the Maemo UI spec:
1779         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
1780                 *remember = TRUE;
1781         else
1782                 *remember = FALSE;
1783 */
1784
1785         gtk_widget_destroy (dialog);
1786 }
1787
1788 void
1789 modest_ui_actions_on_cut (GtkAction *action,
1790                           ModestWindow *window)
1791 {
1792         GtkWidget *focused_widget;
1793
1794         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1795         if (GTK_IS_EDITABLE (focused_widget)) {
1796                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
1797         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1798                 GtkTextBuffer *buffer;
1799                 GtkClipboard *clipboard;
1800
1801                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1802                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1803                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
1804         }
1805 }
1806
1807 void
1808 modest_ui_actions_on_copy (GtkAction *action,
1809                            ModestWindow *window)
1810 {
1811         GtkClipboard *clipboard;
1812         GtkWidget *focused_widget;
1813
1814         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1815         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1816         if (GTK_IS_LABEL (focused_widget)) {
1817                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
1818         } else if (GTK_IS_EDITABLE (focused_widget)) {
1819                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
1820         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1821                 GtkTextBuffer *buffer;
1822
1823                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1824                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
1825         }
1826 }
1827
1828 void
1829 modest_ui_actions_on_undo (GtkAction *action,
1830                            ModestWindow *window)
1831 {
1832         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
1833                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
1834         } else {
1835                 g_return_if_reached ();
1836         }
1837 }
1838
1839 void
1840 modest_ui_actions_on_paste (GtkAction *action,
1841                             ModestWindow *window)
1842 {
1843         GtkWidget *focused_widget;
1844
1845         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1846         if (GTK_IS_EDITABLE (focused_widget)) {
1847                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
1848         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1849                 GtkTextBuffer *buffer;
1850                 GtkClipboard *clipboard;
1851
1852                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1853                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1854                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
1855         }
1856 }
1857
1858 void
1859 modest_ui_actions_on_select_all (GtkAction *action,
1860                                  ModestWindow *window)
1861 {
1862         GtkWidget *focused_widget;
1863
1864         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1865         if (MODEST_IS_ATTACHMENTS_VIEW (focused_widget)) {
1866                 modest_attachments_view_select_all (MODEST_ATTACHMENTS_VIEW (focused_widget));
1867         } else if (GTK_IS_LABEL (focused_widget)) {
1868                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
1869         } else if (GTK_IS_EDITABLE (focused_widget)) {
1870                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
1871         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1872                 GtkTextBuffer *buffer;
1873                 GtkTextIter start, end;
1874
1875                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1876                 gtk_text_buffer_get_start_iter (buffer, &start);
1877                 gtk_text_buffer_get_end_iter (buffer, &end);
1878                 gtk_text_buffer_select_range (buffer, &start, &end);
1879         }
1880 }
1881
1882 void
1883 modest_ui_actions_on_mark_as_read (GtkAction *action,
1884                                    ModestWindow *window)
1885 {       
1886         g_return_if_fail (MODEST_IS_WINDOW(window));
1887                 
1888         /* Mark each header as read */
1889         do_headers_action (window, headers_action_mark_as_read, NULL);
1890 }
1891
1892 void
1893 modest_ui_actions_on_mark_as_unread (GtkAction *action,
1894                                      ModestWindow *window)
1895 {       
1896         g_return_if_fail (MODEST_IS_WINDOW(window));
1897                 
1898         /* Mark each header as read */
1899         do_headers_action (window, headers_action_mark_as_unread, NULL);
1900 }
1901
1902 void
1903 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
1904                                   GtkRadioAction *selected,
1905                                   ModestWindow *window)
1906 {
1907         gint value;
1908
1909         value = gtk_radio_action_get_current_value (selected);
1910         if (MODEST_IS_WINDOW (window)) {
1911                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
1912         }
1913 }
1914
1915 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
1916                                                         GtkRadioAction *selected,
1917                                                         ModestWindow *window)
1918 {
1919         TnyHeaderFlags flags;
1920         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1921
1922         flags = gtk_radio_action_get_current_value (selected);
1923         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
1924 }
1925
1926 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
1927                                                            GtkRadioAction *selected,
1928                                                            ModestWindow *window)
1929 {
1930         gint file_format;
1931
1932         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1933
1934         file_format = gtk_radio_action_get_current_value (selected);
1935         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
1936 }
1937
1938
1939 void     
1940 modest_ui_actions_on_zoom_plus (GtkAction *action,
1941                                 ModestWindow *window)
1942 {
1943         g_return_if_fail (MODEST_IS_WINDOW (window));
1944
1945         modest_window_zoom_plus (MODEST_WINDOW (window));
1946 }
1947
1948 void     
1949 modest_ui_actions_on_zoom_minus (GtkAction *action,
1950                                  ModestWindow *window)
1951 {
1952         g_return_if_fail (MODEST_IS_WINDOW (window));
1953
1954         modest_window_zoom_minus (MODEST_WINDOW (window));
1955 }
1956
1957 void     
1958 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
1959                                            ModestWindow *window)
1960 {
1961         ModestWindowMgr *mgr;
1962         gboolean fullscreen, active;
1963         g_return_if_fail (MODEST_IS_WINDOW (window));
1964
1965         mgr = modest_runtime_get_window_mgr ();
1966
1967         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
1968         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1969
1970         if (active != fullscreen) {
1971                 modest_window_mgr_set_fullscreen_mode (mgr, active);
1972                 gtk_window_present (GTK_WINDOW (window));
1973         }
1974 }
1975
1976 void
1977 modest_ui_actions_on_change_fullscreen (GtkAction *action,
1978                                         ModestWindow *window)
1979 {
1980         ModestWindowMgr *mgr;
1981         gboolean fullscreen;
1982
1983         g_return_if_fail (MODEST_IS_WINDOW (window));
1984
1985         mgr = modest_runtime_get_window_mgr ();
1986         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1987         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
1988
1989         gtk_window_present (GTK_WINDOW (window));
1990 }
1991
1992 /* 
1993  * Used by modest_ui_actions_on_details to call do_headers_action 
1994  */
1995 static void
1996 headers_action_show_details (TnyHeader *header, 
1997                              ModestWindow *window,
1998                              gpointer user_data)
1999
2000 {
2001         GtkWidget *dialog;
2002         
2003         /* Create dialog */
2004         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
2005
2006         /* Run dialog */
2007         gtk_widget_show_all (dialog);
2008         gtk_dialog_run (GTK_DIALOG (dialog));
2009
2010         gtk_widget_destroy (dialog);
2011 }
2012
2013 /*
2014  * Show the folder details in a ModestDetailsDialog widget
2015  */
2016 static void
2017 show_folder_details (TnyFolder *folder, 
2018                      GtkWindow *window)
2019 {
2020         GtkWidget *dialog;
2021         
2022         /* Create dialog */
2023         dialog = modest_details_dialog_new_with_folder (window, folder);
2024
2025         /* Run dialog */
2026         gtk_widget_show_all (dialog);
2027         gtk_dialog_run (GTK_DIALOG (dialog));
2028
2029         gtk_widget_destroy (dialog);
2030 }
2031
2032 /*
2033  * Show the header details in a ModestDetailsDialog widget
2034  */
2035 void     
2036 modest_ui_actions_on_details (GtkAction *action, 
2037                               ModestWindow *win)
2038 {
2039         TnyList * headers_list;
2040         TnyIterator *iter;
2041         TnyHeader *header;              
2042
2043         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
2044                 TnyMsg *msg;
2045
2046                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
2047                 if (!msg) {
2048                         return;
2049                 } else {
2050                         headers_list = get_selected_headers (win);
2051                         if (!headers_list)
2052                                 return;
2053
2054                         iter = tny_list_create_iterator (headers_list);
2055
2056                         header = TNY_HEADER (tny_iterator_get_current (iter));
2057                         headers_action_show_details (header, win, NULL);
2058                         g_object_unref (header);
2059
2060                         g_object_unref (iter);
2061                 }
2062         } else if (MODEST_IS_MAIN_WINDOW (win)) {
2063                 GtkWidget *folder_view, *header_view;
2064
2065                 /* Check which widget has the focus */
2066                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2067                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
2068                 if (gtk_widget_is_focus (folder_view)) {
2069                         TnyFolder *folder;
2070
2071                         folder = (TnyFolder *) modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2072
2073                         /* Show only when it's a folder */
2074                         if (!folder || !TNY_IS_FOLDER (folder))
2075                                 return;
2076
2077                         show_folder_details (folder, GTK_WINDOW (win));
2078
2079                 } else {
2080                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
2081                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
2082                         /* Show details of each header */
2083                         do_headers_action (win, headers_action_show_details, header_view);
2084                 }
2085         }
2086 }
2087
2088 void     
2089 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
2090                                      ModestMsgEditWindow *window)
2091 {
2092         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2093
2094         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
2095 }
2096
2097 void     
2098 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
2099                                       ModestMsgEditWindow *window)
2100 {
2101         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2102
2103         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
2104 }
2105
2106 void
2107 modest_ui_actions_toggle_folders_view (GtkAction *action, 
2108                                        ModestMainWindow *main_window)
2109 {
2110         ModestConf *conf;
2111         
2112         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2113
2114         conf = modest_runtime_get_conf ();
2115         
2116         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
2117                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
2118         else
2119                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
2120 }
2121
2122 void 
2123 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
2124                                      ModestWindow *window)
2125 {
2126         gboolean active, fullscreen = FALSE;
2127         ModestWindowMgr *mgr;
2128
2129         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
2130
2131         /* Check if we want to toggle the toolbar vuew in fullscreen
2132            or normal mode */
2133         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
2134                      "ViewShowToolbarFullScreen")) {
2135                 fullscreen = TRUE;
2136         }
2137
2138         /* Toggle toolbar */
2139         mgr = modest_runtime_get_window_mgr ();
2140         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
2141 }
2142
2143 void     
2144 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
2145                                            ModestMsgEditWindow *window)
2146 {
2147         modest_msg_edit_window_select_font (window);
2148 }
2149
2150 void
2151 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
2152                                                   const gchar *display_name,
2153                                                   GtkWindow *window)
2154 {
2155         /* Do not change the application name if the widget has not
2156            the focus. This callback could be called even if the folder
2157            view has not the focus, because the handled signal could be
2158            emitted when the folder view is redrawn */
2159         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
2160                 if (display_name)
2161                         gtk_window_set_title (window, display_name);
2162                 else
2163                         gtk_window_set_title (window, " ");
2164         }
2165 }
2166
2167 void
2168 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
2169 {
2170         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2171         modest_msg_edit_window_select_contacts (window);
2172 }
2173
2174 void
2175 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
2176 {
2177         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2178         modest_msg_edit_window_check_names (window);
2179 }
2180
2181
2182 static GtkWidget*
2183 create_move_to_dialog (ModestWindow *win,
2184                        GtkWidget *folder_view,
2185                        GtkWidget **tree_view)
2186 {
2187         GtkWidget *dialog, *scroll;
2188
2189         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2190                                               GTK_WINDOW (win),
2191                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
2192                                               GTK_STOCK_OK,
2193                                               GTK_RESPONSE_ACCEPT,
2194                                               GTK_STOCK_CANCEL,
2195                                               GTK_RESPONSE_REJECT,
2196                                               NULL);
2197
2198         /* Create scrolled window */
2199         scroll = gtk_scrolled_window_new (NULL, NULL);
2200         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
2201                                          GTK_POLICY_AUTOMATIC,
2202                                          GTK_POLICY_AUTOMATIC);
2203
2204         /* Create folder view */
2205         *tree_view = modest_folder_view_new (NULL);
2206         gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
2207                                  gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
2208         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
2209
2210         /* Add scroll to dialog */
2211         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
2212                             scroll, FALSE, FALSE, 0);
2213
2214         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2215
2216         return dialog;
2217 }
2218
2219 /*
2220  * Returns TRUE if at least one of the headers of the list belongs to
2221  * a message that has been fully retrieved.
2222  */
2223 static gboolean
2224 has_retrieved_msgs (TnyList *list)
2225 {
2226         TnyIterator *iter;
2227         gboolean found = FALSE;
2228
2229         iter = tny_list_create_iterator (list);
2230         while (tny_iterator_is_done (iter) && !found) {
2231                 TnyHeader *header;
2232                 TnyHeaderFlags flags;
2233
2234                 header = TNY_HEADER (tny_iterator_get_current (iter));
2235                 flags = tny_header_get_flags (header);
2236                 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
2237                         found = TRUE;
2238
2239                 if (!found)
2240                         tny_iterator_next (iter);
2241         }
2242         g_object_unref (iter);
2243
2244         return found;
2245 }
2246
2247 /*
2248  * Shows a confirmation dialog to the user when we're moving messages
2249  * from a remote server to the local storage. Returns the dialog
2250  * response. If it's other kind of movement the it always returns
2251  * GTK_RESPONSE_OK
2252  */
2253 static gint
2254 msgs_move_to_confirmation (GtkWindow *win,
2255                            TnyFolder *dest_folder,
2256                            TnyList *headers)
2257 {
2258         gint response = GTK_RESPONSE_OK;
2259
2260         /* If the destination is a local folder */
2261         if (modest_tny_folder_is_local_folder (dest_folder)) {
2262                 TnyFolder *src_folder;
2263                 TnyIterator *iter;
2264                 TnyHeader *header;
2265
2266                 /* Get source folder */
2267                 iter = tny_list_create_iterator (headers);
2268                 header = TNY_HEADER (tny_iterator_get_current (iter));
2269                 src_folder = tny_header_get_folder (header);
2270                 g_object_unref (header);
2271                 g_object_unref (iter);
2272
2273                 /* If the source is a remote folder */
2274                 if (!modest_tny_folder_is_local_folder (src_folder)) {
2275                         const gchar *message;
2276                         
2277                         if (tny_list_get_length (headers) == 1)
2278                                 if (has_retrieved_msgs (headers))
2279                                         message = _("mcen_nc_move_retrieve");
2280                                 else
2281                                         message = _("mcen_nc_move_header");
2282                         else
2283                                 if (has_retrieved_msgs (headers))
2284                                         message = _("mcen_nc_move_retrieves");
2285                                 else
2286                                         message = _("mcen_nc_move_headers");
2287                         
2288                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
2289                                                                             (const gchar *) message);
2290                 }
2291         }
2292         return response;
2293 }
2294
2295 /*
2296  * UI handler for the "Move to" action when invoked from the
2297  * ModestMainWindow
2298  */
2299 static void 
2300 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
2301                                           ModestMainWindow *win)
2302 {
2303         GtkWidget *dialog, *folder_view, *tree_view = NULL;
2304         gint result;
2305         TnyFolderStore *folder_store;
2306         ModestMailOperation *mail_op = NULL;
2307
2308         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
2309
2310         /* Get the folder view */
2311         folder_view = modest_main_window_get_child_widget (win,
2312                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2313
2314         /* Create and run the dialog */
2315         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);
2316         result = gtk_dialog_run (GTK_DIALOG(dialog));
2317
2318         /* We do this to save an indentation level ;-) */
2319         if (result != GTK_RESPONSE_ACCEPT)
2320                 goto end;
2321
2322         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2323
2324         if (TNY_IS_ACCOUNT (folder_store))
2325                 goto end;
2326
2327         /* Get folder or messages to transfer */
2328         if (gtk_widget_is_focus (folder_view)) {
2329                 TnyFolderStore *src_folder;
2330                 src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2331
2332                 if (TNY_IS_FOLDER (src_folder)) {
2333                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
2334                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2335                                                          mail_op);
2336
2337                         modest_mail_operation_xfer_folder (mail_op, 
2338                                                            TNY_FOLDER (src_folder),
2339                                                            folder_store,
2340                                                            TRUE);
2341                         g_object_unref (G_OBJECT (mail_op));
2342                 }
2343
2344                 /* Frees */
2345                 g_object_unref (G_OBJECT (src_folder));
2346         } else {
2347                 GtkWidget *header_view;
2348                 header_view = modest_main_window_get_child_widget (win,
2349                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
2350                 if (gtk_widget_is_focus (header_view)) {
2351                         TnyList *headers;
2352                         gint response;
2353
2354                         headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
2355
2356                         /* Ask for user confirmation */
2357                         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2358                                                               TNY_FOLDER (folder_store), 
2359                                                               headers);
2360
2361                         /* Transfer messages */
2362                         if (response == GTK_RESPONSE_OK) {
2363                                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
2364                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2365                                                                  mail_op);
2366
2367                                 modest_mail_operation_xfer_msgs (mail_op, 
2368                                                                  headers,
2369                                                                  TNY_FOLDER (folder_store),
2370                                                                  TRUE);
2371                                 g_object_unref (G_OBJECT (mail_op));
2372                         }
2373                 }
2374         }
2375         g_object_unref (folder_store);
2376
2377  end:
2378         gtk_widget_destroy (dialog);
2379 }
2380
2381
2382 /*
2383  * UI handler for the "Move to" action when invoked from the
2384  * ModestMsgViewWindow
2385  */
2386 static void 
2387 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
2388                                               ModestMsgViewWindow *win)
2389 {
2390         GtkWidget *dialog, *folder_view, *tree_view = NULL;
2391         gint result;
2392         ModestMainWindow *main_window;
2393         TnyMsg *msg;
2394         TnyHeader *header;
2395         TnyList *headers;
2396
2397         /* Get the folder view */
2398         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2399         folder_view = modest_main_window_get_child_widget (main_window,
2400                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2401
2402         /* Create and run the dialog */
2403         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);  
2404         result = gtk_dialog_run (GTK_DIALOG(dialog));
2405
2406         if (result == GTK_RESPONSE_ACCEPT) {
2407                 TnyFolderStore *folder_store;
2408                 gint response;
2409
2410                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2411
2412                 /* Create header list */
2413                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
2414                 header = tny_msg_get_header (msg);
2415                 headers = tny_simple_list_new ();
2416                 tny_list_prepend (headers, G_OBJECT (header));
2417                 g_object_unref (header);
2418                 g_object_unref (msg);
2419
2420                 /* Ask user for confirmation. MSG-NOT404 */
2421                 response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2422                                                       TNY_FOLDER (folder_store), 
2423                                                       headers);
2424
2425                 /* Transfer current msg */
2426                 if (response == GTK_RESPONSE_OK) {
2427                         ModestMailOperation *mail_op;
2428
2429                         /* Create mail op */
2430                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
2431                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2432                                                          mail_op);
2433                         
2434                         /* Transfer messages */
2435                         modest_mail_operation_xfer_msgs (mail_op, 
2436                                                          headers,
2437                                                          TNY_FOLDER (folder_store),
2438                                                          TRUE);
2439                         g_object_unref (G_OBJECT (mail_op));
2440                 } else {
2441                         g_object_unref (headers);
2442                 }
2443                 g_object_unref (folder_store);
2444         }
2445         gtk_widget_destroy (dialog);
2446 }
2447
2448 void 
2449 modest_ui_actions_on_move_to (GtkAction *action, 
2450                               ModestWindow *win)
2451 {
2452         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
2453                           MODEST_IS_MSG_VIEW_WINDOW (win));
2454
2455         if (MODEST_IS_MAIN_WINDOW (win)) 
2456                 modest_ui_actions_on_main_window_move_to (action, 
2457                                                           MODEST_MAIN_WINDOW (win));
2458         else
2459                 modest_ui_actions_on_msg_view_window_move_to (action, 
2460                                                               MODEST_MSG_VIEW_WINDOW (win));
2461 }
2462
2463 /*
2464  * Calls #HeadersFunc for each header already selected in the main
2465  * window or the message currently being shown in the msg view window
2466  */
2467 static void
2468 do_headers_action (ModestWindow *win, 
2469                    HeadersFunc func,
2470                    gpointer user_data)
2471 {
2472         TnyList *headers_list;
2473         TnyIterator *iter;
2474
2475         /* Get headers */
2476         headers_list = get_selected_headers (win);
2477         if (!headers_list)
2478                 return;
2479
2480         /* Call the function for each header */
2481         iter = tny_list_create_iterator (headers_list);
2482         while (!tny_iterator_is_done (iter)) {
2483                 TnyHeader *header;
2484
2485                 header = TNY_HEADER (tny_iterator_get_current (iter));
2486                 func (header, win, user_data);
2487                 g_object_unref (header);
2488                 tny_iterator_next (iter);
2489         }
2490         g_object_unref (iter);
2491 }
2492
2493 void 
2494 modest_ui_actions_view_attachment (GtkAction *action,
2495                                    ModestWindow *window)
2496 {
2497         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2498                 modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (window), NULL);
2499         } else {
2500                 /* not supported window for this action */
2501                 g_return_if_reached ();
2502         }
2503 }
2504
2505 void
2506 modest_ui_actions_save_attachments (GtkAction *action,
2507                                     ModestWindow *window)
2508 {
2509         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2510                 modest_msg_view_window_save_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
2511         } else {
2512                 /* not supported window for this action */
2513                 g_return_if_reached ();
2514         }
2515 }
2516
2517 void
2518 modest_ui_actions_remove_attachments (GtkAction *action,
2519                                       ModestWindow *window)
2520 {
2521         if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
2522                 modest_msg_view_window_remove_attachments (MODEST_MSG_VIEW_WINDOW (window), NULL);
2523         } else {
2524                 /* not supported window for this action */
2525                 g_return_if_reached ();
2526         }
2527 }
2528
2529 void 
2530 modest_ui_actions_on_settings (GtkAction *action, 
2531                                ModestWindow *win)
2532 {
2533         GtkWidget *dialog;
2534         gint response;
2535
2536         dialog = modest_platform_get_global_settings_dialog ();
2537         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
2538         gtk_widget_show (dialog);
2539
2540         response = gtk_dialog_run (GTK_DIALOG (dialog));
2541
2542         if (response == GTK_RESPONSE_ACCEPT) {
2543                 g_message ("YES");
2544         }
2545
2546         gtk_widget_destroy (dialog);
2547 }