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