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