* Move mark_as_read call from on_header_activated
[modest] / src / modest-ui-actions.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif /*HAVE_CONFIG_H*/
33
34 #include <glib/gi18n.h>
35 #include <string.h>
36 #include <modest-runtime.h>
37 #include <modest-tny-folder.h>
38 #include <modest-tny-msg.h>
39 #include <modest-tny-account.h>
40 #include <modest-address-book.h>
41
42 #include "modest-ui-actions.h"
43
44 #include "modest-tny-platform-factory.h"
45 #include "modest-platform.h"
46
47 #ifdef MODEST_PLATFORM_MAEMO
48 #include "maemo/modest-osso-state-saving.h"
49 #endif /* MODEST_PLATFORM_MAEMO */
50
51 #include "widgets/modest-ui-constants.h"
52 #include <widgets/modest-main-window.h>
53 #include <widgets/modest-msg-view-window.h>
54 #include <widgets/modest-account-view-window.h>
55 #include <widgets/modest-details-dialog.h>
56 #include <widgets/modest-attachments-view.h>
57 #include "widgets/modest-global-settings-dialog.h"
58 #include "modest-account-mgr-helpers.h"
59 #include "modest-mail-operation.h"
60 #include "modest-text-utils.h"
61
62 #ifdef MODEST_HAVE_EASYSETUP
63 #include "easysetup/modest-easysetup-wizard.h"
64 #endif /* MODEST_HAVE_EASYSETUP */
65
66 #include <modest-widget-memory.h>
67 #include <tny-error.h>
68 #include <tny-simple-list.h>
69 #include <tny-msg-view.h>
70 #include <tny-device.h>
71
72 typedef struct _GetMsgAsyncHelper {     
73         ModestWindow *window;
74         ModestMailOperation *mail_op;
75         TnyIterator *iter;
76         guint num_ops;
77         GFunc func;     
78         gpointer user_data;
79 } GetMsgAsyncHelper;
80
81 typedef enum _ReplyForwardAction {
82         ACTION_REPLY,
83         ACTION_REPLY_TO_ALL,
84         ACTION_FORWARD
85 } ReplyForwardAction;
86
87 typedef struct _ReplyForwardHelper {
88 guint reply_forward_type;
89         ReplyForwardAction action;
90         gchar *account_name;
91         guint pending_ops;
92 } ReplyForwardHelper;
93
94 typedef struct _HeaderActivatedHelper {
95         GtkTreeModel *model;
96         GtkTreeRowReference *row_reference;
97         TnyFolder *folder;
98         TnyHeader *header;
99 } HeaderActivatedHelper;
100
101 /*
102  * The do_headers_action uses this kind of functions to perform some
103  * action to each member of a list of headers
104  */
105 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
106
107 static void
108 do_headers_action (ModestWindow *win, 
109                    HeadersFunc func,
110                    gpointer user_data);
111
112
113 static void     open_msg_func          (const GObject *obj, const TnyMsg *msg, gpointer user_data);
114
115 static void     reply_forward_func     (const GObject *obj, const TnyMsg *msg, gpointer user_data);
116
117 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
118
119 static gchar*   ask_for_folder_name    (GtkWindow *parent_window, const gchar *title);
120
121 void   
122 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
123 {
124         GtkWidget *about;
125         const gchar *authors[] = {
126                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
127                 NULL
128         };
129         about = gtk_about_dialog_new ();
130         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
131         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
132         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
133                                         _("Copyright (c) 2006, Nokia Corporation\n"
134                                           "All rights reserved."));
135         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
136                                        _("a modest e-mail client\n\n"
137                                          "design and implementation: Dirk-Jan C. Binnema\n"
138                                          "contributions from the fine people at KC and Ig\n"
139                                          "uses the tinymail email framework written by Philip van Hoof"));
140         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
141         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
142         
143         gtk_dialog_run (GTK_DIALOG (about));
144         gtk_widget_destroy(about);
145 }
146
147
148 static TnyList *
149 get_selected_headers (ModestWindow *win)
150 {
151         if (MODEST_IS_MAIN_WINDOW(win)) {
152                 GtkWidget *header_view;         
153                 
154                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
155                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
156                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
157                 
158         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
159                 /* for MsgViewWindows, we simply return a list with one element */
160                 TnyMsg *msg;
161                 TnyHeader *header;
162                 TnyList *list = NULL;
163                 
164                 msg  = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
165                 if (msg) {
166                         header = tny_msg_get_header (msg);
167                         list = tny_simple_list_new ();
168                         tny_list_prepend (list, G_OBJECT(header));
169                         g_object_unref (G_OBJECT(header));
170                 }
171                 return list;
172
173         } else
174                 return NULL;
175 }
176
177 static void
178 headers_action_mark_as_read (TnyHeader *header,
179                              ModestWindow *win,
180                              gpointer user_data)
181 {
182         TnyHeaderFlags flags;
183
184         g_return_if_fail (TNY_IS_HEADER(header));
185
186         flags = tny_header_get_flags (header);
187         if (flags & TNY_HEADER_FLAG_SEEN) return;
188         tny_header_set_flags (header, TNY_HEADER_FLAG_SEEN);
189 }
190
191 static void
192 headers_action_mark_as_unread (TnyHeader *header,
193                                ModestWindow *win,
194                                gpointer user_data)
195 {
196         TnyHeaderFlags flags;
197
198         g_return_if_fail (TNY_IS_HEADER(header));
199
200         flags = tny_header_get_flags (header);
201         if (flags & TNY_HEADER_FLAG_SEEN)  {
202                 tny_header_unset_flags (header, TNY_HEADER_FLAG_SEEN);
203         }
204 }
205
206
207 static void
208 headers_action_delete (TnyHeader *header,
209                        ModestWindow *win,
210                        gpointer user_data)
211 {
212         ModestMailOperation *mail_op;
213
214         /* TODO: add confirmation dialog */
215         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_DELETE, G_OBJECT(win));
216         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
217                                          mail_op);
218
219         /* Always delete. TODO: Move to trash still not supported */
220         modest_mail_operation_remove_msg (mail_op, header, FALSE);
221         g_object_unref (G_OBJECT (mail_op));
222 }
223
224 void
225 modest_ui_actions_on_delete (GtkAction *action, ModestWindow *win)
226 {
227         g_return_if_fail (MODEST_IS_WINDOW(win));
228
229         if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
230                 gboolean ret_value;
231                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
232                 return;
233         }
234                 
235         /* Remove each header */
236         do_headers_action (win, headers_action_delete, NULL);
237
238         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
239                 gtk_widget_destroy (GTK_WIDGET(win));
240         } 
241 }
242
243
244 void
245 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
246 {
247         #ifdef MODEST_PLATFORM_MAEMO
248         modest_osso_save_state();
249         #endif /* MODEST_PLATFORM_MAEMO */
250         
251         gtk_main_quit ();
252 }
253
254 void
255 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
256 {
257         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
258                 gtk_widget_destroy (GTK_WIDGET (win));
259         } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
260                 gboolean ret_value;
261                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
262         } else if (MODEST_IS_WINDOW (win)) {
263                 gtk_widget_destroy (GTK_WIDGET (win));
264         } else {
265                 g_return_if_reached ();
266         }
267 }
268
269 void
270 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
271 {
272         GtkClipboard *clipboard = NULL;
273         gchar *selection = NULL;
274
275         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
276         selection = gtk_clipboard_wait_for_text (clipboard);
277
278         modest_address_book_add_address (selection);
279         g_free (selection);
280 }
281
282 void
283 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
284 {
285         
286         /* This is currently only implemented for Maemo,
287          * because it requires a providers preset file which is not publically available.
288          */
289 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
290         GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
291                                 TRUE /* enabled accounts only */);
292         gboolean accounts_exist = account_names != NULL;
293         g_slist_free (account_names);
294         
295         if (!accounts_exist) {
296                 /* If there are no accounts yet, just show the easy-setup wizard, as per the UI spec: */
297                 ModestEasysetupWizardDialog *wizard = modest_easysetup_wizard_dialog_new ();
298                 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
299                 gtk_dialog_run (GTK_DIALOG (wizard));
300                 gtk_widget_destroy (GTK_WIDGET (wizard));
301         } else  {
302                 /* Show the list of accounts: */
303                 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
304                 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW(win));
305                 gtk_dialog_run (account_win);
306                 gtk_widget_destroy (GTK_WIDGET(account_win));
307         }
308 #else
309         GtkWidget *dialog, *label;
310         
311         /* Create the widgets */
312         
313         dialog = gtk_dialog_new_with_buttons ("Message",
314                                               GTK_WINDOW(win),
315                                               GTK_DIALOG_DESTROY_WITH_PARENT,
316                                               GTK_STOCK_OK,
317                                               GTK_RESPONSE_NONE,
318                                               NULL);
319         label = gtk_label_new ("Hello World!");
320         
321         /* Ensure that the dialog box is destroyed when the user responds. */
322         
323         g_signal_connect_swapped (dialog, "response", 
324                                   G_CALLBACK (gtk_widget_destroy),
325                                   dialog);
326         
327         /* Add the label, and show everything we've added to the dialog. */
328         
329         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
330                            label);
331         gtk_widget_show_all (dialog);
332 #endif /* MODEST_PLATFORM_MAEMO */
333 }
334
335 void
336 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
337 {
338         ModestWindow *msg_win;
339         TnyMsg *msg = NULL;
340         TnyFolder *folder = NULL;
341         gchar *account_name = NULL;
342         gchar *from_str = NULL;
343 /*      GError *err = NULL; */
344         TnyAccount *account = NULL;
345         ModestWindowMgr *mgr;
346         gchar *signature = NULL;
347         
348         account_name = g_strdup(modest_window_get_active_account (win));
349         if (!account_name)
350                 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
351         if (!account_name) {
352                 g_printerr ("modest: no account found\n");
353                 goto cleanup;
354         }
355         
356         account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
357                                                                        account_name,
358                                                                        TNY_ACCOUNT_TYPE_STORE);
359         if (!account) {
360                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
361                 goto cleanup;
362         }
363
364         from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
365         if (!from_str) {
366                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
367                 goto cleanup;
368         }
369
370         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr (), account_name,
371                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
372                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), account_name,
373                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
374         } else {
375                 signature = g_strdup ("");
376         }
377
378         msg = modest_tny_msg_new ("", from_str, "", "", "", signature, NULL);
379         if (!msg) {
380                 g_printerr ("modest: failed to create new msg\n");
381                 goto cleanup;
382         }
383         
384         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
385         if (!folder) {
386                 g_printerr ("modest: failed to find Drafts folder\n");
387                 goto cleanup;
388         }
389         
390 /*      tny_folder_add_msg (folder, msg, &err); */
391 /*      if (err) { */
392 /*              g_printerr ("modest: error adding msg to Drafts folder: %s", */
393 /*                          err->message); */
394 /*              g_error_free (err); */
395 /*              goto cleanup; */
396 /*      } */
397
398         /* Create and register edit window */
399         msg_win = modest_msg_edit_window_new (msg, account_name);
400         mgr = modest_runtime_get_window_mgr ();
401         modest_window_mgr_register_window (mgr, msg_win);
402
403         if (win)
404                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
405                                               GTK_WINDOW (win));        
406         gtk_widget_show_all (GTK_WIDGET (msg_win));
407
408 cleanup:
409         g_free (account_name);
410         g_free (from_str);
411         g_free (signature);
412         if (account)
413                 g_object_unref (G_OBJECT(account));
414         if (msg)
415                 g_object_unref (G_OBJECT(msg));
416         if (folder)
417                 g_object_unref (G_OBJECT(folder));
418 }
419
420 static void
421 headers_action_open (TnyHeader *header, 
422                      ModestWindow *win, 
423                      gpointer user_data)
424 {
425         modest_ui_actions_on_header_activated (MODEST_HEADER_VIEW (user_data), 
426                                                header,
427                                                MODEST_MAIN_WINDOW (win));
428 }
429
430 void
431 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
432 {
433         GtkWidget *header_view;
434
435         /* Get header view */
436         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
437                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
438
439         /* Open each message */
440         do_headers_action (win, headers_action_open, header_view);
441 }
442
443
444 static void
445 open_msg_func (const GObject *obj, const TnyMsg *msg, gpointer user_data)
446 {
447         ModestWindowMgr *mgr = NULL;
448         ModestWindow *parent_win = NULL;
449         ModestWindow *win = NULL;
450         HeaderActivatedHelper *helper = NULL;
451         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
452         gchar *account = NULL;
453         
454         g_return_if_fail (MODEST_IS_WINDOW(obj));
455         g_return_if_fail (user_data != NULL);
456         parent_win = MODEST_WINDOW(obj);
457         helper = (HeaderActivatedHelper *) user_data;
458
459         /* Mark header as read */
460         headers_action_mark_as_read (helper->header, MODEST_WINDOW(parent_win), NULL);
461
462         /* Get account */
463         account =  g_strdup(modest_window_get_active_account(MODEST_WINDOW(parent_win)));
464         if (!account)
465                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
466         
467         /* Gets foldert type (OUTBOX headers will be opened in edit window */
468         if (modest_tny_folder_is_local_folder (helper->folder))
469                 folder_type = modest_tny_folder_get_local_folder_type (helper->folder);
470
471         switch (folder_type) {
472         case TNY_FOLDER_TYPE_DRAFTS:
473                 win = modest_msg_edit_window_new ((TnyMsg *) msg, account);
474                 break;
475         default:
476                 if (helper->model != NULL)
477                         win = modest_msg_view_window_new_with_header_model ((TnyMsg *) msg, account, helper->model, helper->row_reference);
478                 else
479                         win = modest_msg_view_window_new ((TnyMsg *) msg, account);
480         }
481         
482         /* Register and show new window */
483         if (win != NULL) {
484                 mgr = modest_runtime_get_window_mgr ();
485                 modest_window_mgr_register_window (mgr, win);
486                 gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent_win));
487                 gtk_widget_show_all (GTK_WIDGET(win));
488         }
489
490         /* Free */
491         g_free(account);
492 /*      g_object_unref (G_OBJECT(msg)); */
493         g_object_unref (G_OBJECT(helper->folder));
494         g_object_unref (G_OBJECT(helper->header));
495         gtk_tree_row_reference_free (helper->row_reference);
496         g_slice_free (HeaderActivatedHelper, helper);
497 }
498
499 static void
500 reply_forward_func (const GObject *obj, const TnyMsg *msg, gpointer user_data)
501 {
502         TnyMsg *new_msg;
503         ReplyForwardHelper *rf_helper;
504         ModestWindow *msg_win;
505         ModestEditType edit_type;
506         gchar *from;
507         GError *err = NULL;
508         TnyFolder *folder = NULL;
509         TnyAccount *account = NULL;
510         ModestWindowMgr *mgr;
511         gchar *signature = NULL;
512                         
513         g_return_if_fail (user_data != NULL);
514         rf_helper = (ReplyForwardHelper *) user_data;
515
516         rf_helper->pending_ops--;
517
518         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
519                                                    rf_helper->account_name);
520         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
521                                          rf_helper->account_name,
522                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
523                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
524                                                            rf_helper->account_name,
525                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
526         }
527
528         /* Create reply mail */
529         switch (rf_helper->action) {
530         case ACTION_REPLY:
531                 new_msg = 
532                         modest_tny_msg_create_reply_msg ((TnyMsg *) msg,  from, signature,
533                                                          rf_helper->reply_forward_type,
534                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
535                 break;
536         case ACTION_REPLY_TO_ALL:
537                 new_msg = 
538                         modest_tny_msg_create_reply_msg ((TnyMsg *) msg, from, signature, rf_helper->reply_forward_type,
539                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
540                 edit_type = MODEST_EDIT_TYPE_REPLY;
541                 break;
542         case ACTION_FORWARD:
543                 new_msg = 
544                         modest_tny_msg_create_forward_msg ((TnyMsg *) msg, from, signature, rf_helper->reply_forward_type);
545                 edit_type = MODEST_EDIT_TYPE_FORWARD;
546                 break;
547         default:
548                 g_return_if_reached ();
549                 return;
550         }
551
552         g_free (signature);
553
554         if (!new_msg) {
555                 g_printerr ("modest: failed to create message\n");
556                 goto cleanup;
557         }
558
559         account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
560                                                                        rf_helper->account_name,
561                                                                        TNY_ACCOUNT_TYPE_STORE);
562         if (!account) {
563                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
564                 goto cleanup;
565         }
566
567         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
568         if (!folder) {
569                 g_printerr ("modest: failed to find Drafts folder\n");
570                 goto cleanup;
571         }
572         
573         tny_folder_add_msg (folder, (TnyMsg *) msg, &err);
574         if (err) {
575                 g_printerr ("modest: error adding msg to Drafts folder: %s",
576                             err->message);
577                 g_error_free (err);
578                 goto cleanup;
579         }       
580
581         /* Create and register the windows */                   
582         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
583         mgr = modest_runtime_get_window_mgr ();
584         modest_window_mgr_register_window (mgr, msg_win);
585
586         /* Show edit window */
587         gtk_widget_show_all (GTK_WIDGET (msg_win));
588
589 cleanup:
590         if (new_msg)
591                 g_object_unref (G_OBJECT (new_msg));
592         if (folder)
593                 g_object_unref (G_OBJECT (folder));
594         if (account)
595                 g_object_unref (G_OBJECT (account));
596         
597         if (rf_helper->pending_ops == 0) {
598                 g_free (rf_helper->account_name);
599                 g_slice_free (ReplyForwardHelper, rf_helper);
600         }
601 }
602 /*
603  * Common code for the reply and forward actions
604  */
605 static void
606 reply_forward (ReplyForwardAction action, ModestWindow *win)
607 {
608         ModestMailOperation *mail_op = NULL;
609         TnyList *header_list = NULL;
610         ReplyForwardHelper *rf_helper = NULL;
611         guint reply_forward_type;
612         
613         g_return_if_fail (MODEST_IS_WINDOW(win));
614
615         header_list = get_selected_headers (win);
616         if (!header_list)
617                 return;
618         
619         reply_forward_type = modest_conf_get_int (modest_runtime_get_conf (),
620                                                   (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
621                                                   NULL);
622         /* We assume that we can only select messages of the
623            same folder and that we reply all of them from the
624            same account. In fact the interface currently only
625            allows single selection */
626         
627         /* Fill helpers */
628         rf_helper = g_slice_new0 (ReplyForwardHelper);
629         rf_helper->reply_forward_type = reply_forward_type;
630         rf_helper->action = action;
631         rf_helper->pending_ops = tny_list_get_length (header_list);
632         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
633         if (!rf_helper->account_name)
634                 rf_helper->account_name =
635                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
636
637         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
638                 TnyMsg *msg;
639                 msg = modest_msg_view_window_get_message(MODEST_MSG_VIEW_WINDOW(win));
640                 if (!msg) {
641                         g_printerr ("modest: no message found\n");
642                         return;
643                 } else
644                         reply_forward_func (G_OBJECT(win), msg, rf_helper);
645         } else {
646                                 
647                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
648                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
649                 modest_mail_operation_process_msg (mail_op, header_list, reply_forward_func, rf_helper);
650
651                 /* Clean */
652                 g_object_unref(mail_op);
653         }
654 }
655
656 void
657 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
658 {
659         g_return_if_fail (MODEST_IS_WINDOW(win));
660
661         reply_forward (ACTION_REPLY, win);
662 }
663
664 void
665 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
666 {
667         g_return_if_fail (MODEST_IS_WINDOW(win));
668
669         reply_forward (ACTION_FORWARD, win);
670 }
671
672 void
673 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
674 {
675         g_return_if_fail (MODEST_IS_WINDOW(win));
676
677         reply_forward (ACTION_REPLY_TO_ALL, win);
678 }
679
680 void 
681 modest_ui_actions_on_next (GtkAction *action, 
682                            ModestWindow *window)
683 {
684         if (MODEST_IS_MAIN_WINDOW (window)) {
685                 GtkWidget *header_view;
686
687                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
688                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
689                 if (!header_view)
690                         return;
691         
692                 modest_header_view_select_next (MODEST_HEADER_VIEW(header_view)); 
693         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
694                 modest_msg_view_window_select_next_message (MODEST_MSG_VIEW_WINDOW (window));
695         } else {
696                 g_return_if_reached ();
697         }
698 }
699
700 void 
701 modest_ui_actions_on_prev (GtkAction *action, 
702                            ModestWindow *window)
703 {
704         g_return_if_fail (MODEST_IS_WINDOW(window));
705
706         if (MODEST_IS_MAIN_WINDOW (window)) {
707                 GtkWidget *header_view;
708                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
709                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
710                 if (!header_view)
711                         return;
712                 
713                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
714         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
715                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
716         } else {
717                 g_return_if_reached ();
718         }
719 }
720
721 void 
722 modest_ui_actions_on_sort (GtkAction *action, 
723                            ModestWindow *window)
724 {
725         g_return_if_fail (MODEST_IS_WINDOW(window));
726
727         if (MODEST_IS_MAIN_WINDOW (window)) {
728                 GtkWidget *header_view;
729                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
730                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
731                 if (!header_view)
732                         return;
733
734                 /* Show sorting dialog */
735                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
736         }
737 }
738
739
740 static gboolean
741 action_send (const gchar* account_name)
742 {
743         TnyAccount *tny_account;
744         ModestTnySendQueue *send_queue;
745
746         g_return_val_if_fail (account_name, FALSE);
747
748         /* Get the transport account according to the open connection, 
749          * because the account might specify connection-specific SMTP servers.
750          */
751         tny_account = 
752                 modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
753                                                                      account_name);
754         if (!tny_account) {
755                 g_printerr ("modest: cannot get tny transport account for %s\n", account_name);
756                 return FALSE;
757         }
758         
759         send_queue = modest_tny_send_queue_new (TNY_CAMEL_TRANSPORT_ACCOUNT(tny_account));
760         if (!send_queue) {
761                 g_object_unref (G_OBJECT(tny_account));
762                 g_printerr ("modest: cannot get send queue for %s\n", account_name);
763                 return FALSE;
764         }
765         
766         modest_tny_send_queue_flush (send_queue);
767
768         g_object_unref (G_OBJECT(send_queue));
769         g_object_unref (G_OBJECT(tny_account));
770
771         return TRUE;
772 }
773
774
775 static gboolean
776 action_receive (const gchar* account_name, 
777                 ModestWindow *win)
778 {
779         TnyAccount *tny_account;
780         ModestMailOperation *mail_op;
781
782         g_return_val_if_fail (account_name, FALSE);
783
784         tny_account = 
785                 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
786                                                                      account_name,
787                                                                      TNY_ACCOUNT_TYPE_STORE);
788         if (!tny_account) {
789                 g_printerr ("modest: cannot get tny store account for %s\n", account_name);
790                 return FALSE;
791         }
792
793         /* Create the mail operation */
794         /* TODO: The spec wants us to first do any pending deletions, before receiving. */
795         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
796         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
797         modest_mail_operation_update_account (mail_op, TNY_STORE_ACCOUNT(tny_account));
798
799         g_object_unref (G_OBJECT(tny_account));
800         g_object_unref (G_OBJECT (mail_op));
801                 
802         return TRUE;
803 }
804
805 /** Check that an appropriate connection is open.
806  */
807 gboolean check_for_connection (const gchar *account_name)
808 {
809         TnyDevice *device = modest_runtime_get_device ();
810
811 /*
812         g_assert (TNY_IS_MAEMO_CONIC_DEVICE (device));
813         
814         TnyMaemoConicDevice *maemo_device = TNY_MAEMO_CONIC_DEVICE (device);
815 */
816         
817         if (tny_device_is_online (device))
818                 return TRUE;
819         else {
820                 modest_platform_connect_and_wait (NULL);
821                 
822                 /* TODO: Wait until a result. */
823                 return TRUE;
824         }
825 }
826
827 /*
828  * This function performs the send & receive required actions. The
829  * window it's used to create the mail operation. Tipically it should
830  * be allways the main window, but we pass it as argument in order to
831  * be more flexible.
832  */
833 void
834 modest_ui_actions_do_send_receive (const gchar *account_name, ModestWindow *win)
835 {
836         gchar *acc_name = NULL;
837
838         /* If no account name was provided get the current account, if
839            there is none either then pick the default one */
840         if (!account_name) {
841                 acc_name = g_strdup (modest_window_get_active_account(win));
842                 if (!acc_name)
843                         acc_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
844                 if (!acc_name) {
845                         g_printerr ("modest: cannot get default account\n");
846                         return;
847                 }
848         } else {
849                 acc_name = g_strdup (account_name);
850         }
851
852         /* Send & receive. Do not continue if no suitable connection
853            is open */
854         if (check_for_connection (acc_name)) {
855                 /* As per the UI spec,
856                  * for POP accounts, we should receive,
857                  * for IMAP we should synchronize everything, including receiving,
858                  * for SMTP we should send,
859                  * first receiving, then sending:
860                  */
861                 if (!action_receive(acc_name, win))
862                         g_printerr ("modest: failed to receive\n");
863                 if (!action_send(acc_name))
864                         g_printerr ("modest: failed to send\n");
865         }
866         /* Free */
867         g_free (acc_name);
868 }
869
870 /*
871  * Refreshes all accounts. This function will be used by automatic
872  * updates
873  */
874 void
875 modest_ui_actions_do_send_receive_all (ModestWindow *win)
876 {
877         GSList *account_names, *iter;
878
879         account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
880                                                           TRUE);
881
882         iter = account_names;
883         while (iter) {                  
884                 modest_ui_actions_do_send_receive ((const char*) iter->data, win);
885                 iter = g_slist_next (iter);
886         }
887         
888         g_slist_foreach (account_names, (GFunc) g_free, NULL);
889         g_slist_free (account_names);
890 }
891
892 /*
893  * Handler of the click on Send&Receive button in the main toolbar
894  */
895 void
896 modest_ui_actions_on_send_receive (GtkAction *action,  ModestWindow *win)
897 {
898         /* Check that at least one account exists: */
899         GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
900                                 TRUE /* enabled accounts only */);
901         gboolean accounts_exist = account_names != NULL;
902         g_slist_free (account_names);
903         
904         /* If not, allow the user to create an account before trying to send/receive. */
905         if (!accounts_exist)
906                 modest_ui_actions_on_accounts (NULL, win);
907         
908         /* Refresh the active account */
909         modest_ui_actions_do_send_receive (NULL, win);
910 }
911
912
913 void
914 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
915 {
916         ModestConf *conf;
917         GtkWidget *header_view;
918         
919         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
920
921         header_view = modest_main_window_get_child_widget (main_window,
922                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
923         if (!header_view)
924                 return;
925
926         conf = modest_runtime_get_conf ();
927         
928         /* what is saved/restored is depending on the style; thus; we save with
929          * old style, then update the style, and restore for this new style
930          */
931         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
932         
933         if (modest_header_view_get_style
934             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
935                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
936                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
937         else
938                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
939                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
940
941         modest_widget_memory_restore (conf, G_OBJECT(header_view),
942                                       MODEST_CONF_HEADER_VIEW_KEY);
943 }
944
945
946 void 
947 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
948                                       TnyHeader *header,
949                                       ModestMainWindow *main_window)
950 {
951         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
952
953         /* If no header has been selected then exit */
954         if (!header)
955                 return;
956
957         /* Update Main window title */
958         if (GTK_WIDGET_HAS_FOCUS (header_view)) {
959                 const gchar *subject = tny_header_get_subject (header);
960                 if (subject && strcmp (subject, ""))
961                         gtk_window_set_title (GTK_WINDOW (main_window), subject);
962                 else
963                         gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
964         }
965 }
966
967 void
968 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
969                                        TnyHeader *header,
970                                        ModestMainWindow *main_window)
971 {
972         ModestMailOperation *mail_op = NULL;
973         HeaderActivatedHelper *helper = NULL;
974         ModestWindowMgr *mgr = NULL;
975         ModestWindow *win = NULL;
976         GtkTreeModel *model = NULL;
977         GtkTreeSelection *sel = NULL;
978         GList *sel_list = NULL;
979         
980         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
981         
982         if (!header)
983                 return;
984
985         /* Look if we already have a message view for that header */
986         mgr = modest_runtime_get_window_mgr ();
987         win = modest_window_mgr_find_window_by_msguid (mgr, tny_header_get_uid (header));
988         if (win) return;
989
990         /* Build helper */
991         helper = g_slice_new0 (HeaderActivatedHelper);
992         helper->folder = tny_header_get_folder (header);
993         helper->header = g_object_ref(header);
994         helper->model = NULL;
995
996         /* Get headers tree model and selected row reference to build message view */
997         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
998         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
999         if (sel_list != NULL) {
1000                 
1001                 /* Fill helpers */
1002                 helper->model = model;
1003                 helper->row_reference = gtk_tree_row_reference_new (model, (GtkTreePath *) sel_list->data);
1004
1005                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
1006                 g_list_free (sel_list);
1007         }
1008
1009         /* New mail operation */
1010         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(main_window));
1011         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1012         modest_mail_operation_get_msg (mail_op, header, open_msg_func, helper);
1013
1014         /* Free */
1015         g_object_unref (mail_op);
1016 }
1017
1018 void 
1019 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1020                                                TnyFolderStore *folder_store, 
1021                                                gboolean selected,
1022                                                ModestMainWindow *main_window)
1023 {
1024         ModestConf *conf;
1025         GtkWidget *header_view;
1026         
1027         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1028
1029         header_view = modest_main_window_get_child_widget(main_window,
1030                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
1031         if (!header_view)
1032                 return;
1033         
1034         conf = modest_runtime_get_conf ();
1035
1036         if (TNY_IS_FOLDER (folder_store)) {
1037
1038                 if (selected) {
1039                         modest_main_window_set_contents_style (main_window, 
1040                                                                MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1041                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1042                                                        TNY_FOLDER (folder_store));
1043                         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1044                                                       MODEST_CONF_HEADER_VIEW_KEY);
1045                 } else {
1046                         modest_widget_memory_save (conf, G_OBJECT (header_view), MODEST_CONF_HEADER_VIEW_KEY);
1047                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
1048                 }
1049         } else if (TNY_IS_ACCOUNT (folder_store)) {
1050
1051                 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1052         }
1053 }
1054
1055 void 
1056 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1057                                      ModestWindow *win)
1058 {
1059         GtkWidget *dialog;
1060         gchar *txt, *item;
1061         gboolean online;
1062
1063         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1064         
1065         if (g_main_depth > 0)   
1066                 gdk_threads_enter ();
1067         online = tny_device_is_online (modest_runtime_get_device());
1068
1069         if (online) {
1070                 /* already online -- the item is simply not there... */
1071                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1072                                                  GTK_DIALOG_MODAL,
1073                                                  GTK_MESSAGE_WARNING,
1074                                                  GTK_BUTTONS_OK,
1075                                                  _("The %s you selected cannot be found"),
1076                                                  item);
1077                 gtk_dialog_run (GTK_DIALOG(dialog));
1078         } else {
1079                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1080                                                       GTK_WINDOW (win),
1081                                                       GTK_DIALOG_MODAL,
1082                                                       GTK_STOCK_CANCEL,
1083                                                       GTK_RESPONSE_REJECT,
1084                                                       GTK_STOCK_OK,
1085                                                       GTK_RESPONSE_ACCEPT,
1086                                                       NULL);
1087                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1088                                          "Do you want to get online?"), item);
1089                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1090                                     gtk_label_new (txt), FALSE, FALSE, 0);
1091                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1092                 g_free (txt);
1093
1094                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1095                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1096 //                      modest_platform_connect_and_wait ();;
1097                 }
1098         }
1099         gtk_widget_destroy (dialog);
1100         if (g_main_depth > 0)   
1101                 gdk_threads_leave ();
1102 }
1103
1104 void
1105 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1106                                      ModestWindow *win)
1107 {
1108         /* g_message ("%s %s", __FUNCTION__, link); */
1109 }       
1110
1111
1112 void
1113 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1114                                         ModestWindow *win)
1115 {
1116         modest_platform_activate_uri (link);
1117 }
1118
1119 void
1120 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1121                                           ModestWindow *win)
1122 {
1123         modest_platform_show_uri_popup (link);
1124 }
1125
1126 void
1127 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1128                                              ModestWindow *win)
1129 {
1130         modest_msg_view_window_view_attachment (MODEST_MSG_VIEW_WINDOW (win), mime_part);
1131 }
1132
1133 void
1134 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1135                                           const gchar *address,
1136                                           ModestWindow *win)
1137 {
1138         /* g_message ("%s %s", __FUNCTION__, address); */
1139 }
1140
1141 void
1142 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1143 {
1144         TnyTransportAccount *transport_account;
1145         ModestMailOperation *mail_operation;
1146         MsgData *data;
1147         gchar *account_name, *from;
1148         ModestAccountMgr *account_mgr;
1149
1150         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1151         
1152         data = modest_msg_edit_window_get_msg_data (edit_window);
1153
1154         account_mgr = modest_runtime_get_account_mgr();
1155         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1156         if (!account_name) 
1157                 account_name = modest_account_mgr_get_default_account (account_mgr);
1158         if (!account_name) {
1159                 g_printerr ("modest: no account found\n");
1160                 modest_msg_edit_window_free_msg_data (edit_window, data);
1161                 return;
1162         }
1163         transport_account =
1164                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
1165                                       (modest_runtime_get_account_store(),
1166                                        account_name,
1167                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1168         if (!transport_account) {
1169                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1170                 g_free (account_name);
1171                 modest_msg_edit_window_free_msg_data (edit_window, data);
1172                 return;
1173         }
1174         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1175
1176         /* Create the mail operation */         
1177         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO, G_OBJECT(edit_window));
1178         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1179
1180         modest_mail_operation_save_to_drafts (mail_operation,
1181                                               transport_account,
1182                                               from,
1183                                               data->to, 
1184                                               data->cc, 
1185                                               data->bcc,
1186                                               data->subject, 
1187                                               data->plain_body, 
1188                                               data->html_body,
1189                                               data->attachments,
1190                                               data->priority_flags);
1191         /* Frees */
1192         g_free (from);
1193         g_free (account_name);
1194         g_object_unref (G_OBJECT (transport_account));
1195         g_object_unref (G_OBJECT (mail_operation));
1196
1197         modest_msg_edit_window_free_msg_data (edit_window, data);
1198
1199         /* Save settings and close the window */
1200         gtk_widget_destroy (GTK_WIDGET (edit_window));
1201 }
1202 void
1203 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1204 {
1205         TnyTransportAccount *transport_account;
1206         ModestMailOperation *mail_operation;
1207         MsgData *data;
1208         gchar *account_name, *from;
1209         ModestAccountMgr *account_mgr;
1210
1211         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1212
1213         if (!modest_msg_edit_window_check_names (edit_window))
1214                 return;
1215         
1216         data = modest_msg_edit_window_get_msg_data (edit_window);
1217
1218         /* FIXME: Code added just for testing. The final version will
1219            use the send queue provided by tinymail and some
1220            classifier */
1221         account_mgr = modest_runtime_get_account_mgr();
1222         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1223         if (!account_name) 
1224                 account_name = modest_account_mgr_get_default_account (account_mgr);
1225         if (!account_name) {
1226                 g_printerr ("modest: no account found\n");
1227                 modest_msg_edit_window_free_msg_data (edit_window, data);
1228                 return;
1229         }
1230         transport_account =
1231                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
1232                                       (modest_runtime_get_account_store(),
1233                                        account_name));
1234         if (!transport_account) {
1235                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1236                 g_free (account_name);
1237                 modest_msg_edit_window_free_msg_data (edit_window, data);
1238                 return;
1239         }
1240         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1241
1242         /* Create the mail operation */         
1243         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_SEND, G_OBJECT(edit_window));
1244         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1245
1246         modest_mail_operation_send_new_mail (mail_operation,
1247                                              transport_account,
1248                                              from,
1249                                              data->to, 
1250                                              data->cc, 
1251                                              data->bcc,
1252                                              data->subject, 
1253                                              data->plain_body, 
1254                                              data->html_body,
1255                                              data->attachments,
1256                                              data->priority_flags);
1257         /* Frees */
1258         g_free (from);
1259         g_free (account_name);
1260         g_object_unref (G_OBJECT (transport_account));
1261         g_object_unref (G_OBJECT (mail_operation));
1262
1263         modest_msg_edit_window_free_msg_data (edit_window, data);
1264
1265         /* Save settings and close the window */
1266         gtk_widget_destroy (GTK_WIDGET (edit_window));
1267 }
1268
1269 void 
1270 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1271                                   ModestMsgEditWindow *window)
1272 {
1273         ModestMsgEditFormatState *format_state = NULL;
1274
1275         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1276         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1277
1278         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1279                 return;
1280
1281         format_state = modest_msg_edit_window_get_format_state (window);
1282         g_return_if_fail (format_state != NULL);
1283
1284         format_state->bold = gtk_toggle_action_get_active (action);
1285         modest_msg_edit_window_set_format_state (window, format_state);
1286         g_free (format_state);
1287         
1288 }
1289
1290 void 
1291 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1292                                      ModestMsgEditWindow *window)
1293 {
1294         ModestMsgEditFormatState *format_state = NULL;
1295
1296         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1297         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1298
1299         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1300                 return;
1301
1302         format_state = modest_msg_edit_window_get_format_state (window);
1303         g_return_if_fail (format_state != NULL);
1304
1305         format_state->italics = gtk_toggle_action_get_active (action);
1306         modest_msg_edit_window_set_format_state (window, format_state);
1307         g_free (format_state);
1308         
1309 }
1310
1311 void 
1312 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
1313                                      ModestMsgEditWindow *window)
1314 {
1315         ModestMsgEditFormatState *format_state = NULL;
1316
1317         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1318         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1319
1320         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1321                 return;
1322
1323         format_state = modest_msg_edit_window_get_format_state (window);
1324         g_return_if_fail (format_state != NULL);
1325
1326         format_state->bullet = gtk_toggle_action_get_active (action);
1327         modest_msg_edit_window_set_format_state (window, format_state);
1328         g_free (format_state);
1329         
1330 }
1331
1332 void 
1333 modest_ui_actions_on_change_justify (GtkRadioAction *action,
1334                                      GtkRadioAction *selected,
1335                                      ModestMsgEditWindow *window)
1336 {
1337         ModestMsgEditFormatState *format_state = NULL;
1338         GtkJustification value;
1339
1340         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1341
1342         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1343                 return;
1344
1345         value = gtk_radio_action_get_current_value (selected);
1346
1347         format_state = modest_msg_edit_window_get_format_state (window);
1348         g_return_if_fail (format_state != NULL);
1349
1350         format_state->justification = value;
1351         modest_msg_edit_window_set_format_state (window, format_state);
1352         g_free (format_state);
1353 }
1354
1355 void 
1356 modest_ui_actions_on_select_editor_color (GtkAction *action,
1357                                           ModestMsgEditWindow *window)
1358 {
1359         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1360         g_return_if_fail (GTK_IS_ACTION (action));
1361
1362         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1363                 return;
1364
1365         modest_msg_edit_window_select_color (window);
1366 }
1367
1368 void 
1369 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
1370                                                      ModestMsgEditWindow *window)
1371 {
1372         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1373         g_return_if_fail (GTK_IS_ACTION (action));
1374
1375         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1376                 return;
1377
1378         modest_msg_edit_window_select_background_color (window);
1379 }
1380
1381 void 
1382 modest_ui_actions_on_insert_image (GtkAction *action,
1383                                    ModestMsgEditWindow *window)
1384 {
1385         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1386         g_return_if_fail (GTK_IS_ACTION (action));
1387
1388         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1389                 return;
1390
1391         modest_msg_edit_window_insert_image (window);
1392 }
1393
1394 void 
1395 modest_ui_actions_on_attach_file (GtkAction *action,
1396                                   ModestMsgEditWindow *window)
1397 {
1398         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1399         g_return_if_fail (GTK_IS_ACTION (action));
1400
1401         modest_msg_edit_window_attach_file (window);
1402 }
1403
1404 void 
1405 modest_ui_actions_on_remove_attachments (GtkAction *action,
1406                                          ModestMsgEditWindow *window)
1407 {
1408         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1409         g_return_if_fail (GTK_IS_ACTION (action));
1410
1411         modest_msg_edit_window_remove_attachments (window, NULL);
1412 }
1413
1414 /*
1415  * Shows a dialog with an entry that asks for some text. The returned
1416  * value must be freed by the caller. The dialog window title will be
1417  * set to @title.
1418  */
1419 static gchar *
1420 ask_for_folder_name (GtkWindow *parent_window,
1421                      const gchar *title)
1422 {
1423         GtkWidget *dialog, *entry;
1424         gchar *folder_name = NULL;
1425
1426         /* Ask for folder name */
1427         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1428                                               parent_window,
1429                                               GTK_DIALOG_MODAL,
1430                                               GTK_STOCK_CANCEL,
1431                                               GTK_RESPONSE_REJECT,
1432                                               GTK_STOCK_OK,
1433                                               GTK_RESPONSE_ACCEPT,
1434                                               NULL);
1435         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1436                             gtk_label_new(title),
1437                             FALSE, FALSE, 0);
1438                 
1439         entry = gtk_entry_new_with_max_length (40);
1440         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1441                             entry,
1442                             TRUE, FALSE, 0);    
1443         
1444         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1445         
1446         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
1447                 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1448
1449         gtk_widget_destroy (dialog);
1450
1451         return folder_name;
1452 }
1453
1454 void 
1455 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1456 {
1457         TnyFolderStore *parent_folder;
1458         GtkWidget *folder_view;
1459         
1460         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1461
1462         folder_view = modest_main_window_get_child_widget (main_window,
1463                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1464         if (!folder_view)
1465                 return;
1466
1467         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1468         
1469         if (parent_folder) {
1470                 gboolean finished = FALSE;
1471                 gint result;
1472                 gchar *folder_name = NULL, *suggested_name = NULL;
1473
1474                 /* Run the new folder dialog */
1475                 while (!finished) {
1476                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (main_window),
1477                                                                         parent_folder,
1478                                                                         suggested_name,
1479                                                                         &folder_name);
1480
1481                         if (result == GTK_RESPONSE_REJECT) {
1482                                 finished = TRUE;
1483                         } else {
1484                                 ModestMailOperation *mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO, G_OBJECT(main_window));
1485                                 TnyFolder *new_folder = NULL;
1486
1487                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
1488                                                                  mail_op);
1489                 
1490                                 new_folder = modest_mail_operation_create_folder (mail_op,
1491                                                                                   parent_folder,
1492                                                                                   (const gchar *) folder_name);
1493                                 if (new_folder) {
1494                                         g_object_unref (new_folder);
1495                                         finished = TRUE;
1496                                 } 
1497 /*                              else { */
1498 /*                                      /\* TODO: check error and follow proper actions *\/ */
1499 /* /\*                                  suggested_name = X; *\/ */
1500 /*                                      /\* Show error to the user *\/ */
1501 /*                                      modest_platform_run_information_dialog (GTK_WINDOW (main_window), */
1502 /*                                                                              _("mail_in_ui_folder_create_error")); */
1503 /*                              } */
1504                                 g_object_unref (mail_op);
1505                         }
1506                         g_free (folder_name);
1507                         folder_name = NULL;
1508                 }
1509
1510                 g_object_unref (parent_folder);
1511         }
1512 }
1513
1514 void 
1515 modest_ui_actions_on_rename_folder (GtkAction *action,
1516                                      ModestMainWindow *main_window)
1517 {
1518         TnyFolderStore *folder;
1519         GtkWidget *folder_view;
1520         
1521         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1522
1523         folder_view = modest_main_window_get_child_widget (main_window,
1524                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1525         if (!folder_view)
1526                 return;
1527         
1528         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1529         
1530         if (folder && TNY_IS_FOLDER (folder)) {
1531                 gchar *folder_name;
1532                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1533                                                    _("Please enter a new name for the folder"));
1534
1535                 if (folder_name != NULL && strlen (folder_name) > 0) {
1536                         ModestMailOperation *mail_op;
1537
1538                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO, G_OBJECT(main_window));
1539                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1540                                                          mail_op);
1541
1542                         modest_mail_operation_rename_folder (mail_op,
1543                                                              TNY_FOLDER (folder),
1544                                                              (const gchar *) folder_name);
1545
1546                         g_object_unref (mail_op);
1547                         g_free (folder_name);
1548                 }
1549                 g_object_unref (folder);
1550         }
1551 }
1552
1553 static void
1554 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
1555 {
1556         TnyFolderStore *folder;
1557         GtkWidget *folder_view;
1558         gint response;
1559         gchar *message;
1560         
1561         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1562
1563         folder_view = modest_main_window_get_child_widget (main_window,
1564                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1565         if (!folder_view)
1566                 return;
1567
1568         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1569
1570         /* Show an error if it's an account */
1571         if (!TNY_IS_FOLDER (folder)) {
1572                 modest_platform_run_information_dialog (GTK_WINDOW (main_window),
1573                                                         _("mail_in_ui_folder_delete_error"));
1574                 return ;
1575         }
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                                                                 _("mail_in_ui_folder_delete_error"));
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
2535         dialog = modest_platform_get_global_settings_dialog ();
2536         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (win));
2537         gtk_widget_show (dialog);
2538
2539         gtk_dialog_run (GTK_DIALOG (dialog));
2540
2541         gtk_widget_destroy (dialog);
2542 }