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