* Added MMC icon name
[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         /* Frees */
1063         g_free (from);
1064         g_free (account_name);
1065         g_object_unref (G_OBJECT (transport_account));
1066         g_object_unref (G_OBJECT (mail_operation));
1067
1068         modest_msg_edit_window_free_msg_data (edit_window, data);
1069
1070         /* Save settings and close the window */
1071         gtk_widget_destroy (GTK_WIDGET (edit_window));
1072 }
1073
1074 void 
1075 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1076                                   ModestMsgEditWindow *window)
1077 {
1078         ModestMsgEditFormatState *format_state = NULL;
1079
1080         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1081         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1082
1083         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1084                 return;
1085
1086         format_state = modest_msg_edit_window_get_format_state (window);
1087         g_return_if_fail (format_state != NULL);
1088
1089         format_state->bold = gtk_toggle_action_get_active (action);
1090         modest_msg_edit_window_set_format_state (window, format_state);
1091         g_free (format_state);
1092         
1093 }
1094
1095 void 
1096 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1097                                      ModestMsgEditWindow *window)
1098 {
1099         ModestMsgEditFormatState *format_state = NULL;
1100
1101         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1102         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1103
1104         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1105                 return;
1106
1107         format_state = modest_msg_edit_window_get_format_state (window);
1108         g_return_if_fail (format_state != NULL);
1109
1110         format_state->italics = gtk_toggle_action_get_active (action);
1111         modest_msg_edit_window_set_format_state (window, format_state);
1112         g_free (format_state);
1113         
1114 }
1115
1116 void 
1117 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
1118                                      ModestMsgEditWindow *window)
1119 {
1120         ModestMsgEditFormatState *format_state = NULL;
1121
1122         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1123         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1124
1125         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1126                 return;
1127
1128         format_state = modest_msg_edit_window_get_format_state (window);
1129         g_return_if_fail (format_state != NULL);
1130
1131         format_state->bullet = gtk_toggle_action_get_active (action);
1132         modest_msg_edit_window_set_format_state (window, format_state);
1133         g_free (format_state);
1134         
1135 }
1136
1137 void 
1138 modest_ui_actions_on_change_justify (GtkRadioAction *action,
1139                                      GtkRadioAction *selected,
1140                                      ModestMsgEditWindow *window)
1141 {
1142         ModestMsgEditFormatState *format_state = NULL;
1143         GtkJustification value;
1144
1145         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1146
1147         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1148                 return;
1149
1150         value = gtk_radio_action_get_current_value (selected);
1151
1152         format_state = modest_msg_edit_window_get_format_state (window);
1153         g_return_if_fail (format_state != NULL);
1154
1155         format_state->justification = value;
1156         modest_msg_edit_window_set_format_state (window, format_state);
1157         g_free (format_state);
1158 }
1159
1160 void 
1161 modest_ui_actions_on_select_editor_color (GtkAction *action,
1162                                           ModestMsgEditWindow *window)
1163 {
1164         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1165         g_return_if_fail (GTK_IS_ACTION (action));
1166
1167         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1168                 return;
1169
1170         modest_msg_edit_window_select_color (window);
1171 }
1172
1173 void 
1174 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
1175                                                      ModestMsgEditWindow *window)
1176 {
1177         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1178         g_return_if_fail (GTK_IS_ACTION (action));
1179
1180         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1181                 return;
1182
1183         modest_msg_edit_window_select_background_color (window);
1184 }
1185
1186 void 
1187 modest_ui_actions_on_insert_image (GtkAction *action,
1188                                    ModestMsgEditWindow *window)
1189 {
1190         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1191         g_return_if_fail (GTK_IS_ACTION (action));
1192
1193         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1194                 return;
1195
1196         modest_msg_edit_window_insert_image (window);
1197 }
1198
1199 /*
1200  * Shows a dialog with an entry that asks for some text. The returned
1201  * value must be freed by the caller. The dialog window title will be
1202  * set to @title.
1203  */
1204 static gchar *
1205 ask_for_folder_name (GtkWindow *parent_window,
1206                      const gchar *title)
1207 {
1208         GtkWidget *dialog, *entry;
1209         gchar *folder_name = NULL;
1210
1211         /* Ask for folder name */
1212         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1213                                               parent_window,
1214                                               GTK_DIALOG_MODAL,
1215                                               GTK_STOCK_CANCEL,
1216                                               GTK_RESPONSE_REJECT,
1217                                               GTK_STOCK_OK,
1218                                               GTK_RESPONSE_ACCEPT,
1219                                               NULL);
1220         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1221                             gtk_label_new(title),
1222                             FALSE, FALSE, 0);
1223                 
1224         entry = gtk_entry_new_with_max_length (40);
1225         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1226                             entry,
1227                             TRUE, FALSE, 0);    
1228         
1229         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1230         
1231         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
1232                 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1233
1234         gtk_widget_destroy (dialog);
1235
1236         return folder_name;
1237 }
1238
1239 void 
1240 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1241 {
1242         TnyFolder *parent_folder;
1243         GtkWidget *folder_view;
1244         
1245         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1246
1247         folder_view = modest_main_window_get_child_widget (main_window,
1248                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1249         if (!folder_view)
1250                 return;
1251
1252         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1253         
1254         if (parent_folder) {
1255                 gchar *folder_name;
1256
1257                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1258                                                    _("Please enter a name for the new folder"));
1259
1260                 if (folder_name != NULL && strlen (folder_name) > 0) {
1261                         TnyFolder *new_folder;
1262                         ModestMailOperation *mail_op;
1263
1264                         mail_op = modest_mail_operation_new ();
1265                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
1266                                                          mail_op);
1267
1268                         new_folder = modest_mail_operation_create_folder (mail_op,
1269                                                                           TNY_FOLDER_STORE (parent_folder),
1270                                                                           (const gchar *) folder_name);
1271                         if (new_folder) 
1272                                 g_object_unref (new_folder);
1273                         g_object_unref (mail_op);
1274                         g_free (folder_name);
1275                 }
1276                 g_object_unref (parent_folder);
1277         }
1278 }
1279
1280 void 
1281 modest_ui_actions_on_rename_folder (GtkAction *action,
1282                                      ModestMainWindow *main_window)
1283 {
1284         TnyFolder *folder;
1285         GtkWidget *folder_view;
1286         
1287         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1288
1289         folder_view = modest_main_window_get_child_widget (main_window,
1290                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1291         if (!folder_view)
1292                 return;
1293         
1294         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1295         
1296         if (folder) {
1297                 gchar *folder_name;
1298                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1299                                                    _("Please enter a new name for the folder"));
1300
1301                 if (folder_name != NULL && strlen (folder_name) > 0) {
1302                         ModestMailOperation *mail_op;
1303
1304                         mail_op = modest_mail_operation_new ();
1305                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1306                                                          mail_op);
1307
1308                         modest_mail_operation_rename_folder (mail_op,
1309                                                              folder,
1310                                                              (const gchar *) folder_name);
1311
1312                         g_object_unref (mail_op);
1313                         g_free (folder_name);
1314                 }
1315                 g_object_unref (folder);
1316         }
1317 }
1318
1319 static void
1320 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
1321 {
1322         TnyFolder *folder;
1323         ModestMailOperation *mail_op;
1324         GtkWidget *folder_view;
1325         
1326         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1327
1328         folder_view = modest_main_window_get_child_widget (main_window,
1329                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1330         if (!folder_view)
1331                 return;
1332
1333         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1334         
1335         mail_op = modest_mail_operation_new ();
1336         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1337                                          mail_op);
1338         modest_mail_operation_remove_folder (mail_op, folder, move_to_trash);
1339
1340         g_object_unref (G_OBJECT (mail_op));
1341         g_object_unref (G_OBJECT (folder));
1342 }
1343
1344 void 
1345 modest_ui_actions_on_delete_folder (GtkAction *action,
1346                                      ModestMainWindow *main_window)
1347 {
1348         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1349
1350         delete_folder (main_window, FALSE);
1351 }
1352
1353 void 
1354 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1355 {
1356         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1357         
1358         delete_folder (main_window, TRUE);
1359 }
1360
1361 void
1362 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
1363                                          const gchar* account_name,
1364                                          gchar **password, 
1365                                          gboolean *cancel, 
1366                                          gboolean *remember,
1367                                          ModestMainWindow *main_window)
1368 {
1369         gchar *txt;
1370         GtkWidget *dialog, *entry, *remember_pass_check;
1371
1372         dialog = gtk_dialog_new_with_buttons (_("Password requested"),
1373                                               NULL,
1374                                               GTK_DIALOG_MODAL,
1375                                               GTK_STOCK_CANCEL,
1376                                               GTK_RESPONSE_REJECT,
1377                                               GTK_STOCK_OK,
1378                                               GTK_RESPONSE_ACCEPT,
1379                                               NULL);
1380         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1381         
1382         txt = g_strdup_printf (_("Please enter your password for %s"), account_name);
1383         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1384                             FALSE, FALSE, 0);
1385         g_free (txt);
1386
1387         entry = gtk_entry_new_with_max_length (40);
1388         gtk_entry_set_visibility (GTK_ENTRY(entry), FALSE);
1389         gtk_entry_set_invisible_char (GTK_ENTRY(entry), 0x2022); /* bullet unichar */
1390         
1391         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry,
1392                             TRUE, FALSE, 0);    
1393
1394         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1395         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1396                             TRUE, FALSE, 0);
1397
1398         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1399         
1400         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1401                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry)));
1402                 *cancel   = FALSE;
1403         } else {
1404                 *password = NULL;
1405                 *cancel   = TRUE;
1406         }
1407
1408         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
1409                 *remember = TRUE;
1410         else
1411                 *remember = FALSE;
1412
1413         gtk_widget_destroy (dialog);
1414 }
1415
1416 void
1417 modest_ui_actions_on_cut (GtkAction *action,
1418                           ModestWindow *window)
1419 {
1420         GtkWidget *focused_widget;
1421
1422         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1423         if (GTK_IS_EDITABLE (focused_widget)) {
1424                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
1425         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1426                 GtkTextBuffer *buffer;
1427                 GtkClipboard *clipboard;
1428
1429                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1430                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1431                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
1432         }
1433 }
1434
1435 void
1436 modest_ui_actions_on_copy (GtkAction *action,
1437                            ModestWindow *window)
1438 {
1439         GtkClipboard *clipboard;
1440         GtkWidget *focused_widget;
1441
1442         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1443         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1444         if (GTK_IS_LABEL (focused_widget)) {
1445                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
1446         } else if (GTK_IS_EDITABLE (focused_widget)) {
1447                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
1448         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1449                 GtkTextBuffer *buffer;
1450
1451                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1452                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
1453         }
1454 }
1455
1456 void
1457 modest_ui_actions_on_paste (GtkAction *action,
1458                             ModestWindow *window)
1459 {
1460         GtkWidget *focused_widget;
1461
1462         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1463         if (GTK_IS_EDITABLE (focused_widget)) {
1464                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
1465         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1466                 GtkTextBuffer *buffer;
1467                 GtkClipboard *clipboard;
1468
1469                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1470                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1471                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
1472         }
1473 }
1474
1475 void
1476 modest_ui_actions_on_select_all (GtkAction *action,
1477                                  ModestWindow *window)
1478 {
1479         GtkWidget *focused_widget;
1480
1481         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1482         if (GTK_IS_LABEL (focused_widget)) {
1483                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
1484         } else if (GTK_IS_EDITABLE (focused_widget)) {
1485                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
1486         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1487                 GtkTextBuffer *buffer;
1488                 GtkTextIter start, end;
1489
1490                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1491                 gtk_text_buffer_get_start_iter (buffer, &start);
1492                 gtk_text_buffer_get_end_iter (buffer, &end);
1493                 gtk_text_buffer_select_range (buffer, &start, &end);
1494         }
1495 }
1496
1497 void
1498 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
1499                                   GtkRadioAction *selected,
1500                                   ModestWindow *window)
1501 {
1502         gint value;
1503
1504         value = gtk_radio_action_get_current_value (selected);
1505         if (MODEST_IS_WINDOW (window)) {
1506                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
1507         }
1508 }
1509
1510 void     
1511 modest_ui_actions_on_zoom_plus (GtkAction *action,
1512                                 ModestWindow *window)
1513 {
1514         g_return_if_fail (MODEST_IS_WINDOW (window));
1515
1516         modest_window_zoom_plus (MODEST_WINDOW (window));
1517 }
1518
1519 void     
1520 modest_ui_actions_on_zoom_minus (GtkAction *action,
1521                                  ModestWindow *window)
1522 {
1523         g_return_if_fail (MODEST_IS_WINDOW (window));
1524
1525         modest_window_zoom_minus (MODEST_WINDOW (window));
1526 }
1527
1528 void     
1529 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
1530                                            ModestWindow *window)
1531 {
1532         ModestWindowMgr *mgr;
1533         gboolean fullscreen, active;
1534         g_return_if_fail (MODEST_IS_WINDOW (window));
1535
1536         mgr = modest_runtime_get_window_mgr ();
1537
1538         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
1539         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1540
1541         if (active != fullscreen) {
1542                 modest_window_mgr_set_fullscreen_mode (mgr, active);
1543                 gtk_window_present (GTK_WINDOW (window));
1544         }
1545 }
1546
1547 void
1548 modest_ui_actions_on_change_fullscreen (GtkAction *action,
1549                                         ModestWindow *window)
1550 {
1551         ModestWindowMgr *mgr;
1552         gboolean fullscreen;
1553
1554         g_return_if_fail (MODEST_IS_WINDOW (window));
1555
1556         mgr = modest_runtime_get_window_mgr ();
1557         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1558         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
1559
1560         gtk_window_present (GTK_WINDOW (window));
1561 }
1562
1563 static void
1564 modest_ui_actions_message_details_cb (gpointer msg_data, 
1565                                       gpointer helper_data)
1566 {
1567         GtkWidget *dialog;
1568         TnyMsg *msg = (TnyMsg *) msg_data;
1569         TnyHeader *header;
1570         GetMsgAsyncHelper *helper = (GetMsgAsyncHelper *) helper_data;
1571         
1572         header = tny_msg_get_header (msg);
1573         
1574         dialog = modest_msg_view_details_dialog_new (GTK_WINDOW (helper->window), header);
1575         g_object_unref (header);
1576         gtk_widget_show_all (dialog);
1577
1578         gtk_dialog_run (GTK_DIALOG (dialog));
1579
1580         gtk_widget_destroy (dialog);
1581 }
1582
1583 void     
1584 modest_ui_actions_on_message_details (GtkAction *action, 
1585                                       ModestWindow *win)
1586 {
1587         TnyList * headers_list;
1588         GetMsgAsyncHelper *helper;
1589
1590         headers_list = get_selected_headers (win);
1591         if (!headers_list)
1592                 return;
1593
1594         helper = g_slice_new0 (GetMsgAsyncHelper);
1595         helper->window = win;
1596         helper->func = modest_ui_actions_message_details_cb;
1597         helper->iter = tny_list_create_iterator (headers_list);
1598         helper->user_data = NULL;
1599
1600         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1601                 TnyMsg *msg;
1602
1603                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
1604                 if (!msg)
1605                         return;
1606                 else {
1607                         modest_ui_actions_message_details_cb (msg, helper);
1608                 }
1609         } else {
1610                 /* here we should add an implementation to run the message details dialog
1611                    from the main window */
1612                 g_return_if_reached ();
1613         }
1614 }
1615
1616 void     
1617 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
1618                                      ModestMsgEditWindow *window)
1619 {
1620         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1621
1622         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
1623 }
1624
1625 void     
1626 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
1627                                       ModestMsgEditWindow *window)
1628 {
1629         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1630
1631         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
1632 }
1633
1634 void
1635 modest_ui_actions_toggle_folders_view (GtkAction *action, 
1636                                        ModestMainWindow *main_window)
1637 {
1638         ModestConf *conf;
1639         
1640         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1641
1642         conf = modest_runtime_get_conf ();
1643         
1644         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
1645                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
1646         else
1647                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
1648 }
1649
1650 void 
1651 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
1652                                      ModestWindow *window)
1653 {
1654         gboolean active, fullscreen = FALSE;
1655         ModestWindowMgr *mgr;
1656
1657         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
1658
1659         /* Check if we want to toggle the toolbar vuew in fullscreen
1660            or normal mode */
1661         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
1662                      "ViewShowToolbarFullScreen")) {
1663                 fullscreen = TRUE;
1664         }
1665
1666         /* Toggle toolbar */
1667         mgr = modest_runtime_get_window_mgr ();
1668         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
1669 }