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