* Fixed a bug when there was no header selected
[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         /* If no header has been selected then exit */
935         if (!header)
936                 return;
937
938         /* Update Main window title */
939         if (GTK_WIDGET_HAS_FOCUS (header_view)) {
940                 const gchar *subject = tny_header_get_subject (header);
941                 if (subject && strcmp (subject, ""))
942                         gtk_window_set_title (GTK_WINDOW (main_window), subject);
943                 else
944                         gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
945         }
946 }
947
948
949
950 void 
951 modest_ui_actions_on_header_activated (ModestHeaderView *header_view, TnyHeader *header,
952                                        ModestMainWindow *main_window)
953 {
954         ModestWindow *win = NULL;
955         TnyFolder *folder = NULL;
956         TnyMsg    *msg    = NULL;
957         ModestWindowMgr *mgr;
958         GtkTreeModel *model;
959         GtkTreeIter iter;
960         GtkTreeSelection *sel = NULL;
961         GList *sel_list = NULL;
962         
963         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
964         
965         if (!header)
966                 return;
967
968         folder = tny_header_get_folder (header);
969         if (!folder) {
970                 g_printerr ("modest: cannot get folder for header\n");
971                 return;
972         }
973
974         /* FIXME: make async?; check error  */
975         msg = tny_folder_get_msg (folder, header, NULL);
976         if (!msg) {
977                 g_printerr ("modest: cannot get msg for header\n");
978                 goto cleanup;
979         }
980
981         /* Look if we already have a message view for that header */    
982         mgr = modest_runtime_get_window_mgr ();
983         win = modest_window_mgr_find_window_by_msguid (mgr, tny_header_get_uid (header));
984
985         /* If not, create a new window */
986         if (!win) {
987                 gchar *account;
988
989                 account =  g_strdup(modest_window_get_active_account(MODEST_WINDOW(main_window)));
990                 if (!account)
991                         account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
992
993                 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
994                 sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
995                 if (sel_list != NULL) {
996                         gtk_tree_model_get_iter (model, &iter, (GtkTreePath *) sel_list->data);
997                         
998                         win = modest_msg_view_window_new_with_header_model (msg, account, model, iter);
999                         g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
1000                         g_list_free (sel_list);
1001                 } else {
1002                         win = modest_msg_view_window_new (msg, account);
1003                 }
1004                 modest_window_mgr_register_window (mgr, win);
1005
1006                 gtk_window_set_transient_for (GTK_WINDOW (win),
1007                                               GTK_WINDOW (main_window));
1008         }
1009
1010         gtk_widget_show_all (GTK_WIDGET(win));
1011
1012         g_object_unref (G_OBJECT (msg));
1013         
1014 cleanup:
1015         g_object_unref (G_OBJECT (folder));
1016 }
1017
1018 void 
1019 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1020                                                TnyFolderStore *folder_store, 
1021                                                gboolean selected,
1022                                                ModestMainWindow *main_window)
1023 {
1024         ModestConf *conf;
1025         GtkWidget *header_view;
1026         
1027         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1028
1029         header_view = modest_main_window_get_child_widget(main_window,
1030                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
1031         if (!header_view)
1032                 return;
1033         
1034         conf = modest_runtime_get_conf ();
1035
1036         if (TNY_IS_FOLDER (folder_store)) {
1037
1038                 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1039
1040                 if (selected) {
1041                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1042                                                        TNY_FOLDER (folder_store));
1043                         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1044                                                       MODEST_CONF_HEADER_VIEW_KEY);
1045                 } else {
1046                         modest_widget_memory_save (conf, G_OBJECT (header_view), MODEST_CONF_HEADER_VIEW_KEY);
1047                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
1048                 }
1049         } else if (TNY_IS_ACCOUNT (folder_store)) {
1050
1051                 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1052         }
1053 }
1054
1055 void 
1056 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1057                                      ModestWindow *win)
1058 {
1059         GtkWidget *dialog;
1060         gchar *txt, *item;
1061         gboolean online;
1062
1063         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1064         
1065         if (g_main_depth > 0)   
1066                 gdk_threads_enter ();
1067         online = tny_device_is_online (modest_runtime_get_device());
1068
1069         if (online) {
1070                 /* already online -- the item is simply not there... */
1071                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1072                                                  GTK_DIALOG_MODAL,
1073                                                  GTK_MESSAGE_WARNING,
1074                                                  GTK_BUTTONS_OK,
1075                                                  _("The %s you selected cannot be found"),
1076                                                  item);
1077                 gtk_dialog_run (GTK_DIALOG(dialog));
1078         } else {
1079                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1080                                                       GTK_WINDOW (win),
1081                                                       GTK_DIALOG_MODAL,
1082                                                       GTK_STOCK_CANCEL,
1083                                                       GTK_RESPONSE_REJECT,
1084                                                       GTK_STOCK_OK,
1085                                                       GTK_RESPONSE_ACCEPT,
1086                                                       NULL);
1087                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1088                                          "Do you want to get online?"), item);
1089                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1090                                     gtk_label_new (txt), FALSE, FALSE, 0);
1091                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1092                 g_free (txt);
1093
1094                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1095                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1096 //                      modest_platform_connect_and_wait ();;
1097                 }
1098         }
1099         gtk_widget_destroy (dialog);
1100         if (g_main_depth > 0)   
1101                 gdk_threads_leave ();
1102 }
1103
1104 void
1105 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1106                                      ModestWindow *win)
1107 {
1108         g_message ("%s %s", __FUNCTION__, link);
1109 }       
1110
1111
1112 void
1113 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1114                                         ModestWindow *win)
1115 {
1116         modest_platform_activate_uri (link);
1117 }
1118
1119 void
1120 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1121                                           ModestWindow *win)
1122 {
1123         modest_platform_show_uri_popup (link);
1124 }
1125
1126 void
1127 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1128                                              ModestWindow *win)
1129 {
1130         g_message (__FUNCTION__);
1131         
1132 }
1133
1134 void
1135 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1136                                           const gchar *address,
1137                                           ModestWindow *win)
1138 {
1139         g_message ("%s %s", __FUNCTION__, address);
1140 }
1141
1142 void
1143 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1144 {
1145         TnyTransportAccount *transport_account;
1146         ModestMailOperation *mail_operation;
1147         MsgData *data;
1148         gchar *account_name, *from;
1149         ModestAccountMgr *account_mgr;
1150
1151         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1152         
1153         data = modest_msg_edit_window_get_msg_data (edit_window);
1154
1155         account_mgr = modest_runtime_get_account_mgr();
1156         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1157         if (!account_name) 
1158                 account_name = modest_account_mgr_get_default_account (account_mgr);
1159         if (!account_name) {
1160                 g_printerr ("modest: no account found\n");
1161                 modest_msg_edit_window_free_msg_data (edit_window, data);
1162                 return;
1163         }
1164         transport_account =
1165                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
1166                                       (modest_runtime_get_account_store(),
1167                                        account_name,
1168                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1169         if (!transport_account) {
1170                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1171                 g_free (account_name);
1172                 modest_msg_edit_window_free_msg_data (edit_window, data);
1173                 return;
1174         }
1175         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1176
1177         /* Create the mail operation */         
1178         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO);
1179         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1180
1181         modest_mail_operation_save_to_drafts (mail_operation,
1182                                               transport_account,
1183                                               from,
1184                                               data->to, 
1185                                               data->cc, 
1186                                               data->bcc,
1187                                               data->subject, 
1188                                               data->plain_body, 
1189                                               data->html_body,
1190                                               data->attachments,
1191                                               data->priority_flags);
1192         /* Frees */
1193         g_free (from);
1194         g_free (account_name);
1195         g_object_unref (G_OBJECT (transport_account));
1196         g_object_unref (G_OBJECT (mail_operation));
1197
1198         modest_msg_edit_window_free_msg_data (edit_window, data);
1199
1200         /* Save settings and close the window */
1201         gtk_widget_destroy (GTK_WIDGET (edit_window));
1202 }
1203 void
1204 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1205 {
1206         TnyTransportAccount *transport_account;
1207         ModestMailOperation *mail_operation;
1208         MsgData *data;
1209         gchar *account_name, *from;
1210         ModestAccountMgr *account_mgr;
1211
1212         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1213
1214         if (!modest_msg_edit_window_check_names (edit_window))
1215                 return;
1216         
1217         data = modest_msg_edit_window_get_msg_data (edit_window);
1218
1219         /* FIXME: Code added just for testing. The final version will
1220            use the send queue provided by tinymail and some
1221            classifier */
1222         account_mgr = modest_runtime_get_account_mgr();
1223         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1224         if (!account_name) 
1225                 account_name = modest_account_mgr_get_default_account (account_mgr);
1226         if (!account_name) {
1227                 g_printerr ("modest: no account found\n");
1228                 modest_msg_edit_window_free_msg_data (edit_window, data);
1229                 return;
1230         }
1231         transport_account =
1232                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
1233                                       (modest_runtime_get_account_store(),
1234                                        account_name));
1235         if (!transport_account) {
1236                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1237                 g_free (account_name);
1238                 modest_msg_edit_window_free_msg_data (edit_window, data);
1239                 return;
1240         }
1241         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1242
1243         /* Create the mail operation */         
1244         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_SEND);
1245         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1246
1247         modest_mail_operation_send_new_mail (mail_operation,
1248                                              transport_account,
1249                                              from,
1250                                              data->to, 
1251                                              data->cc, 
1252                                              data->bcc,
1253                                              data->subject, 
1254                                              data->plain_body, 
1255                                              data->html_body,
1256                                              data->attachments,
1257                                              data->priority_flags);
1258         /* Frees */
1259         g_free (from);
1260         g_free (account_name);
1261         g_object_unref (G_OBJECT (transport_account));
1262         g_object_unref (G_OBJECT (mail_operation));
1263
1264         modest_msg_edit_window_free_msg_data (edit_window, data);
1265
1266         /* Save settings and close the window */
1267         gtk_widget_destroy (GTK_WIDGET (edit_window));
1268 }
1269
1270 void 
1271 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1272                                   ModestMsgEditWindow *window)
1273 {
1274         ModestMsgEditFormatState *format_state = NULL;
1275
1276         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1277         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1278
1279         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1280                 return;
1281
1282         format_state = modest_msg_edit_window_get_format_state (window);
1283         g_return_if_fail (format_state != NULL);
1284
1285         format_state->bold = gtk_toggle_action_get_active (action);
1286         modest_msg_edit_window_set_format_state (window, format_state);
1287         g_free (format_state);
1288         
1289 }
1290
1291 void 
1292 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1293                                      ModestMsgEditWindow *window)
1294 {
1295         ModestMsgEditFormatState *format_state = NULL;
1296
1297         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1298         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1299
1300         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1301                 return;
1302
1303         format_state = modest_msg_edit_window_get_format_state (window);
1304         g_return_if_fail (format_state != NULL);
1305
1306         format_state->italics = gtk_toggle_action_get_active (action);
1307         modest_msg_edit_window_set_format_state (window, format_state);
1308         g_free (format_state);
1309         
1310 }
1311
1312 void 
1313 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
1314                                      ModestMsgEditWindow *window)
1315 {
1316         ModestMsgEditFormatState *format_state = NULL;
1317
1318         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1319         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1320
1321         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1322                 return;
1323
1324         format_state = modest_msg_edit_window_get_format_state (window);
1325         g_return_if_fail (format_state != NULL);
1326
1327         format_state->bullet = gtk_toggle_action_get_active (action);
1328         modest_msg_edit_window_set_format_state (window, format_state);
1329         g_free (format_state);
1330         
1331 }
1332
1333 void 
1334 modest_ui_actions_on_change_justify (GtkRadioAction *action,
1335                                      GtkRadioAction *selected,
1336                                      ModestMsgEditWindow *window)
1337 {
1338         ModestMsgEditFormatState *format_state = NULL;
1339         GtkJustification value;
1340
1341         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1342
1343         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1344                 return;
1345
1346         value = gtk_radio_action_get_current_value (selected);
1347
1348         format_state = modest_msg_edit_window_get_format_state (window);
1349         g_return_if_fail (format_state != NULL);
1350
1351         format_state->justification = value;
1352         modest_msg_edit_window_set_format_state (window, format_state);
1353         g_free (format_state);
1354 }
1355
1356 void 
1357 modest_ui_actions_on_select_editor_color (GtkAction *action,
1358                                           ModestMsgEditWindow *window)
1359 {
1360         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1361         g_return_if_fail (GTK_IS_ACTION (action));
1362
1363         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1364                 return;
1365
1366         modest_msg_edit_window_select_color (window);
1367 }
1368
1369 void 
1370 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
1371                                                      ModestMsgEditWindow *window)
1372 {
1373         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1374         g_return_if_fail (GTK_IS_ACTION (action));
1375
1376         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1377                 return;
1378
1379         modest_msg_edit_window_select_background_color (window);
1380 }
1381
1382 void 
1383 modest_ui_actions_on_insert_image (GtkAction *action,
1384                                    ModestMsgEditWindow *window)
1385 {
1386         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1387         g_return_if_fail (GTK_IS_ACTION (action));
1388
1389         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1390                 return;
1391
1392         modest_msg_edit_window_insert_image (window);
1393 }
1394
1395 /*
1396  * Shows a dialog with an entry that asks for some text. The returned
1397  * value must be freed by the caller. The dialog window title will be
1398  * set to @title.
1399  */
1400 static gchar *
1401 ask_for_folder_name (GtkWindow *parent_window,
1402                      const gchar *title)
1403 {
1404         GtkWidget *dialog, *entry;
1405         gchar *folder_name = NULL;
1406
1407         /* Ask for folder name */
1408         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1409                                               parent_window,
1410                                               GTK_DIALOG_MODAL,
1411                                               GTK_STOCK_CANCEL,
1412                                               GTK_RESPONSE_REJECT,
1413                                               GTK_STOCK_OK,
1414                                               GTK_RESPONSE_ACCEPT,
1415                                               NULL);
1416         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1417                             gtk_label_new(title),
1418                             FALSE, FALSE, 0);
1419                 
1420         entry = gtk_entry_new_with_max_length (40);
1421         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1422                             entry,
1423                             TRUE, FALSE, 0);    
1424         
1425         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1426         
1427         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
1428                 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1429
1430         gtk_widget_destroy (dialog);
1431
1432         return folder_name;
1433 }
1434
1435 void 
1436 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1437 {
1438         TnyFolderStore *parent_folder;
1439         GtkWidget *folder_view;
1440         
1441         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1442
1443         folder_view = modest_main_window_get_child_widget (main_window,
1444                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1445         if (!folder_view)
1446                 return;
1447
1448         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1449         
1450         if (parent_folder) {
1451                 gboolean finished = FALSE;
1452                 gint result;
1453                 gchar *folder_name = NULL, *suggested_name = NULL;
1454
1455                 /* Run the new folder dialog */
1456                 while (!finished) {
1457                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (main_window),
1458                                                                         parent_folder,
1459                                                                         suggested_name,
1460                                                                         &folder_name);
1461
1462                         if (result == GTK_RESPONSE_REJECT) {
1463                                 finished = TRUE;
1464                         } else {
1465                                 ModestMailOperation *mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO);
1466                                 TnyFolder *new_folder = NULL;
1467
1468                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
1469                                                                  mail_op);
1470                 
1471                                 new_folder = modest_mail_operation_create_folder (mail_op,
1472                                                                                   parent_folder,
1473                                                                                   (const gchar *) folder_name);
1474                                 if (new_folder) {
1475                                         g_object_unref (new_folder);
1476                                         finished = TRUE;
1477                                 } 
1478 /*                              else { */
1479 /*                                      /\* TODO: check error and follow proper actions *\/ */
1480 /* /\*                                  suggested_name = X; *\/ */
1481 /*                                      /\* Show error to the user *\/ */
1482 /*                                      modest_platform_run_information_dialog (GTK_WINDOW (main_window), */
1483 /*                                                                              MODEST_INFORMATION_CREATE_FOLDER); */
1484 /*                              } */
1485                                 g_object_unref (mail_op);
1486                         }
1487                         g_free (folder_name);
1488                         folder_name = NULL;
1489                 }
1490
1491                 g_object_unref (parent_folder);
1492         }
1493 }
1494
1495 void 
1496 modest_ui_actions_on_rename_folder (GtkAction *action,
1497                                      ModestMainWindow *main_window)
1498 {
1499         TnyFolderStore *folder;
1500         GtkWidget *folder_view;
1501         
1502         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1503
1504         folder_view = modest_main_window_get_child_widget (main_window,
1505                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1506         if (!folder_view)
1507                 return;
1508         
1509         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1510         
1511         if (folder && TNY_IS_FOLDER (folder)) {
1512                 gchar *folder_name;
1513                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1514                                                    _("Please enter a new name for the folder"));
1515
1516                 if (folder_name != NULL && strlen (folder_name) > 0) {
1517                         ModestMailOperation *mail_op;
1518
1519                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO);
1520                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1521                                                          mail_op);
1522
1523                         modest_mail_operation_rename_folder (mail_op,
1524                                                              TNY_FOLDER (folder),
1525                                                              (const gchar *) folder_name);
1526
1527                         g_object_unref (mail_op);
1528                         g_free (folder_name);
1529                 }
1530                 g_object_unref (folder);
1531         }
1532 }
1533
1534 static void
1535 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
1536 {
1537         TnyFolderStore *folder;
1538         GtkWidget *folder_view;
1539         gint response;
1540         gchar *message;
1541         
1542         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1543
1544         folder_view = modest_main_window_get_child_widget (main_window,
1545                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1546         if (!folder_view)
1547                 return;
1548
1549         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1550
1551         /* Ask the user */      
1552         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
1553                                     tny_folder_get_name (TNY_FOLDER (folder)));
1554         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window), 
1555                                                             (const gchar *) message);
1556         g_free (message);
1557
1558         if (response == GTK_RESPONSE_OK) {
1559                 ModestMailOperation *mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_DELETE);
1560
1561                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1562                                                  mail_op);
1563                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
1564
1565                 /* Show error if happened */
1566                 if (modest_mail_operation_get_error (mail_op))
1567                         modest_platform_run_information_dialog (GTK_WINDOW (main_window),
1568                                                                 MODEST_INFORMATION_DELETE_FOLDER);
1569
1570                 g_object_unref (G_OBJECT (mail_op));
1571         }
1572
1573         g_object_unref (G_OBJECT (folder));
1574 }
1575
1576 void 
1577 modest_ui_actions_on_delete_folder (GtkAction *action,
1578                                      ModestMainWindow *main_window)
1579 {
1580         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1581
1582         delete_folder (main_window, FALSE);
1583 }
1584
1585 void 
1586 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1587 {
1588         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1589         
1590         delete_folder (main_window, TRUE);
1591 }
1592
1593 void
1594 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
1595                                          const gchar* account_name,
1596                                          gchar **password, 
1597                                          gboolean *cancel, 
1598                                          gboolean *remember,
1599                                          ModestMainWindow *main_window)
1600 {
1601         gchar *txt;
1602         GtkWidget *dialog, *entry, *remember_pass_check;
1603
1604         dialog = gtk_dialog_new_with_buttons (_("Password requested"),
1605                                               NULL,
1606                                               GTK_DIALOG_MODAL,
1607                                               GTK_STOCK_CANCEL,
1608                                               GTK_RESPONSE_REJECT,
1609                                               GTK_STOCK_OK,
1610                                               GTK_RESPONSE_ACCEPT,
1611                                               NULL);
1612         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1613         
1614         txt = g_strdup_printf (_("Please enter your password for %s"), account_name);
1615         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1616                             FALSE, FALSE, 0);
1617         g_free (txt);
1618
1619         entry = gtk_entry_new_with_max_length (40);
1620         gtk_entry_set_visibility (GTK_ENTRY(entry), FALSE);
1621         gtk_entry_set_invisible_char (GTK_ENTRY(entry), 0x2022); /* bullet unichar */
1622         
1623         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry,
1624                             TRUE, FALSE, 0);    
1625
1626         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1627         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1628                             TRUE, FALSE, 0);
1629
1630         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1631         
1632         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1633                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry)));
1634                 *cancel   = FALSE;
1635         } else {
1636                 *password = NULL;
1637                 *cancel   = TRUE;
1638         }
1639
1640         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
1641                 *remember = TRUE;
1642         else
1643                 *remember = FALSE;
1644
1645         gtk_widget_destroy (dialog);
1646 }
1647
1648 void
1649 modest_ui_actions_on_cut (GtkAction *action,
1650                           ModestWindow *window)
1651 {
1652         GtkWidget *focused_widget;
1653
1654         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1655         if (GTK_IS_EDITABLE (focused_widget)) {
1656                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
1657         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1658                 GtkTextBuffer *buffer;
1659                 GtkClipboard *clipboard;
1660
1661                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1662                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1663                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
1664         }
1665 }
1666
1667 void
1668 modest_ui_actions_on_copy (GtkAction *action,
1669                            ModestWindow *window)
1670 {
1671         GtkClipboard *clipboard;
1672         GtkWidget *focused_widget;
1673
1674         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1675         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1676         if (GTK_IS_LABEL (focused_widget)) {
1677                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
1678         } else if (GTK_IS_EDITABLE (focused_widget)) {
1679                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
1680         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1681                 GtkTextBuffer *buffer;
1682
1683                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1684                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
1685         }
1686 }
1687
1688 void
1689 modest_ui_actions_on_undo (GtkAction *action,
1690                            ModestWindow *window)
1691 {
1692         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
1693                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
1694         } else {
1695                 g_return_if_reached ();
1696         }
1697 }
1698
1699 void
1700 modest_ui_actions_on_paste (GtkAction *action,
1701                             ModestWindow *window)
1702 {
1703         GtkWidget *focused_widget;
1704
1705         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1706         if (GTK_IS_EDITABLE (focused_widget)) {
1707                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
1708         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1709                 GtkTextBuffer *buffer;
1710                 GtkClipboard *clipboard;
1711
1712                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1713                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1714                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
1715         }
1716 }
1717
1718 void
1719 modest_ui_actions_on_select_all (GtkAction *action,
1720                                  ModestWindow *window)
1721 {
1722         GtkWidget *focused_widget;
1723
1724         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1725         if (GTK_IS_LABEL (focused_widget)) {
1726                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
1727         } else if (GTK_IS_EDITABLE (focused_widget)) {
1728                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
1729         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1730                 GtkTextBuffer *buffer;
1731                 GtkTextIter start, end;
1732
1733                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1734                 gtk_text_buffer_get_start_iter (buffer, &start);
1735                 gtk_text_buffer_get_end_iter (buffer, &end);
1736                 gtk_text_buffer_select_range (buffer, &start, &end);
1737         }
1738 }
1739
1740 void
1741 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
1742                                   GtkRadioAction *selected,
1743                                   ModestWindow *window)
1744 {
1745         gint value;
1746
1747         value = gtk_radio_action_get_current_value (selected);
1748         if (MODEST_IS_WINDOW (window)) {
1749                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
1750         }
1751 }
1752
1753 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
1754                                                         GtkRadioAction *selected,
1755                                                         ModestWindow *window)
1756 {
1757         TnyHeaderFlags flags;
1758         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1759
1760         flags = gtk_radio_action_get_current_value (selected);
1761         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
1762 }
1763
1764 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
1765                                                            GtkRadioAction *selected,
1766                                                            ModestWindow *window)
1767 {
1768         gint file_format;
1769
1770         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1771
1772         file_format = gtk_radio_action_get_current_value (selected);
1773         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
1774 }
1775
1776
1777 void     
1778 modest_ui_actions_on_zoom_plus (GtkAction *action,
1779                                 ModestWindow *window)
1780 {
1781         g_return_if_fail (MODEST_IS_WINDOW (window));
1782
1783         modest_window_zoom_plus (MODEST_WINDOW (window));
1784 }
1785
1786 void     
1787 modest_ui_actions_on_zoom_minus (GtkAction *action,
1788                                  ModestWindow *window)
1789 {
1790         g_return_if_fail (MODEST_IS_WINDOW (window));
1791
1792         modest_window_zoom_minus (MODEST_WINDOW (window));
1793 }
1794
1795 void     
1796 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
1797                                            ModestWindow *window)
1798 {
1799         ModestWindowMgr *mgr;
1800         gboolean fullscreen, active;
1801         g_return_if_fail (MODEST_IS_WINDOW (window));
1802
1803         mgr = modest_runtime_get_window_mgr ();
1804
1805         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
1806         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1807
1808         if (active != fullscreen) {
1809                 modest_window_mgr_set_fullscreen_mode (mgr, active);
1810                 gtk_window_present (GTK_WINDOW (window));
1811         }
1812 }
1813
1814 void
1815 modest_ui_actions_on_change_fullscreen (GtkAction *action,
1816                                         ModestWindow *window)
1817 {
1818         ModestWindowMgr *mgr;
1819         gboolean fullscreen;
1820
1821         g_return_if_fail (MODEST_IS_WINDOW (window));
1822
1823         mgr = modest_runtime_get_window_mgr ();
1824         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1825         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
1826
1827         gtk_window_present (GTK_WINDOW (window));
1828 }
1829
1830 /* 
1831  * Used by modest_ui_actions_on_details to call do_headers_action 
1832  */
1833 static void
1834 headers_action_show_details (TnyHeader *header, 
1835                              ModestWindow *window,
1836                              gpointer user_data)
1837
1838 {
1839         GtkWidget *dialog;
1840         
1841         /* Create dialog */
1842         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
1843
1844         /* Run dialog */
1845         gtk_widget_show_all (dialog);
1846         gtk_dialog_run (GTK_DIALOG (dialog));
1847
1848         gtk_widget_destroy (dialog);
1849 }
1850
1851 /*
1852  * Show the folder details in a ModestDetailsDialog widget
1853  */
1854 static void
1855 show_folder_details (TnyFolder *folder, 
1856                      GtkWindow *window)
1857 {
1858         GtkWidget *dialog;
1859         
1860         /* Create dialog */
1861         dialog = modest_details_dialog_new_with_folder (window, folder);
1862
1863         /* Run dialog */
1864         gtk_widget_show_all (dialog);
1865         gtk_dialog_run (GTK_DIALOG (dialog));
1866
1867         gtk_widget_destroy (dialog);
1868 }
1869
1870 /*
1871  * Show the header details in a ModestDetailsDialog widget
1872  */
1873 void     
1874 modest_ui_actions_on_details (GtkAction *action, 
1875                               ModestWindow *win)
1876 {
1877         TnyList * headers_list;
1878         TnyIterator *iter;
1879         TnyHeader *header;              
1880
1881         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1882                 TnyMsg *msg;
1883
1884                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
1885                 if (!msg) {
1886                         return;
1887                 } else {
1888                         headers_list = get_selected_headers (win);
1889                         if (!headers_list)
1890                                 return;
1891
1892                         iter = tny_list_create_iterator (headers_list);
1893
1894                         header = TNY_HEADER (tny_iterator_get_current (iter));
1895                         headers_action_show_details (header, win, NULL);
1896                         g_object_unref (header);
1897
1898                         g_object_unref (iter);
1899                 }
1900         } else if (MODEST_IS_MAIN_WINDOW (win)) {
1901                 GtkWidget *folder_view, *header_view;
1902
1903                 /* Check which widget has the focus */
1904                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1905                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
1906                 if (gtk_widget_is_focus (folder_view)) {
1907                         TnyFolder *folder;
1908
1909                         folder = (TnyFolder *) modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1910
1911                         /* Show only when it's a folder */
1912                         if (!folder || !TNY_IS_FOLDER (folder))
1913                                 return;
1914
1915                         show_folder_details (folder, GTK_WINDOW (win));
1916
1917                 } else {
1918                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1919                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1920                         /* Show details of each header */
1921                         do_headers_action (win, headers_action_show_details, header_view);
1922                 }
1923         }
1924 }
1925
1926 void     
1927 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
1928                                      ModestMsgEditWindow *window)
1929 {
1930         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1931
1932         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
1933 }
1934
1935 void     
1936 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
1937                                       ModestMsgEditWindow *window)
1938 {
1939         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1940
1941         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
1942 }
1943
1944 void
1945 modest_ui_actions_toggle_folders_view (GtkAction *action, 
1946                                        ModestMainWindow *main_window)
1947 {
1948         ModestConf *conf;
1949         
1950         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1951
1952         conf = modest_runtime_get_conf ();
1953         
1954         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
1955                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
1956         else
1957                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
1958 }
1959
1960 void 
1961 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
1962                                      ModestWindow *window)
1963 {
1964         gboolean active, fullscreen = FALSE;
1965         ModestWindowMgr *mgr;
1966
1967         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
1968
1969         /* Check if we want to toggle the toolbar vuew in fullscreen
1970            or normal mode */
1971         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
1972                      "ViewShowToolbarFullScreen")) {
1973                 fullscreen = TRUE;
1974         }
1975
1976         /* Toggle toolbar */
1977         mgr = modest_runtime_get_window_mgr ();
1978         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
1979 }
1980
1981 void     
1982 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
1983                                            ModestMsgEditWindow *window)
1984 {
1985         modest_msg_edit_window_select_font (window);
1986 }
1987
1988 void
1989 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
1990                                                   const gchar *display_name,
1991                                                   GtkWindow *window)
1992 {
1993         /* Do not change the application name if the widget has not
1994            the focus. This callback could be called even if the folder
1995            view has not the focus, because the handled signal could be
1996            emitted when the folder view is redrawn */
1997         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
1998                 if (display_name)
1999                         gtk_window_set_title (window, display_name);
2000                 else
2001                         gtk_window_set_title (window, " ");
2002         }
2003 }
2004
2005 void
2006 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
2007 {
2008         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2009         modest_msg_edit_window_select_contacts (window);
2010 }
2011
2012 void
2013 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
2014 {
2015         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2016         modest_msg_edit_window_check_names (window);
2017 }
2018
2019
2020 static GtkWidget*
2021 create_move_to_dialog (ModestWindow *win,
2022                        GtkWidget *folder_view,
2023                        GtkWidget **tree_view)
2024 {
2025         GtkWidget *dialog, *scroll;
2026
2027         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2028                                               GTK_WINDOW (win),
2029                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
2030                                               GTK_STOCK_OK,
2031                                               GTK_RESPONSE_ACCEPT,
2032                                               GTK_STOCK_CANCEL,
2033                                               GTK_RESPONSE_REJECT,
2034                                               NULL);
2035
2036         /* Create scrolled window */
2037         scroll = gtk_scrolled_window_new (NULL, NULL);
2038         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
2039                                          GTK_POLICY_AUTOMATIC,
2040                                          GTK_POLICY_AUTOMATIC);
2041
2042         /* Create folder view */
2043         *tree_view = modest_folder_view_new (NULL);
2044         gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
2045                                  gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
2046         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
2047
2048         /* Add scroll to dialog */
2049         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
2050                             scroll, FALSE, FALSE, 0);
2051
2052         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2053
2054         return dialog;
2055 }
2056
2057 /*
2058  * Returns TRUE if at least one of the headers of the list belongs to
2059  * a message that has been fully retrieved.
2060  */
2061 static gboolean
2062 has_retrieved_msgs (TnyList *list)
2063 {
2064         TnyIterator *iter;
2065         gboolean found = FALSE;
2066
2067         iter = tny_list_create_iterator (list);
2068         while (tny_iterator_is_done (iter) && !found) {
2069                 TnyHeader *header;
2070                 TnyHeaderFlags flags;
2071
2072                 header = TNY_HEADER (tny_iterator_get_current (iter));
2073                 flags = tny_header_get_flags (header);
2074                 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
2075                         found = TRUE;
2076
2077                 if (!found)
2078                         tny_iterator_next (iter);
2079         }
2080         g_object_unref (iter);
2081
2082         return found;
2083 }
2084
2085 /*
2086  * Shows a confirmation dialog to the user when we're moving messages
2087  * from a remote server to the local storage. Returns the dialog
2088  * response. If it's other kind of movement the it always returns
2089  * GTK_RESPONSE_OK
2090  */
2091 static gint
2092 msgs_move_to_confirmation (GtkWindow *win,
2093                            TnyFolder *dest_folder,
2094                            TnyList *headers)
2095 {
2096         gint response = GTK_RESPONSE_OK;
2097
2098         /* If the destination is a local folder */
2099         if (modest_tny_folder_is_local_folder (dest_folder)) {
2100                 TnyFolder *src_folder;
2101                 TnyIterator *iter;
2102                 TnyHeader *header;
2103
2104                 /* Get source folder */
2105                 iter = tny_list_create_iterator (headers);
2106                 header = TNY_HEADER (tny_iterator_get_current (iter));
2107                 src_folder = tny_header_get_folder (header);
2108                 g_object_unref (header);
2109                 g_object_unref (iter);
2110
2111                 /* If the source is a remote folder */
2112                 if (!modest_tny_folder_is_local_folder (src_folder)) {
2113                         const gchar *message;
2114                         
2115                         if (tny_list_get_length (headers) == 1)
2116                                 if (has_retrieved_msgs (headers))
2117                                         message = _("mcen_nc_move_retrieve");
2118                                 else
2119                                         message = _("mcen_nc_move_header");
2120                         else
2121                                 if (has_retrieved_msgs (headers))
2122                                         message = _("mcen_nc_move_retrieves");
2123                                 else
2124                                         message = _("mcen_nc_move_headers");
2125                         
2126                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
2127                                                                             (const gchar *) message);
2128                 }
2129         }
2130         return response;
2131 }
2132
2133 /*
2134  * UI handler for the "Move to" action when invoked from the
2135  * ModestMainWindow
2136  */
2137 static void 
2138 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
2139                                           ModestMainWindow *win)
2140 {
2141         GtkWidget *dialog, *folder_view, *tree_view = NULL;
2142         gint result;
2143         TnyFolderStore *folder_store;
2144         ModestMailOperation *mail_op = NULL;
2145
2146         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
2147
2148         /* Get the folder view */
2149         folder_view = modest_main_window_get_child_widget (win,
2150                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2151
2152         /* Create and run the dialog */
2153         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);
2154         result = gtk_dialog_run (GTK_DIALOG(dialog));
2155
2156         /* We do this to save an indentation level ;-) */
2157         if (result != GTK_RESPONSE_ACCEPT)
2158                 goto end;
2159
2160         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2161
2162         if (TNY_IS_ACCOUNT (folder_store))
2163                 goto end;
2164
2165         /* Get folder or messages to transfer */
2166         if (gtk_widget_is_focus (folder_view)) {
2167                 TnyFolderStore *src_folder;
2168                 src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2169
2170                 if (TNY_IS_FOLDER (src_folder)) {
2171                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE);
2172                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2173                                                          mail_op);
2174
2175                         modest_mail_operation_xfer_folder (mail_op, 
2176                                                            TNY_FOLDER (src_folder),
2177                                                            folder_store,
2178                                                            TRUE);
2179                         g_object_unref (G_OBJECT (mail_op));
2180                 }
2181
2182                 /* Frees */
2183                 g_object_unref (G_OBJECT (src_folder));
2184         } else {
2185                 GtkWidget *header_view;
2186                 header_view = modest_main_window_get_child_widget (win,
2187                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
2188                 if (gtk_widget_is_focus (header_view)) {
2189                         TnyList *headers;
2190                         gint response;
2191
2192                         headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
2193
2194                         /* Ask for user confirmation */
2195                         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2196                                                               TNY_FOLDER (folder_store), 
2197                                                               headers);
2198
2199                         /* Transfer messages */
2200                         if (response == GTK_RESPONSE_OK) {
2201                                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE);
2202                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2203                                                                  mail_op);
2204
2205                                 modest_mail_operation_xfer_msgs (mail_op, 
2206                                                                  headers,
2207                                                                  TNY_FOLDER (folder_store),
2208                                                                  TRUE);
2209                                 g_object_unref (G_OBJECT (mail_op));
2210                         }
2211                 }
2212         }
2213         g_object_unref (folder_store);
2214
2215  end:
2216         gtk_widget_destroy (dialog);
2217 }
2218
2219
2220 /*
2221  * UI handler for the "Move to" action when invoked from the
2222  * ModestMsgViewWindow
2223  */
2224 static void 
2225 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
2226                                               ModestMsgViewWindow *win)
2227 {
2228         GtkWidget *dialog, *folder_view, *tree_view = NULL;
2229         gint result;
2230         ModestMainWindow *main_window;
2231         TnyMsg *msg;
2232         TnyHeader *header;
2233         TnyList *headers;
2234
2235         /* Get the folder view */
2236         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2237         folder_view = modest_main_window_get_child_widget (main_window,
2238                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2239
2240         /* Create and run the dialog */
2241         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);  
2242         result = gtk_dialog_run (GTK_DIALOG(dialog));
2243
2244         if (result == GTK_RESPONSE_ACCEPT) {
2245                 TnyFolderStore *folder_store;
2246                 gint response;
2247
2248                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2249
2250                 /* Create header list */
2251                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
2252                 header = tny_msg_get_header (msg);
2253                 headers = tny_simple_list_new ();
2254                 tny_list_prepend (headers, G_OBJECT (header));
2255                 g_object_unref (header);
2256                 g_object_unref (msg);
2257
2258                 /* Ask user for confirmation. MSG-NOT404 */
2259                 response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2260                                                       TNY_FOLDER (folder_store), 
2261                                                       headers);
2262
2263                 /* Transfer current msg */
2264                 if (response == GTK_RESPONSE_OK) {
2265                         ModestMailOperation *mail_op;
2266
2267                         /* Create mail op */
2268                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE);
2269                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2270                                                          mail_op);
2271                         
2272                         /* Transfer messages */
2273                         modest_mail_operation_xfer_msgs (mail_op, 
2274                                                          headers,
2275                                                          TNY_FOLDER (folder_store),
2276                                                          TRUE);
2277                         g_object_unref (G_OBJECT (mail_op));
2278                 } else {
2279                         g_object_unref (headers);
2280                 }
2281                 g_object_unref (folder_store);
2282         }
2283         gtk_widget_destroy (dialog);
2284 }
2285
2286 void 
2287 modest_ui_actions_on_move_to (GtkAction *action, 
2288                               ModestWindow *win)
2289 {
2290         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
2291                           MODEST_IS_MSG_VIEW_WINDOW (win));
2292
2293         if (MODEST_IS_MAIN_WINDOW (win)) 
2294                 modest_ui_actions_on_main_window_move_to (action, 
2295                                                           MODEST_MAIN_WINDOW (win));
2296         else
2297                 modest_ui_actions_on_msg_view_window_move_to (action, 
2298                                                               MODEST_MSG_VIEW_WINDOW (win));
2299 }
2300
2301 /*
2302  * Calls #HeadersFunc for each header already selected in the main
2303  * window or the message currently being shown in the msg view window
2304  */
2305 static void
2306 do_headers_action (ModestWindow *win, 
2307                    HeadersFunc func,
2308                    gpointer user_data)
2309 {
2310         TnyList *headers_list;
2311         TnyIterator *iter;
2312
2313         /* Get headers */
2314         headers_list = get_selected_headers (win);
2315         if (!headers_list)
2316                 return;
2317
2318         /* Call the function for each header */
2319         iter = tny_list_create_iterator (headers_list);
2320         while (!tny_iterator_is_done (iter)) {
2321                 TnyHeader *header;
2322
2323                 header = TNY_HEADER (tny_iterator_get_current (iter));
2324                 func (header, win, user_data);
2325                 g_object_unref (header);
2326                 tny_iterator_next (iter);
2327         }
2328         g_object_unref (iter);
2329 }