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