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