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