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