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