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