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