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