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