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