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