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