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