* src/modest-address-book.h:
[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-msg-view-details-dialog.h>
51
52 #include "modest-account-mgr-helpers.h"
53 #include "modest-mail-operation.h"
54
55 #ifdef MODEST_HAVE_EASYSETUP
56 #include "easysetup/modest-easysetup-wizard.h"
57 #endif /*MODEST_HAVE_EASYSETUP*/
58
59 #include <modest-widget-memory.h>
60 #include <tny-error.h>
61 #include <tny-simple-list.h>
62 #include <tny-msg-view.h>
63 #include <tny-device.h>
64
65
66 typedef struct _GetMsgAsyncHelper {
67         ModestWindow *window;
68         TnyIterator *iter;
69         GFunc func;
70         gpointer user_data;
71 } GetMsgAsyncHelper;
72
73 typedef enum _ReplyForwardAction {
74         ACTION_REPLY,
75         ACTION_REPLY_TO_ALL,
76         ACTION_FORWARD
77 } ReplyForwardAction;
78
79 typedef struct _ReplyForwardHelper {
80 guint reply_forward_type;
81         ReplyForwardAction action;
82         gchar *account_name;
83 } ReplyForwardHelper;
84
85
86 static void     reply_forward_func     (gpointer data, gpointer user_data);
87 static void     read_msg_func          (gpointer data, gpointer user_data);
88 static void     get_msg_cb             (TnyFolder *folder, TnyMsg *msg, GError **err, 
89                                         gpointer user_data);
90 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
91 static void     modest_ui_actions_message_details_cb (gpointer msg_data, 
92                                                       gpointer helper_data);
93 static gchar*   ask_for_folder_name    (GtkWindow *parent_window, const gchar *title);
94
95
96 void   
97 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
98 {
99         GtkWidget *about;
100         const gchar *authors[] = {
101                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
102                 NULL
103         };
104         about = gtk_about_dialog_new ();
105         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
106         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
107         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
108                                         _("Copyright (c) 2006, Nokia Corporation\n"
109                                           "All rights reserved."));
110         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
111                                        _("a modest e-mail client\n\n"
112                                          "design and implementation: Dirk-Jan C. Binnema\n"
113                                          "contributions from the fine people at KernelConcepts and Igalia\n"
114                                          "uses the tinymail email framework written by Philip van Hoof"));
115         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
116         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
117         
118         gtk_dialog_run (GTK_DIALOG (about));
119         gtk_widget_destroy(about);
120 }
121
122
123 static TnyList *
124 get_selected_headers (ModestWindow *win)
125 {
126         if (MODEST_IS_MAIN_WINDOW(win)) {
127                 GtkWidget *header_view;         
128                 
129                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
130                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
131                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
132                 
133         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
134                 /* for MsgViewWindows, we simply return a list with one element */
135                 TnyMsg *msg;
136                 TnyHeader *header;
137                 TnyList *list = NULL;
138                 
139                 msg  = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
140                 if (msg) {
141                         header = tny_msg_get_header (msg);
142                         list = tny_simple_list_new ();
143                         tny_list_prepend (list, G_OBJECT(header));
144                         g_object_unref (G_OBJECT(header));
145                 }
146                 return list;
147
148         } else
149                 return NULL;
150 }
151
152 void
153 modest_ui_actions_on_delete (GtkAction *action, ModestWindow *win)
154 {
155         TnyList *header_list;
156         TnyIterator *iter;
157
158         g_return_if_fail (MODEST_IS_WINDOW(win));
159                 
160         header_list = get_selected_headers (win);
161         
162         if (header_list) {
163                 iter = tny_list_create_iterator (header_list);
164                 do {
165                         TnyHeader *header;
166                         ModestMailOperation *mail_op;
167
168                         header = TNY_HEADER (tny_iterator_get_current (iter));
169                         /* TODO: thick grain mail operation involving
170                            a list of objects. Composite pattern ??? */
171                         /* TODO: add confirmation dialog */
172                         mail_op = modest_mail_operation_new ();
173                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
174                                                          mail_op);
175
176                         /* Always delete. TODO: Move to trash still not supported */
177                         modest_mail_operation_remove_msg (mail_op, header, FALSE);
178
179                         /* Frees */
180                         g_object_unref (G_OBJECT (mail_op));
181                         g_object_unref (G_OBJECT (header));
182
183                         tny_iterator_next (iter);
184
185                 } while (!tny_iterator_is_done (iter));
186
187                 /* Free iter */
188                 g_object_unref (G_OBJECT (iter));
189         }
190
191         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
192                 gtk_widget_destroy (GTK_WIDGET(win));
193         } 
194 }
195
196
197 void
198 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
199 {
200         gtk_main_quit ();
201 }
202
203 void
204 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
205 {
206         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
207                 gtk_widget_destroy (GTK_WIDGET (win));
208         } else if (MODEST_IS_WINDOW (win)) {
209                 gtk_widget_destroy (GTK_WIDGET (win));
210         } else {
211                 g_return_if_reached ();
212         }
213 }
214
215 void
216 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
217 {
218         GtkClipboard *clipboard = NULL;
219         gchar *selection = NULL;
220
221         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
222         selection = gtk_clipboard_wait_for_text (clipboard);
223
224         modest_address_book_add_address (selection);
225         g_free (selection);
226 }
227
228 void
229 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
230 {
231         
232         /* This is currently only implemented for Maemo,
233          * because it requires a providers preset file which is not publically available.
234          */
235 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
236         GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr());
237         gboolean accounts_exist = account_names != NULL;
238         g_slist_free (account_names);
239         
240 /* To test, while modest_account_mgr_account_names() is broken: accounts_exist = TRUE; */
241         if (!accounts_exist) {
242                 /* If there are no accounts yet, just show the easy-setup wizard, as per the UI spec: */
243                 ModestEasysetupWizardDialog *wizard = modest_easysetup_wizard_dialog_new ();
244                 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
245                 gtk_dialog_run (GTK_DIALOG (wizard));
246                 gtk_widget_destroy (GTK_WIDGET (wizard));
247         } else  {
248                 /* Show the list of accounts: */
249                 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
250                 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW(win));
251                 gtk_dialog_run (account_win);
252                 gtk_widget_destroy (GTK_WIDGET(account_win));
253         }
254 #else
255         GtkWidget *dialog, *label;
256         
257         /* Create the widgets */
258         
259         dialog = gtk_dialog_new_with_buttons ("Message",
260                                               GTK_WINDOW(win),
261                                               GTK_DIALOG_DESTROY_WITH_PARENT,
262                                               GTK_STOCK_OK,
263                                               GTK_RESPONSE_NONE,
264                                               NULL);
265         label = gtk_label_new ("Hello World!");
266         
267         /* Ensure that the dialog box is destroyed when the user responds. */
268         
269         g_signal_connect_swapped (dialog, "response", 
270                                   G_CALLBACK (gtk_widget_destroy),
271                                   dialog);
272         
273         /* Add the label, and show everything we've added to the dialog. */
274         
275         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
276                            label);
277         gtk_widget_show_all (dialog);
278 #endif /* MODEST_PLATFORM_MAEMO */
279 }
280
281 void
282 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
283 {
284         ModestWindow *msg_win;
285         TnyMsg *msg = NULL;
286         TnyFolder *folder = NULL;
287         gchar *account_name = NULL;
288         gchar *from_str = NULL;
289         GError *err = NULL;
290         TnyAccount *account = NULL;
291         ModestWindowMgr *mgr;
292         
293         account_name = g_strdup(modest_window_get_active_account (win));
294         if (!account_name)
295                 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
296         if (!account_name) {
297                 g_printerr ("modest: no account found\n");
298                 goto cleanup;
299         }
300         
301         account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
302                                                                        account_name,
303                                                                        TNY_ACCOUNT_TYPE_STORE);
304         if (!account) {
305                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
306                 goto cleanup;
307         }
308
309         from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
310
311         msg    = modest_tny_msg_new ("", from_str, "", "", "", "", NULL);
312         if (!msg) {
313                 g_printerr ("modest: failed to create new msg\n");
314                 goto cleanup;
315         }
316         
317         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
318         if (!folder) {
319                 g_printerr ("modest: failed to find Drafts folder\n");
320                 goto cleanup;
321         }
322         
323         tny_folder_add_msg (folder, msg, &err);
324         if (err) {
325                 g_printerr ("modest: error adding msg to Drafts folder: %s",
326                             err->message);
327                 g_error_free (err);
328                 goto cleanup;
329         }
330
331         /* Create and register edit window */
332         msg_win = modest_msg_edit_window_new (msg, account_name);
333         mgr = modest_runtime_get_window_mgr ();
334         modest_window_mgr_register_window (mgr, msg_win);
335
336         if (win)
337                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
338                                               GTK_WINDOW (win));        
339         gtk_widget_show_all (GTK_WIDGET (msg_win));
340
341 cleanup:
342         g_free (account_name);
343         g_free (from_str);
344         if (account)
345                 g_object_unref (G_OBJECT(account));
346         if (msg)
347                 g_object_unref (G_OBJECT(msg));
348         if (folder)
349                 g_object_unref (G_OBJECT(folder));
350 }
351
352
353 void
354 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
355 {
356         modest_runtime_not_implemented (GTK_WINDOW(win)); /* FIXME */
357 }
358
359
360
361 static void
362 reply_forward_func (gpointer data, gpointer user_data)
363 {
364         TnyMsg *msg, *new_msg;
365         GetMsgAsyncHelper *helper;
366         ReplyForwardHelper *rf_helper;
367         ModestWindow *msg_win;
368         ModestEditType edit_type;
369         gchar *from;
370         GError *err = NULL;
371         TnyFolder *folder = NULL;
372         TnyAccount *account = NULL;
373         ModestWindowMgr *mgr;
374         
375         msg = TNY_MSG (data);
376         helper = (GetMsgAsyncHelper *) user_data;
377         rf_helper = (ReplyForwardHelper *) helper->user_data;
378
379         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
380                                                    rf_helper->account_name);
381         /* Create reply mail */
382         switch (rf_helper->action) {
383         case ACTION_REPLY:
384                 new_msg = 
385                         modest_tny_msg_create_reply_msg (msg,  from, 
386                                                          rf_helper->reply_forward_type,
387                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
388                 break;
389         case ACTION_REPLY_TO_ALL:
390                 new_msg = 
391                         modest_tny_msg_create_reply_msg (msg, from, rf_helper->reply_forward_type,
392                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
393                 edit_type = MODEST_EDIT_TYPE_REPLY;
394                 break;
395         case ACTION_FORWARD:
396                 new_msg = 
397                         modest_tny_msg_create_forward_msg (msg, from, rf_helper->reply_forward_type);
398                 edit_type = MODEST_EDIT_TYPE_FORWARD;
399                 break;
400         default:
401                 g_return_if_reached ();
402                 return;
403         }
404
405         if (!new_msg) {
406                 g_printerr ("modest: failed to create message\n");
407                 goto cleanup;
408         }
409
410         account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
411                                                                        rf_helper->account_name,
412                                                                        TNY_ACCOUNT_TYPE_STORE);
413         if (!account) {
414                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
415                 goto cleanup;
416         }
417
418         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
419         if (!folder) {
420                 g_printerr ("modest: failed to find Drafts folder\n");
421                 goto cleanup;
422         }
423         
424         tny_folder_add_msg (folder, msg, &err);
425         if (err) {
426                 g_printerr ("modest: error adding msg to Drafts folder: %s",
427                             err->message);
428                 g_error_free (err);
429                 goto cleanup;
430         }       
431
432         /* Create and register the windows */                   
433         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
434         mgr = modest_runtime_get_window_mgr ();
435         modest_window_mgr_register_window (mgr, msg_win);
436
437         /* Show edit window */
438         gtk_widget_show_all (GTK_WIDGET (msg_win));
439
440 cleanup:
441         if (new_msg)
442                 g_object_unref (G_OBJECT (new_msg));
443         if (folder)
444                 g_object_unref (G_OBJECT (folder));
445         if (account)
446                 g_object_unref (G_OBJECT (account));
447         
448         g_free (rf_helper->account_name);
449         g_slice_free (ReplyForwardHelper, rf_helper);
450 }
451 /*
452  * Common code for the reply and forward actions
453  */
454 static void
455 reply_forward (ReplyForwardAction action, ModestWindow *win)
456 {
457         TnyList *header_list;
458         guint reply_forward_type;
459         TnyHeader *header;
460         TnyFolder *folder;
461         GetMsgAsyncHelper *helper;
462         ReplyForwardHelper *rf_helper;
463         
464         g_return_if_fail (MODEST_IS_WINDOW(win));
465
466         header_list = get_selected_headers (win);
467         if (!header_list)
468                 return;
469         
470         reply_forward_type = modest_conf_get_int (modest_runtime_get_conf (),
471                                                   (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
472                                                   NULL);
473         /* We assume that we can only select messages of the
474            same folder and that we reply all of them from the
475            same account. In fact the interface currently only
476            allows single selection */
477         
478         /* Fill helpers */
479         rf_helper = g_slice_new0 (ReplyForwardHelper);
480         rf_helper->reply_forward_type = reply_forward_type;
481         rf_helper->action = action;
482
483         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
484         if (!rf_helper->account_name)
485                 rf_helper->account_name =
486                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
487
488         helper = g_slice_new0 (GetMsgAsyncHelper);
489         helper->window = win;
490         helper->func = reply_forward_func;
491         helper->iter = tny_list_create_iterator (header_list);
492         helper->user_data = rf_helper;
493
494         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
495                 TnyMsg *msg;
496                 msg = modest_msg_view_window_get_message(MODEST_MSG_VIEW_WINDOW(win));
497                 if (!msg) {
498                         g_printerr ("modest: no message found\n");
499                         return;
500                 } else
501                         reply_forward_func (msg, helper);
502         } else {
503                 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
504                 folder = tny_header_get_folder (header);
505                 if (folder) {
506                         /* The callback will call it per each header */
507                         tny_folder_get_msg_async (folder, header, get_msg_cb, helper);
508                         g_object_unref (G_OBJECT (folder));
509                 } else 
510                         g_printerr ("modest: no folder for header\n");
511                 
512                 /* Clean */
513                 g_object_unref (G_OBJECT (header));
514         }
515 }
516
517
518 void
519 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
520 {
521         g_return_if_fail (MODEST_IS_WINDOW(win));
522
523         reply_forward (ACTION_REPLY, win);
524 }
525
526 void
527 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
528 {
529         g_return_if_fail (MODEST_IS_WINDOW(win));
530
531         reply_forward (ACTION_FORWARD, win);
532 }
533
534 void
535 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
536 {
537         g_return_if_fail (MODEST_IS_WINDOW(win));
538
539         reply_forward (ACTION_REPLY_TO_ALL, win);
540 }
541
542 void 
543 modest_ui_actions_on_next (GtkAction *action, 
544                            ModestWindow *window)
545 {
546         if (MODEST_IS_MAIN_WINDOW (window)) {
547                 GtkWidget *header_view;
548
549                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
550                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
551                 if (!header_view)
552                         return;
553         
554                 modest_header_view_select_next (MODEST_HEADER_VIEW(header_view)); 
555         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
556                 modest_msg_view_window_select_next_message (MODEST_MSG_VIEW_WINDOW (window));
557         } else {
558                 g_return_if_reached ();
559         }
560 }
561
562 void 
563 modest_ui_actions_on_prev (GtkAction *action, 
564                            ModestWindow *window)
565 {
566         g_return_if_fail (MODEST_IS_WINDOW(window));
567
568         if (MODEST_IS_MAIN_WINDOW (window)) {
569                 GtkWidget *header_view;
570                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
571                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
572                 if (!header_view)
573                         return;
574                 
575                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
576         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
577                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
578         } else {
579                 g_return_if_reached ();
580         }
581 }
582
583
584 static gboolean
585 action_send (const gchar* account_name)
586 {
587         TnyAccount *tny_account;
588         ModestTnySendQueue *send_queue;
589
590         g_return_val_if_fail (account_name, FALSE);
591
592         tny_account = 
593                 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
594                                                                      account_name,
595                                                                      TNY_ACCOUNT_TYPE_TRANSPORT);
596         if (!tny_account) {
597                 g_printerr ("modest: cannot get tny transport account for %s\n", account_name);
598                 return FALSE;
599         }
600         send_queue = modest_tny_send_queue_new (TNY_CAMEL_TRANSPORT_ACCOUNT(tny_account));
601         if (!send_queue) {
602                 g_object_unref (G_OBJECT(tny_account));
603                 g_printerr ("modest: cannot get send queue for %s\n", account_name);
604                 return FALSE;
605         }
606         
607         //modest_tny_send_queue_flush (send_queue);
608
609         g_object_unref (G_OBJECT(send_queue));
610         g_object_unref (G_OBJECT(tny_account));
611
612         return TRUE;
613 }
614
615
616 static gboolean
617 action_receive (const gchar* account_name)
618 {
619         TnyAccount *tny_account;
620         ModestMailOperation *mail_op;
621
622         g_return_val_if_fail (account_name, FALSE);
623
624         tny_account = 
625                 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
626                                                                      account_name,
627                                                                      TNY_ACCOUNT_TYPE_STORE);
628         if (!tny_account) {
629                 g_printerr ("modest: cannot get tny store account for %s\n", account_name);
630                 return FALSE;
631         }
632
633         /* Create the mail operation */
634         mail_op = modest_mail_operation_new ();
635         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
636         modest_mail_operation_update_account (mail_op, TNY_STORE_ACCOUNT(tny_account));
637
638         g_object_unref (G_OBJECT(tny_account));
639         g_object_unref (G_OBJECT (mail_op));
640                 
641         return TRUE;
642 }
643
644
645
646 void
647 modest_ui_actions_on_send_receive (GtkAction *action,  ModestWindow *win)
648 {
649         gchar *account_name;
650         
651         account_name =
652                 g_strdup(modest_window_get_active_account(MODEST_WINDOW(win)));
653         if (!account_name)
654                 account_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
655         if (!account_name) {
656                 g_printerr ("modest: cannot get account\n");
657                 return;
658         }
659
660         if (!action_send(account_name))
661                 g_printerr ("modest: failed to send\n");
662         if (!action_receive(account_name))
663                 g_printerr ("modest: failed to receive\n");
664 }
665
666
667
668 void
669 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
670 {
671         ModestConf *conf;
672         GtkWidget *header_view;
673         
674         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
675
676         header_view = modest_main_window_get_child_widget (main_window,
677                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
678         if (!header_view)
679                 return;
680
681         conf = modest_runtime_get_conf ();
682         
683         /* what is saved/restored is depending on the style; thus; we save with
684          * old style, then update the style, and restore for this new style
685          */
686         modest_widget_memory_save (conf, G_OBJECT(header_view), "header-view");
687         
688         if (modest_header_view_get_style
689             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
690                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
691                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
692         else
693                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
694                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
695
696         modest_widget_memory_restore (conf, G_OBJECT(header_view),
697                                       "header-view");
698 }
699
700
701
702 /*
703  * Marks a message as read and passes it to the msg preview widget
704  */
705 static void
706 read_msg_func (gpointer data, gpointer user_data)
707 {
708         TnyMsg *msg;
709         TnyHeader *header;
710         GetMsgAsyncHelper *helper;
711         TnyHeaderFlags header_flags;
712         GtkWidget *msg_preview;
713         
714         msg = TNY_MSG (data);
715         helper = (GetMsgAsyncHelper *) user_data;
716
717         msg_preview = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (helper->window),
718                                                            MODEST_WIDGET_TYPE_MSG_PREVIEW);
719         if (!msg_preview)
720                 return;
721         
722         header = TNY_HEADER (tny_iterator_get_current (helper->iter));
723         header_flags = tny_header_get_flags (header);
724         tny_header_set_flags (header, header_flags | TNY_HEADER_FLAG_SEEN);
725         g_object_unref (G_OBJECT (header));
726
727         /* Set message on msg view */
728         modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), msg);
729 }
730
731 /*
732  * This function is a generic handler for the tny_folder_get_msg_async
733  * call. It expects as user_data a #GetMsgAsyncHelper. This helper
734  * contains a user provided function that is called inside this
735  * method. This will allow us to use this callback in many different
736  * places. This callback performs the common actions for the
737  * get_msg_async call, more specific actions will be done by the user
738  * function
739  */
740 static void
741 get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
742 {
743         GetMsgAsyncHelper *helper;
744
745         helper = (GetMsgAsyncHelper *) user_data;
746
747         if ((*err && ((*err)->code == TNY_FOLDER_ERROR_GET_MSG)) || !msg) {
748                 modest_ui_actions_on_item_not_found (NULL,
749                                                      MODEST_ITEM_TYPE_MESSAGE,
750                                                      helper->window);
751                 return;
752         }
753
754         /* Call user function */
755         helper->func (msg, user_data);
756
757         /* Process next element (if exists) */
758         tny_iterator_next (helper->iter);
759         if (tny_iterator_is_done (helper->iter)) {
760                 TnyList *headers;
761                 headers = tny_iterator_get_list (helper->iter);
762                 /* Free resources */
763                 g_object_unref (G_OBJECT (headers));
764                 g_object_unref (G_OBJECT (helper->iter));
765                 g_slice_free (GetMsgAsyncHelper, helper);
766         } else {
767                 TnyHeader *header;
768                 header = TNY_HEADER (tny_iterator_get_current (helper->iter)); 
769                 tny_folder_get_msg_async (folder, header,                         
770                                           get_msg_cb, helper);
771                 g_object_unref (G_OBJECT(header));
772         }
773 }
774
775 void 
776 modest_ui_actions_on_header_selected (ModestHeaderView *folder_view, 
777                                       TnyHeader *header,
778                                       ModestMainWindow *main_window)
779 {
780         GtkWidget *msg_preview;
781         TnyFolder *folder;
782         GetMsgAsyncHelper *helper;
783         TnyList *list;
784
785         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
786         
787         msg_preview = modest_main_window_get_child_widget(main_window,
788                                                           MODEST_WIDGET_TYPE_MSG_PREVIEW);
789         if (!msg_preview)
790                 return;
791         
792         /* when there's no header, clear the msgview */
793         if (!header) {
794                 modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), NULL);
795                 return;
796         }
797
798         folder = tny_header_get_folder (TNY_HEADER(header));
799
800         /* Create list */
801         list = tny_simple_list_new ();
802         tny_list_prepend (list, G_OBJECT (header));
803
804         /* Fill helper data */
805         helper = g_slice_new0 (GetMsgAsyncHelper);
806         helper->window = MODEST_WINDOW (main_window);
807         helper->iter = tny_list_create_iterator (list);
808         helper->func = read_msg_func;
809
810         tny_folder_get_msg_async (TNY_FOLDER(folder),
811                                   header, get_msg_cb,
812                                   helper);
813
814         /* Frees */
815         g_object_unref (G_OBJECT (folder));
816 }
817
818
819
820 void 
821 modest_ui_actions_on_header_activated (ModestHeaderView *folder_view, TnyHeader *header,
822                                        ModestMainWindow *main_window)
823 {
824         ModestWindow *win = NULL;
825         TnyFolder *folder = NULL;
826         TnyMsg    *msg    = NULL;
827         ModestWindowMgr *mgr;
828         
829         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
830         
831         if (!header)
832                 return;
833
834         folder = tny_header_get_folder (header);
835         if (!folder) {
836                 g_printerr ("modest: cannot get folder for header\n");
837                 return;
838         }
839
840         /* FIXME: make async?; check error  */
841         msg = tny_folder_get_msg (folder, header, NULL);
842         if (!msg) {
843                 g_printerr ("modest: cannot get msg for header\n");
844                 goto cleanup;
845         }
846
847         /* Look if we already have a message view for that header */    
848         mgr = modest_runtime_get_window_mgr ();
849         win = modest_window_mgr_find_window_by_msguid (mgr, tny_header_get_uid (header));
850
851         /* If not, create a new window */
852         if (!win) {
853                 gchar *account;
854
855                 account =  g_strdup(modest_window_get_active_account(MODEST_WINDOW(main_window)));
856                 if (!account)
857                         account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
858
859                 win = modest_msg_view_window_new (msg, account);
860                 modest_window_mgr_register_window (mgr, win);
861
862                 gtk_window_set_transient_for (GTK_WINDOW (win),
863                                               GTK_WINDOW (main_window));
864         }
865
866         gtk_widget_show_all (GTK_WIDGET(win));
867
868         g_object_unref (G_OBJECT (msg));
869         
870 cleanup:
871         g_object_unref (G_OBJECT (folder));
872 }
873
874 void 
875 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
876                                                TnyFolder *folder, 
877                                                gboolean selected,
878                                                ModestMainWindow *main_window)
879 {
880         ModestConf *conf;
881         GtkWidget *header_view;
882         
883         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
884
885         header_view = modest_main_window_get_child_widget(main_window,
886                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
887         if (!header_view)
888                 return;
889         
890         conf = modest_runtime_get_conf ();
891
892         if (!selected) { /* the folder was unselected; save it's settings  */
893                 modest_widget_memory_save (conf, G_OBJECT (header_view), "header-view");
894                 gtk_window_set_title (GTK_WINDOW(main_window), NULL);
895                 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
896         } else {  /* the folder was selected */
897                 if (folder) { /* folder may be NULL */
898                         guint unread;
899
900                         /* Change main window title */                  
901                         unread = tny_folder_get_unread_count (folder);
902
903                         if (unread == 0) {
904                                 gtk_window_set_title (GTK_WINDOW(main_window), 
905                                                       tny_folder_get_name (folder));
906                         } else {
907                                 gchar *txt = g_strdup_printf (_("%s (%d)"),
908                                                               tny_folder_get_name (folder),
909                                                               unread);
910                                 gtk_window_set_title (GTK_WINDOW(main_window), txt);
911                                 g_free (txt);
912                         }
913                 } else {
914                         gtk_window_set_title (GTK_WINDOW(main_window), NULL);
915                 }
916
917                 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), folder);
918                 modest_widget_memory_restore (conf, G_OBJECT(header_view),
919                                               "header-view");
920         }
921 }
922
923 void 
924 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
925                                      ModestWindow *win)
926 {
927         GtkWidget *dialog;
928         gchar *txt, *item;
929         gboolean online;
930
931         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
932         
933         if (g_main_depth > 0)   
934                 gdk_threads_enter ();
935         online = tny_device_is_online (modest_runtime_get_device());
936
937         if (online) {
938                 /* already online -- the item is simply not there... */
939                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
940                                                  GTK_DIALOG_MODAL,
941                                                  GTK_MESSAGE_WARNING,
942                                                  GTK_BUTTONS_OK,
943                                                  _("The %s you selected cannot be found"),
944                                                  item);
945                 gtk_dialog_run (GTK_DIALOG(dialog));
946         } else {
947                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
948                                                       GTK_WINDOW (win),
949                                                       GTK_DIALOG_MODAL,
950                                                       GTK_STOCK_CANCEL,
951                                                       GTK_RESPONSE_REJECT,
952                                                       GTK_STOCK_OK,
953                                                       GTK_RESPONSE_ACCEPT,
954                                                       NULL);
955                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
956                                          "Do you want to get online?"), item);
957                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
958                                     gtk_label_new (txt), FALSE, FALSE, 0);
959                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
960                 g_free (txt);
961
962                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
963                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
964 //                      tny_device_force_online (modest_runtime_get_device());
965                 }
966         }
967         gtk_widget_destroy (dialog);
968         if (g_main_depth > 0)   
969                 gdk_threads_leave ();
970 }
971
972 void
973 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
974                                      ModestWindow *win)
975 {
976         g_message ("%s %s", __FUNCTION__, link);
977 }       
978
979
980 void
981 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
982                                         ModestWindow *win)
983 {
984         modest_platform_activate_uri (link);
985 }
986
987 void
988 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
989                                           ModestWindow *win)
990 {
991         modest_platform_show_uri_popup (link);
992 }
993
994 void
995 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
996                                              ModestWindow *win)
997 {
998         g_message (__FUNCTION__);
999         
1000 }
1001
1002 void
1003 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1004                                           const gchar *address,
1005                                           ModestWindow *win)
1006 {
1007         g_message ("%s %s", __FUNCTION__, address);
1008 }
1009
1010 void
1011 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1012 {
1013         TnyTransportAccount *transport_account;
1014         ModestMailOperation *mail_operation;
1015         MsgData *data;
1016         gchar *account_name, *from;
1017         ModestAccountMgr *account_mgr;
1018
1019         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1020         
1021         data = modest_msg_edit_window_get_msg_data (edit_window);
1022
1023         /* FIXME: Code added just for testing. The final version will
1024            use the send queue provided by tinymail and some
1025            classifier */
1026         account_mgr = modest_runtime_get_account_mgr();
1027         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1028         if (!account_name) 
1029                 account_name = modest_account_mgr_get_default_account (account_mgr);
1030         if (!account_name) {
1031                 g_printerr ("modest: no account found\n");
1032                 modest_msg_edit_window_free_msg_data (edit_window, data);
1033                 return;
1034         }
1035         transport_account =
1036                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
1037                                       (modest_runtime_get_account_store(),
1038                                        account_name,
1039                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1040         if (!transport_account) {
1041                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1042                 g_free (account_name);
1043                 modest_msg_edit_window_free_msg_data (edit_window, data);
1044                 return;
1045         }
1046         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1047
1048         /* Create the mail operation */         
1049         mail_operation = modest_mail_operation_new ();
1050         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1051
1052         modest_mail_operation_send_new_mail (mail_operation,
1053                                              transport_account,
1054                                              from,
1055                                              data->to, 
1056                                              data->cc, 
1057                                              data->bcc,
1058                                              data->subject, 
1059                                              data->plain_body, 
1060                                              data->html_body,
1061                                              data->attachments,
1062                                              data->priority_flags);
1063         /* Frees */
1064         g_free (from);
1065         g_free (account_name);
1066         g_object_unref (G_OBJECT (transport_account));
1067         g_object_unref (G_OBJECT (mail_operation));
1068
1069         modest_msg_edit_window_free_msg_data (edit_window, data);
1070
1071         /* Save settings and close the window */
1072         gtk_widget_destroy (GTK_WIDGET (edit_window));
1073 }
1074
1075 void 
1076 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1077                                   ModestMsgEditWindow *window)
1078 {
1079         ModestMsgEditFormatState *format_state = NULL;
1080
1081         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1082         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1083
1084         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1085                 return;
1086
1087         format_state = modest_msg_edit_window_get_format_state (window);
1088         g_return_if_fail (format_state != NULL);
1089
1090         format_state->bold = gtk_toggle_action_get_active (action);
1091         modest_msg_edit_window_set_format_state (window, format_state);
1092         g_free (format_state);
1093         
1094 }
1095
1096 void 
1097 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1098                                      ModestMsgEditWindow *window)
1099 {
1100         ModestMsgEditFormatState *format_state = NULL;
1101
1102         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1103         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1104
1105         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1106                 return;
1107
1108         format_state = modest_msg_edit_window_get_format_state (window);
1109         g_return_if_fail (format_state != NULL);
1110
1111         format_state->italics = gtk_toggle_action_get_active (action);
1112         modest_msg_edit_window_set_format_state (window, format_state);
1113         g_free (format_state);
1114         
1115 }
1116
1117 void 
1118 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
1119                                      ModestMsgEditWindow *window)
1120 {
1121         ModestMsgEditFormatState *format_state = NULL;
1122
1123         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1124         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1125
1126         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1127                 return;
1128
1129         format_state = modest_msg_edit_window_get_format_state (window);
1130         g_return_if_fail (format_state != NULL);
1131
1132         format_state->bullet = gtk_toggle_action_get_active (action);
1133         modest_msg_edit_window_set_format_state (window, format_state);
1134         g_free (format_state);
1135         
1136 }
1137
1138 void 
1139 modest_ui_actions_on_change_justify (GtkRadioAction *action,
1140                                      GtkRadioAction *selected,
1141                                      ModestMsgEditWindow *window)
1142 {
1143         ModestMsgEditFormatState *format_state = NULL;
1144         GtkJustification value;
1145
1146         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1147
1148         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1149                 return;
1150
1151         value = gtk_radio_action_get_current_value (selected);
1152
1153         format_state = modest_msg_edit_window_get_format_state (window);
1154         g_return_if_fail (format_state != NULL);
1155
1156         format_state->justification = value;
1157         modest_msg_edit_window_set_format_state (window, format_state);
1158         g_free (format_state);
1159 }
1160
1161 void 
1162 modest_ui_actions_on_select_editor_color (GtkAction *action,
1163                                           ModestMsgEditWindow *window)
1164 {
1165         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1166         g_return_if_fail (GTK_IS_ACTION (action));
1167
1168         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1169                 return;
1170
1171         modest_msg_edit_window_select_color (window);
1172 }
1173
1174 void 
1175 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
1176                                                      ModestMsgEditWindow *window)
1177 {
1178         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1179         g_return_if_fail (GTK_IS_ACTION (action));
1180
1181         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1182                 return;
1183
1184         modest_msg_edit_window_select_background_color (window);
1185 }
1186
1187 void 
1188 modest_ui_actions_on_insert_image (GtkAction *action,
1189                                    ModestMsgEditWindow *window)
1190 {
1191         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1192         g_return_if_fail (GTK_IS_ACTION (action));
1193
1194         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1195                 return;
1196
1197         modest_msg_edit_window_insert_image (window);
1198 }
1199
1200 /*
1201  * Shows a dialog with an entry that asks for some text. The returned
1202  * value must be freed by the caller. The dialog window title will be
1203  * set to @title.
1204  */
1205 static gchar *
1206 ask_for_folder_name (GtkWindow *parent_window,
1207                      const gchar *title)
1208 {
1209         GtkWidget *dialog, *entry;
1210         gchar *folder_name = NULL;
1211
1212         /* Ask for folder name */
1213         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1214                                               parent_window,
1215                                               GTK_DIALOG_MODAL,
1216                                               GTK_STOCK_CANCEL,
1217                                               GTK_RESPONSE_REJECT,
1218                                               GTK_STOCK_OK,
1219                                               GTK_RESPONSE_ACCEPT,
1220                                               NULL);
1221         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1222                             gtk_label_new(title),
1223                             FALSE, FALSE, 0);
1224                 
1225         entry = gtk_entry_new_with_max_length (40);
1226         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1227                             entry,
1228                             TRUE, FALSE, 0);    
1229         
1230         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1231         
1232         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
1233                 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1234
1235         gtk_widget_destroy (dialog);
1236
1237         return folder_name;
1238 }
1239
1240 void 
1241 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1242 {
1243         TnyFolder *parent_folder;
1244         GtkWidget *folder_view;
1245         
1246         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1247
1248         folder_view = modest_main_window_get_child_widget (main_window,
1249                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1250         if (!folder_view)
1251                 return;
1252
1253         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1254         
1255         if (parent_folder) {
1256                 gchar *folder_name;
1257
1258                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1259                                                    _("Please enter a name for the new folder"));
1260
1261                 if (folder_name != NULL && strlen (folder_name) > 0) {
1262                         TnyFolder *new_folder;
1263                         ModestMailOperation *mail_op;
1264
1265                         mail_op = modest_mail_operation_new ();
1266                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
1267                                                          mail_op);
1268
1269                         new_folder = modest_mail_operation_create_folder (mail_op,
1270                                                                           TNY_FOLDER_STORE (parent_folder),
1271                                                                           (const gchar *) folder_name);
1272                         if (new_folder) 
1273                                 g_object_unref (new_folder);
1274                         g_object_unref (mail_op);
1275                         g_free (folder_name);
1276                 }
1277                 g_object_unref (parent_folder);
1278         }
1279 }
1280
1281 void 
1282 modest_ui_actions_on_rename_folder (GtkAction *action,
1283                                      ModestMainWindow *main_window)
1284 {
1285         TnyFolder *folder;
1286         GtkWidget *folder_view;
1287         
1288         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1289
1290         folder_view = modest_main_window_get_child_widget (main_window,
1291                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1292         if (!folder_view)
1293                 return;
1294         
1295         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1296         
1297         if (folder) {
1298                 gchar *folder_name;
1299                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1300                                                    _("Please enter a new name for the folder"));
1301
1302                 if (folder_name != NULL && strlen (folder_name) > 0) {
1303                         ModestMailOperation *mail_op;
1304
1305                         mail_op = modest_mail_operation_new ();
1306                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1307                                                          mail_op);
1308
1309                         modest_mail_operation_rename_folder (mail_op,
1310                                                              folder,
1311                                                              (const gchar *) folder_name);
1312
1313                         g_object_unref (mail_op);
1314                         g_free (folder_name);
1315                 }
1316                 g_object_unref (folder);
1317         }
1318 }
1319
1320 static void
1321 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
1322 {
1323         TnyFolder *folder;
1324         ModestMailOperation *mail_op;
1325         GtkWidget *folder_view;
1326         
1327         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1328
1329         folder_view = modest_main_window_get_child_widget (main_window,
1330                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1331         if (!folder_view)
1332                 return;
1333
1334         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1335         
1336         mail_op = modest_mail_operation_new ();
1337         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1338                                          mail_op);
1339         modest_mail_operation_remove_folder (mail_op, folder, move_to_trash);
1340
1341         g_object_unref (G_OBJECT (mail_op));
1342         g_object_unref (G_OBJECT (folder));
1343 }
1344
1345 void 
1346 modest_ui_actions_on_delete_folder (GtkAction *action,
1347                                      ModestMainWindow *main_window)
1348 {
1349         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1350
1351         delete_folder (main_window, FALSE);
1352 }
1353
1354 void 
1355 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1356 {
1357         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1358         
1359         delete_folder (main_window, TRUE);
1360 }
1361
1362 void
1363 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
1364                                          const gchar* account_name,
1365                                          gchar **password, 
1366                                          gboolean *cancel, 
1367                                          gboolean *remember,
1368                                          ModestMainWindow *main_window)
1369 {
1370         gchar *txt;
1371         GtkWidget *dialog, *entry, *remember_pass_check;
1372
1373         dialog = gtk_dialog_new_with_buttons (_("Password requested"),
1374                                               NULL,
1375                                               GTK_DIALOG_MODAL,
1376                                               GTK_STOCK_CANCEL,
1377                                               GTK_RESPONSE_REJECT,
1378                                               GTK_STOCK_OK,
1379                                               GTK_RESPONSE_ACCEPT,
1380                                               NULL);
1381         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1382         
1383         txt = g_strdup_printf (_("Please enter your password for %s"), account_name);
1384         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1385                             FALSE, FALSE, 0);
1386         g_free (txt);
1387
1388         entry = gtk_entry_new_with_max_length (40);
1389         gtk_entry_set_visibility (GTK_ENTRY(entry), FALSE);
1390         gtk_entry_set_invisible_char (GTK_ENTRY(entry), 0x2022); /* bullet unichar */
1391         
1392         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry,
1393                             TRUE, FALSE, 0);    
1394
1395         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1396         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1397                             TRUE, FALSE, 0);
1398
1399         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1400         
1401         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1402                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry)));
1403                 *cancel   = FALSE;
1404         } else {
1405                 *password = NULL;
1406                 *cancel   = TRUE;
1407         }
1408
1409         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
1410                 *remember = TRUE;
1411         else
1412                 *remember = FALSE;
1413
1414         gtk_widget_destroy (dialog);
1415 }
1416
1417 void
1418 modest_ui_actions_on_cut (GtkAction *action,
1419                           ModestWindow *window)
1420 {
1421         GtkWidget *focused_widget;
1422
1423         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1424         if (GTK_IS_EDITABLE (focused_widget)) {
1425                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
1426         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1427                 GtkTextBuffer *buffer;
1428                 GtkClipboard *clipboard;
1429
1430                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1431                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1432                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
1433         }
1434 }
1435
1436 void
1437 modest_ui_actions_on_copy (GtkAction *action,
1438                            ModestWindow *window)
1439 {
1440         GtkClipboard *clipboard;
1441         GtkWidget *focused_widget;
1442
1443         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1444         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1445         if (GTK_IS_LABEL (focused_widget)) {
1446                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
1447         } else if (GTK_IS_EDITABLE (focused_widget)) {
1448                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
1449         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1450                 GtkTextBuffer *buffer;
1451
1452                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1453                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
1454         }
1455 }
1456
1457 void
1458 modest_ui_actions_on_paste (GtkAction *action,
1459                             ModestWindow *window)
1460 {
1461         GtkWidget *focused_widget;
1462
1463         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1464         if (GTK_IS_EDITABLE (focused_widget)) {
1465                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
1466         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1467                 GtkTextBuffer *buffer;
1468                 GtkClipboard *clipboard;
1469
1470                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1471                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1472                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
1473         }
1474 }
1475
1476 void
1477 modest_ui_actions_on_select_all (GtkAction *action,
1478                                  ModestWindow *window)
1479 {
1480         GtkWidget *focused_widget;
1481
1482         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1483         if (GTK_IS_LABEL (focused_widget)) {
1484                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
1485         } else if (GTK_IS_EDITABLE (focused_widget)) {
1486                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
1487         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1488                 GtkTextBuffer *buffer;
1489                 GtkTextIter start, end;
1490
1491                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1492                 gtk_text_buffer_get_start_iter (buffer, &start);
1493                 gtk_text_buffer_get_end_iter (buffer, &end);
1494                 gtk_text_buffer_select_range (buffer, &start, &end);
1495         }
1496 }
1497
1498 void
1499 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
1500                                   GtkRadioAction *selected,
1501                                   ModestWindow *window)
1502 {
1503         gint value;
1504
1505         value = gtk_radio_action_get_current_value (selected);
1506         if (MODEST_IS_WINDOW (window)) {
1507                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
1508         }
1509 }
1510
1511 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
1512                                                         GtkRadioAction *selected,
1513                                                         ModestWindow *window)
1514 {
1515         TnyHeaderFlags flags;
1516         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1517
1518         flags = gtk_radio_action_get_current_value (selected);
1519         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
1520 }
1521
1522
1523 void     
1524 modest_ui_actions_on_zoom_plus (GtkAction *action,
1525                                 ModestWindow *window)
1526 {
1527         g_return_if_fail (MODEST_IS_WINDOW (window));
1528
1529         modest_window_zoom_plus (MODEST_WINDOW (window));
1530 }
1531
1532 void     
1533 modest_ui_actions_on_zoom_minus (GtkAction *action,
1534                                  ModestWindow *window)
1535 {
1536         g_return_if_fail (MODEST_IS_WINDOW (window));
1537
1538         modest_window_zoom_minus (MODEST_WINDOW (window));
1539 }
1540
1541 void     
1542 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
1543                                            ModestWindow *window)
1544 {
1545         ModestWindowMgr *mgr;
1546         gboolean fullscreen, active;
1547         g_return_if_fail (MODEST_IS_WINDOW (window));
1548
1549         mgr = modest_runtime_get_window_mgr ();
1550
1551         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
1552         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1553
1554         if (active != fullscreen) {
1555                 modest_window_mgr_set_fullscreen_mode (mgr, active);
1556                 gtk_window_present (GTK_WINDOW (window));
1557         }
1558 }
1559
1560 void
1561 modest_ui_actions_on_change_fullscreen (GtkAction *action,
1562                                         ModestWindow *window)
1563 {
1564         ModestWindowMgr *mgr;
1565         gboolean fullscreen;
1566
1567         g_return_if_fail (MODEST_IS_WINDOW (window));
1568
1569         mgr = modest_runtime_get_window_mgr ();
1570         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1571         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
1572
1573         gtk_window_present (GTK_WINDOW (window));
1574 }
1575
1576 static void
1577 modest_ui_actions_message_details_cb (gpointer msg_data, 
1578                                       gpointer helper_data)
1579 {
1580         GtkWidget *dialog;
1581         TnyMsg *msg = (TnyMsg *) msg_data;
1582         TnyHeader *header;
1583         GetMsgAsyncHelper *helper = (GetMsgAsyncHelper *) helper_data;
1584         
1585         header = tny_msg_get_header (msg);
1586         
1587         dialog = modest_msg_view_details_dialog_new (GTK_WINDOW (helper->window), header);
1588         g_object_unref (header);
1589         gtk_widget_show_all (dialog);
1590
1591         gtk_dialog_run (GTK_DIALOG (dialog));
1592
1593         gtk_widget_destroy (dialog);
1594 }
1595
1596 void     
1597 modest_ui_actions_on_message_details (GtkAction *action, 
1598                                       ModestWindow *win)
1599 {
1600         TnyList * headers_list;
1601         GetMsgAsyncHelper *helper;
1602
1603         headers_list = get_selected_headers (win);
1604         if (!headers_list)
1605                 return;
1606
1607         helper = g_slice_new0 (GetMsgAsyncHelper);
1608         helper->window = win;
1609         helper->func = modest_ui_actions_message_details_cb;
1610         helper->iter = tny_list_create_iterator (headers_list);
1611         helper->user_data = NULL;
1612
1613         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1614                 TnyMsg *msg;
1615
1616                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
1617                 if (!msg)
1618                         return;
1619                 else {
1620                         modest_ui_actions_message_details_cb (msg, helper);
1621                 }
1622         } else {
1623                 /* here we should add an implementation to run the message details dialog
1624                    from the main window */
1625                 g_return_if_reached ();
1626         }
1627 }
1628
1629 void     
1630 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
1631                                      ModestMsgEditWindow *window)
1632 {
1633         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1634
1635         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
1636 }
1637
1638 void     
1639 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
1640                                       ModestMsgEditWindow *window)
1641 {
1642         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1643
1644         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
1645 }
1646
1647 void
1648 modest_ui_actions_toggle_folders_view (GtkAction *action, 
1649                                        ModestMainWindow *main_window)
1650 {
1651         ModestConf *conf;
1652         
1653         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1654
1655         conf = modest_runtime_get_conf ();
1656         
1657         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
1658                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
1659         else
1660                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
1661 }
1662
1663 void 
1664 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
1665                                      ModestWindow *window)
1666 {
1667         gboolean active, fullscreen = FALSE;
1668         ModestWindowMgr *mgr;
1669
1670         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
1671
1672         /* Check if we want to toggle the toolbar vuew in fullscreen
1673            or normal mode */
1674         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
1675                      "ViewShowToolbarFullScreen")) {
1676                 fullscreen = TRUE;
1677         }
1678
1679         /* Toggle toolbar */
1680         mgr = modest_runtime_get_window_mgr ();
1681         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
1682 }