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