3ea4a8b642fda29c19a0f3a786ff76f3e985d4c8
[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
637         g_object_unref (G_OBJECT(tny_account));
638         g_object_unref (G_OBJECT (mail_op));
639                 
640         return TRUE;
641 }
642
643
644
645 void
646 modest_ui_actions_on_send_receive (GtkAction *action,  ModestWindow *win)
647 {
648         gchar *account_name;
649         
650         account_name =
651                 g_strdup(modest_window_get_active_account(MODEST_WINDOW(win)));
652         if (!account_name)
653                 account_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
654         if (!account_name) {
655                 g_printerr ("modest: cannot get account\n");
656                 return;
657         }
658
659         if (!action_send(account_name))
660                 g_printerr ("modest: failed to send\n");
661         if (!action_receive(account_name))
662                 g_printerr ("modest: failed to receive\n");
663 }
664
665
666
667 void
668 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
669 {
670         ModestConf *conf;
671         GtkWidget *header_view;
672         
673         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
674
675         header_view = modest_main_window_get_child_widget (main_window,
676                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
677         if (!header_view)
678                 return;
679
680         conf = modest_runtime_get_conf ();
681         
682         /* what is saved/restored is depending on the style; thus; we save with
683          * old style, then update the style, and restore for this new style
684          */
685         modest_widget_memory_save (conf, G_OBJECT(header_view), "header-view");
686         
687         if (modest_header_view_get_style
688             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
689                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
690                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
691         else
692                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
693                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
694
695         modest_widget_memory_restore (conf, G_OBJECT(header_view),
696                                       "header-view");
697 }
698
699
700
701 /*
702  * Marks a message as read and passes it to the msg preview widget
703  */
704 static void
705 read_msg_func (gpointer data, gpointer user_data)
706 {
707         TnyMsg *msg;
708         TnyHeader *header;
709         GetMsgAsyncHelper *helper;
710         TnyHeaderFlags header_flags;
711         GtkWidget *msg_preview;
712         
713         msg = TNY_MSG (data);
714         helper = (GetMsgAsyncHelper *) user_data;
715
716         msg_preview = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (helper->window),
717                                                            MODEST_WIDGET_TYPE_MSG_PREVIEW);
718         if (!msg_preview)
719                 return;
720         
721         header = TNY_HEADER (tny_iterator_get_current (helper->iter));
722         header_flags = tny_header_get_flags (header);
723         tny_header_set_flags (header, header_flags | TNY_HEADER_FLAG_SEEN);
724         g_object_unref (G_OBJECT (header));
725
726         /* Set message on msg view */
727         modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), msg);
728 }
729
730 /*
731  * This function is a generic handler for the tny_folder_get_msg_async
732  * call. It expects as user_data a #GetMsgAsyncHelper. This helper
733  * contains a user provided function that is called inside this
734  * method. This will allow us to use this callback in many different
735  * places. This callback performs the common actions for the
736  * get_msg_async call, more specific actions will be done by the user
737  * function
738  */
739 static void
740 get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
741 {
742         GetMsgAsyncHelper *helper;
743
744         helper = (GetMsgAsyncHelper *) user_data;
745
746         if ((*err && ((*err)->code == TNY_FOLDER_ERROR_GET_MSG)) || !msg) {
747                 modest_ui_actions_on_item_not_found (NULL,
748                                                      MODEST_ITEM_TYPE_MESSAGE,
749                                                      helper->window);
750                 return;
751         }
752
753         /* Call user function */
754         helper->func (msg, user_data);
755
756         /* Process next element (if exists) */
757         tny_iterator_next (helper->iter);
758         if (tny_iterator_is_done (helper->iter)) {
759                 TnyList *headers;
760                 headers = tny_iterator_get_list (helper->iter);
761                 /* Free resources */
762                 g_object_unref (G_OBJECT (headers));
763                 g_object_unref (G_OBJECT (helper->iter));
764                 g_slice_free (GetMsgAsyncHelper, helper);
765         } else {
766                 TnyHeader *header;
767                 header = TNY_HEADER (tny_iterator_get_current (helper->iter)); 
768                 tny_folder_get_msg_async (folder, header,                         
769                                           get_msg_cb, helper);
770                 g_object_unref (G_OBJECT(header));
771         }
772 }
773
774 void 
775 modest_ui_actions_on_header_selected (ModestHeaderView *folder_view, 
776                                       TnyHeader *header,
777                                       ModestMainWindow *main_window)
778 {
779         GtkWidget *msg_preview;
780         TnyFolder *folder;
781         GetMsgAsyncHelper *helper;
782         TnyList *list;
783
784         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
785         
786         msg_preview = modest_main_window_get_child_widget(main_window,
787                                                           MODEST_WIDGET_TYPE_MSG_PREVIEW);
788         if (!msg_preview)
789                 return;
790         
791         /* when there's no header, clear the msgview */
792         if (!header) {
793                 modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), NULL);
794                 return;
795         }
796
797         folder = tny_header_get_folder (TNY_HEADER(header));
798
799         /* Create list */
800         list = tny_simple_list_new ();
801         tny_list_prepend (list, G_OBJECT (header));
802
803         /* Fill helper data */
804         helper = g_slice_new0 (GetMsgAsyncHelper);
805         helper->window = MODEST_WINDOW (main_window);
806         helper->iter = tny_list_create_iterator (list);
807         helper->func = read_msg_func;
808
809         tny_folder_get_msg_async (TNY_FOLDER(folder),
810                                   header, get_msg_cb,
811                                   helper);
812
813         /* Frees */
814         g_object_unref (G_OBJECT (folder));
815 }
816
817
818
819 void 
820 modest_ui_actions_on_header_activated (ModestHeaderView *folder_view, TnyHeader *header,
821                                        ModestMainWindow *main_window)
822 {
823         ModestWindow *win = NULL;
824         TnyFolder *folder = NULL;
825         TnyMsg    *msg    = NULL;
826         ModestWindowMgr *mgr;
827         
828         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
829         
830         if (!header)
831                 return;
832
833         folder = tny_header_get_folder (header);
834         if (!folder) {
835                 g_printerr ("modest: cannot get folder for header\n");
836                 return;
837         }
838
839         /* FIXME: make async?; check error  */
840         msg = tny_folder_get_msg (folder, header, NULL);
841         if (!msg) {
842                 g_printerr ("modest: cannot get msg for header\n");
843                 goto cleanup;
844         }
845
846         /* Look if we already have a message view for that header */    
847         mgr = modest_runtime_get_window_mgr ();
848         win = modest_window_mgr_find_window_by_msguid (mgr, tny_header_get_uid (header));
849
850         /* If not, create a new window */
851         if (!win) {
852                 gchar *account;
853
854                 account =  g_strdup(modest_window_get_active_account(MODEST_WINDOW(main_window)));
855                 if (!account)
856                         account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
857
858                 win = modest_msg_view_window_new (msg, account);
859                 modest_window_mgr_register_window (mgr, win);
860
861                 gtk_window_set_transient_for (GTK_WINDOW (win),
862                                               GTK_WINDOW (main_window));
863         }
864
865         gtk_widget_show_all (GTK_WIDGET(win));
866
867         g_object_unref (G_OBJECT (msg));
868         
869 cleanup:
870         g_object_unref (G_OBJECT (folder));
871 }
872
873 void 
874 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
875                                                TnyFolder *folder, 
876                                                gboolean selected,
877                                                ModestMainWindow *main_window)
878 {
879         gchar *txt;
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), "Modest");
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 num, unread;
899                         gchar *title;
900
901                         num    = tny_folder_get_all_count    (folder);
902                         unread = tny_folder_get_unread_count (folder);
903                         
904                         title = g_strdup_printf ("Modest: %s",
905                                                  tny_folder_get_name (folder));
906                         
907                         gtk_window_set_title (GTK_WINDOW(main_window), title);
908                         g_free (title);
909                         
910                         txt = g_strdup_printf (_("%d %s, %d unread"),
911                                                num, num==1 ? _("item") : _("items"), unread);           
912                         //gtk_label_set_label (GTK_LABEL(folder_info_label), txt);
913                         g_free (txt);
914                 }
915                 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), folder);
916                 modest_widget_memory_restore (conf, G_OBJECT(header_view),
917                                               "header-view");
918         }
919 }
920
921 void 
922 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
923                                      ModestWindow *win)
924 {
925         GtkWidget *dialog;
926         gchar *txt, *item;
927         gboolean online;
928
929         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
930         
931         if (g_main_depth > 0)   
932                 gdk_threads_enter ();
933         online = tny_device_is_online (modest_runtime_get_device());
934
935         if (online) {
936                 /* already online -- the item is simply not there... */
937                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
938                                                  GTK_DIALOG_MODAL,
939                                                  GTK_MESSAGE_WARNING,
940                                                  GTK_BUTTONS_OK,
941                                                  _("The %s you selected cannot be found"),
942                                                  item);
943                 gtk_dialog_run (GTK_DIALOG(dialog));
944         } else {
945                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
946                                                       GTK_WINDOW (win),
947                                                       GTK_DIALOG_MODAL,
948                                                       GTK_STOCK_CANCEL,
949                                                       GTK_RESPONSE_REJECT,
950                                                       GTK_STOCK_OK,
951                                                       GTK_RESPONSE_ACCEPT,
952                                                       NULL);
953                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
954                                          "Do you want to get online?"), item);
955                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
956                                     gtk_label_new (txt), FALSE, FALSE, 0);
957                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
958                 g_free (txt);
959
960                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
961                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
962 //                      tny_device_force_online (modest_runtime_get_device());
963                 }
964         }
965         gtk_widget_destroy (dialog);
966         if (g_main_depth > 0)   
967                 gdk_threads_leave ();
968 }
969
970 void
971 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
972                                      ModestWindow *win)
973 {
974         g_message ("%s %s", __FUNCTION__, link);
975 }       
976
977
978 void
979 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
980                                         ModestWindow *win)
981 {
982         modest_platform_activate_uri (link);
983 }
984
985 void
986 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
987                                           ModestWindow *win)
988 {
989         modest_platform_show_uri_popup (link);
990 }
991
992 void
993 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
994                                              ModestWindow *win)
995 {
996         g_message (__FUNCTION__);
997         
998 }
999
1000 void
1001 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1002                                           const gchar *address,
1003                                           ModestWindow *win)
1004 {
1005         g_message ("%s %s", __FUNCTION__, address);
1006 }
1007
1008 void
1009 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1010 {
1011         TnyTransportAccount *transport_account;
1012         ModestMailOperation *mail_operation;
1013         MsgData *data;
1014         gchar *account_name, *from;
1015         ModestAccountMgr *account_mgr;
1016
1017         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1018         
1019         data = modest_msg_edit_window_get_msg_data (edit_window);
1020
1021         /* FIXME: Code added just for testing. The final version will
1022            use the send queue provided by tinymail and some
1023            classifier */
1024         account_mgr = modest_runtime_get_account_mgr();
1025         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1026         if (!account_name) 
1027                 account_name = modest_account_mgr_get_default_account (account_mgr);
1028         if (!account_name) {
1029                 g_printerr ("modest: no account found\n");
1030                 modest_msg_edit_window_free_msg_data (edit_window, data);
1031                 return;
1032         }
1033         transport_account =
1034                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
1035                                       (modest_runtime_get_account_store(),
1036                                        account_name,
1037                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1038         if (!transport_account) {
1039                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1040                 g_free (account_name);
1041                 modest_msg_edit_window_free_msg_data (edit_window, data);
1042                 return;
1043         }
1044         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1045
1046         /* Create the mail operation */         
1047         mail_operation = modest_mail_operation_new ();
1048         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1049
1050         modest_mail_operation_send_new_mail (mail_operation,
1051                                              transport_account,
1052                                              from,
1053                                              data->to, 
1054                                              data->cc, 
1055                                              data->bcc,
1056                                              data->subject, 
1057                                              data->plain_body, 
1058                                              data->html_body,
1059                                              data->attachments);
1060         /* Frees */
1061         g_free (from);
1062         g_free (account_name);
1063         g_object_unref (G_OBJECT (transport_account));
1064         g_object_unref (G_OBJECT (mail_operation));
1065
1066         modest_msg_edit_window_free_msg_data (edit_window, data);
1067
1068         /* Save settings and close the window */
1069         gtk_widget_destroy (GTK_WIDGET (edit_window));
1070 }
1071
1072 void 
1073 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1074                                   ModestMsgEditWindow *window)
1075 {
1076         ModestMsgEditFormatState *format_state = NULL;
1077
1078         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1079         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1080
1081         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1082                 return;
1083
1084         format_state = modest_msg_edit_window_get_format_state (window);
1085         g_return_if_fail (format_state != NULL);
1086
1087         format_state->bold = gtk_toggle_action_get_active (action);
1088         modest_msg_edit_window_set_format_state (window, format_state);
1089         g_free (format_state);
1090         
1091 }
1092
1093 void 
1094 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1095                                      ModestMsgEditWindow *window)
1096 {
1097         ModestMsgEditFormatState *format_state = NULL;
1098
1099         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1100         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1101
1102         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1103                 return;
1104
1105         format_state = modest_msg_edit_window_get_format_state (window);
1106         g_return_if_fail (format_state != NULL);
1107
1108         format_state->italics = gtk_toggle_action_get_active (action);
1109         modest_msg_edit_window_set_format_state (window, format_state);
1110         g_free (format_state);
1111         
1112 }
1113
1114 void 
1115 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
1116                                      ModestMsgEditWindow *window)
1117 {
1118         ModestMsgEditFormatState *format_state = NULL;
1119
1120         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1121         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1122
1123         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1124                 return;
1125
1126         format_state = modest_msg_edit_window_get_format_state (window);
1127         g_return_if_fail (format_state != NULL);
1128
1129         format_state->bullet = gtk_toggle_action_get_active (action);
1130         modest_msg_edit_window_set_format_state (window, format_state);
1131         g_free (format_state);
1132         
1133 }
1134
1135 void 
1136 modest_ui_actions_on_change_justify (GtkRadioAction *action,
1137                                      GtkRadioAction *selected,
1138                                      ModestMsgEditWindow *window)
1139 {
1140         ModestMsgEditFormatState *format_state = NULL;
1141         GtkJustification value;
1142
1143         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1144
1145         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1146                 return;
1147
1148         value = gtk_radio_action_get_current_value (selected);
1149
1150         format_state = modest_msg_edit_window_get_format_state (window);
1151         g_return_if_fail (format_state != NULL);
1152
1153         format_state->justification = value;
1154         modest_msg_edit_window_set_format_state (window, format_state);
1155         g_free (format_state);
1156 }
1157
1158 void 
1159 modest_ui_actions_on_select_editor_color (GtkAction *action,
1160                                           ModestMsgEditWindow *window)
1161 {
1162         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1163         g_return_if_fail (GTK_IS_ACTION (action));
1164
1165         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1166                 return;
1167
1168         modest_msg_edit_window_select_color (window);
1169 }
1170
1171 void 
1172 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
1173                                                      ModestMsgEditWindow *window)
1174 {
1175         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1176         g_return_if_fail (GTK_IS_ACTION (action));
1177
1178         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1179                 return;
1180
1181         modest_msg_edit_window_select_background_color (window);
1182 }
1183
1184 void 
1185 modest_ui_actions_on_insert_image (GtkAction *action,
1186                                    ModestMsgEditWindow *window)
1187 {
1188         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1189         g_return_if_fail (GTK_IS_ACTION (action));
1190
1191         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1192                 return;
1193
1194         modest_msg_edit_window_insert_image (window);
1195 }
1196
1197 /*
1198  * Shows a dialog with an entry that asks for some text. The returned
1199  * value must be freed by the caller. The dialog window title will be
1200  * set to @title.
1201  */
1202 static gchar *
1203 ask_for_folder_name (GtkWindow *parent_window,
1204                      const gchar *title)
1205 {
1206         GtkWidget *dialog, *entry;
1207         gchar *folder_name = NULL;
1208
1209         /* Ask for folder name */
1210         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1211                                               parent_window,
1212                                               GTK_DIALOG_MODAL,
1213                                               GTK_STOCK_CANCEL,
1214                                               GTK_RESPONSE_REJECT,
1215                                               GTK_STOCK_OK,
1216                                               GTK_RESPONSE_ACCEPT,
1217                                               NULL);
1218         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1219                             gtk_label_new(title),
1220                             FALSE, FALSE, 0);
1221                 
1222         entry = gtk_entry_new_with_max_length (40);
1223         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1224                             entry,
1225                             TRUE, FALSE, 0);    
1226         
1227         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1228         
1229         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
1230                 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1231
1232         gtk_widget_destroy (dialog);
1233
1234         return folder_name;
1235 }
1236
1237 void 
1238 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1239 {
1240         TnyFolder *parent_folder;
1241         GtkWidget *folder_view;
1242         
1243         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1244
1245         folder_view = modest_main_window_get_child_widget (main_window,
1246                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1247         if (!folder_view)
1248                 return;
1249
1250         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1251         
1252         if (parent_folder) {
1253                 gchar *folder_name;
1254
1255                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1256                                                    _("Please enter a name for the new folder"));
1257
1258                 if (folder_name != NULL && strlen (folder_name) > 0) {
1259                         TnyFolder *new_folder;
1260                         ModestMailOperation *mail_op;
1261
1262                         mail_op = modest_mail_operation_new ();
1263                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
1264                                                          mail_op);
1265
1266                         new_folder = modest_mail_operation_create_folder (mail_op,
1267                                                                           TNY_FOLDER_STORE (parent_folder),
1268                                                                           (const gchar *) folder_name);
1269                         if (new_folder) 
1270                                 g_object_unref (new_folder);
1271                         g_object_unref (mail_op);
1272                         g_free (folder_name);
1273                 }
1274                 g_object_unref (parent_folder);
1275         }
1276 }
1277
1278 void 
1279 modest_ui_actions_on_rename_folder (GtkAction *action,
1280                                      ModestMainWindow *main_window)
1281 {
1282         TnyFolder *folder;
1283         GtkWidget *folder_view;
1284         
1285         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1286
1287         folder_view = modest_main_window_get_child_widget (main_window,
1288                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1289         if (!folder_view)
1290                 return;
1291         
1292         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1293         
1294         if (folder) {
1295                 gchar *folder_name;
1296                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1297                                                    _("Please enter a new name for the folder"));
1298
1299                 if (folder_name != NULL && strlen (folder_name) > 0) {
1300                         ModestMailOperation *mail_op;
1301
1302                         mail_op = modest_mail_operation_new ();
1303                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1304                                                          mail_op);
1305
1306                         modest_mail_operation_rename_folder (mail_op,
1307                                                              folder,
1308                                                              (const gchar *) folder_name);
1309
1310                         g_object_unref (mail_op);
1311                         g_free (folder_name);
1312                 }
1313                 g_object_unref (folder);
1314         }
1315 }
1316
1317 static void
1318 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
1319 {
1320         TnyFolder *folder;
1321         ModestMailOperation *mail_op;
1322         GtkWidget *folder_view;
1323         
1324         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1325
1326         folder_view = modest_main_window_get_child_widget (main_window,
1327                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1328         if (!folder_view)
1329                 return;
1330
1331         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1332         
1333         mail_op = modest_mail_operation_new ();
1334         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1335                                          mail_op);
1336         modest_mail_operation_remove_folder (mail_op, folder, move_to_trash);
1337
1338         g_object_unref (G_OBJECT (mail_op));
1339         g_object_unref (G_OBJECT (folder));
1340 }
1341
1342 void 
1343 modest_ui_actions_on_delete_folder (GtkAction *action,
1344                                      ModestMainWindow *main_window)
1345 {
1346         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1347
1348         delete_folder (main_window, FALSE);
1349 }
1350
1351 void 
1352 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1353 {
1354         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1355         
1356         delete_folder (main_window, TRUE);
1357 }
1358
1359 void
1360 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
1361                                          const gchar* account_name,
1362                                          gchar **password, 
1363                                          gboolean *cancel, 
1364                                          gboolean *remember,
1365                                          ModestMainWindow *main_window)
1366 {
1367         gchar *txt;
1368         GtkWidget *dialog, *entry, *remember_pass_check;
1369
1370         dialog = gtk_dialog_new_with_buttons (_("Password requested"),
1371                                               NULL,
1372                                               GTK_DIALOG_MODAL,
1373                                               GTK_STOCK_CANCEL,
1374                                               GTK_RESPONSE_REJECT,
1375                                               GTK_STOCK_OK,
1376                                               GTK_RESPONSE_ACCEPT,
1377                                               NULL);
1378         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1379         
1380         txt = g_strdup_printf (_("Please enter your password for %s"), account_name);
1381         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1382                             FALSE, FALSE, 0);
1383         g_free (txt);
1384
1385         entry = gtk_entry_new_with_max_length (40);
1386         gtk_entry_set_visibility (GTK_ENTRY(entry), FALSE);
1387         gtk_entry_set_invisible_char (GTK_ENTRY(entry), 0x2022); /* bullet unichar */
1388         
1389         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry,
1390                             TRUE, FALSE, 0);    
1391
1392         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1393         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1394                             TRUE, FALSE, 0);
1395
1396         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1397         
1398         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1399                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry)));
1400                 *cancel   = FALSE;
1401         } else {
1402                 *password = NULL;
1403                 *cancel   = TRUE;
1404         }
1405
1406         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
1407                 *remember = TRUE;
1408         else
1409                 *remember = FALSE;
1410
1411         gtk_widget_destroy (dialog);
1412 }
1413
1414 void
1415 modest_ui_actions_on_cut (GtkAction *action,
1416                           ModestWindow *window)
1417 {
1418         GtkWidget *focused_widget;
1419
1420         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1421         if (GTK_IS_EDITABLE (focused_widget)) {
1422                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
1423         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1424                 GtkTextBuffer *buffer;
1425                 GtkClipboard *clipboard;
1426
1427                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1428                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1429                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
1430         }
1431 }
1432
1433 void
1434 modest_ui_actions_on_copy (GtkAction *action,
1435                            ModestWindow *window)
1436 {
1437         GtkClipboard *clipboard;
1438         GtkWidget *focused_widget;
1439
1440         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1441         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1442         if (GTK_IS_LABEL (focused_widget)) {
1443                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
1444         } else if (GTK_IS_EDITABLE (focused_widget)) {
1445                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
1446         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1447                 GtkTextBuffer *buffer;
1448
1449                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1450                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
1451         }
1452 }
1453
1454 void
1455 modest_ui_actions_on_paste (GtkAction *action,
1456                             ModestWindow *window)
1457 {
1458         GtkWidget *focused_widget;
1459
1460         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1461         if (GTK_IS_EDITABLE (focused_widget)) {
1462                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
1463         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1464                 GtkTextBuffer *buffer;
1465                 GtkClipboard *clipboard;
1466
1467                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1468                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1469                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
1470         }
1471 }
1472
1473 void
1474 modest_ui_actions_on_select_all (GtkAction *action,
1475                                  ModestWindow *window)
1476 {
1477         GtkWidget *focused_widget;
1478
1479         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1480         if (GTK_IS_LABEL (focused_widget)) {
1481                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
1482         } else if (GTK_IS_EDITABLE (focused_widget)) {
1483                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
1484         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1485                 GtkTextBuffer *buffer;
1486                 GtkTextIter start, end;
1487
1488                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1489                 gtk_text_buffer_get_start_iter (buffer, &start);
1490                 gtk_text_buffer_get_end_iter (buffer, &end);
1491                 gtk_text_buffer_select_range (buffer, &start, &end);
1492         }
1493 }
1494
1495 void
1496 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
1497                                   GtkRadioAction *selected,
1498                                   ModestWindow *window)
1499 {
1500         gint value;
1501
1502         value = gtk_radio_action_get_current_value (selected);
1503         if (MODEST_IS_WINDOW (window)) {
1504                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
1505         }
1506 }
1507
1508 void     
1509 modest_ui_actions_on_zoom_plus (GtkAction *action,
1510                                 ModestWindow *window)
1511 {
1512         g_return_if_fail (MODEST_IS_WINDOW (window));
1513
1514         modest_window_zoom_plus (MODEST_WINDOW (window));
1515 }
1516
1517 void     
1518 modest_ui_actions_on_zoom_minus (GtkAction *action,
1519                                  ModestWindow *window)
1520 {
1521         g_return_if_fail (MODEST_IS_WINDOW (window));
1522
1523         modest_window_zoom_minus (MODEST_WINDOW (window));
1524 }
1525
1526 void     
1527 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
1528                                            ModestWindow *window)
1529 {
1530         ModestWindowMgr *mgr;
1531         gboolean fullscreen, active;
1532         g_return_if_fail (MODEST_IS_WINDOW (window));
1533
1534         mgr = modest_runtime_get_window_mgr ();
1535
1536         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
1537         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1538
1539         if (active != fullscreen) {
1540                 modest_window_mgr_set_fullscreen_mode (mgr, active);
1541                 gtk_window_present (GTK_WINDOW (window));
1542         }
1543 }
1544
1545 void
1546 modest_ui_actions_on_change_fullscreen (GtkAction *action,
1547                                         ModestWindow *window)
1548 {
1549         ModestWindowMgr *mgr;
1550         gboolean fullscreen;
1551
1552         g_return_if_fail (MODEST_IS_WINDOW (window));
1553
1554         mgr = modest_runtime_get_window_mgr ();
1555         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1556         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
1557
1558         gtk_window_present (GTK_WINDOW (window));
1559 }
1560
1561 static void
1562 modest_ui_actions_message_details_cb (gpointer msg_data, 
1563                                       gpointer helper_data)
1564 {
1565         GtkWidget *dialog;
1566         TnyMsg *msg = (TnyMsg *) msg_data;
1567         TnyHeader *header;
1568         GetMsgAsyncHelper *helper = (GetMsgAsyncHelper *) helper_data;
1569         
1570         header = tny_msg_get_header (msg);
1571         
1572         dialog = modest_msg_view_details_dialog_new (GTK_WINDOW (helper->window), header);
1573         g_object_unref (header);
1574         gtk_widget_show_all (dialog);
1575
1576         gtk_dialog_run (GTK_DIALOG (dialog));
1577
1578         gtk_widget_destroy (dialog);
1579 }
1580
1581 void     
1582 modest_ui_actions_on_message_details (GtkAction *action, 
1583                                       ModestWindow *win)
1584 {
1585         TnyList * headers_list;
1586         GetMsgAsyncHelper *helper;
1587
1588         headers_list = get_selected_headers (win);
1589         if (!headers_list)
1590                 return;
1591
1592         helper = g_slice_new0 (GetMsgAsyncHelper);
1593         helper->window = win;
1594         helper->func = modest_ui_actions_message_details_cb;
1595         helper->iter = tny_list_create_iterator (headers_list);
1596         helper->user_data = NULL;
1597
1598         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1599                 TnyMsg *msg;
1600
1601                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
1602                 if (!msg)
1603                         return;
1604                 else {
1605                         modest_ui_actions_message_details_cb (msg, helper);
1606                 }
1607         } else {
1608                 /* here we should add an implementation to run the message details dialog
1609                    from the main window */
1610                 g_return_if_reached ();
1611         }
1612 }
1613
1614 void     
1615 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
1616                                      ModestMsgEditWindow *window)
1617 {
1618         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1619
1620         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
1621 }
1622
1623 void     
1624 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
1625                                       ModestMsgEditWindow *window)
1626 {
1627         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1628
1629         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
1630 }
1631
1632 void
1633 modest_ui_actions_toggle_folders_view (GtkAction *action, 
1634                                        ModestMainWindow *main_window)
1635 {
1636         ModestConf *conf;
1637         
1638         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1639
1640         conf = modest_runtime_get_conf ();
1641         
1642         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
1643                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
1644         else
1645                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
1646 }
1647
1648 void 
1649 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
1650                                      ModestWindow *window)
1651 {
1652         gboolean active, fullscreen = FALSE;
1653         ModestWindowMgr *mgr;
1654
1655         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
1656
1657         /* Check if we want to toggle the toolbar vuew in fullscreen
1658            or normal mode */
1659         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
1660                      "ViewShowToolbarFullScreen")) {
1661                 fullscreen = TRUE;
1662         }
1663
1664         /* Toggle toolbar */
1665         mgr = modest_runtime_get_window_mgr ();
1666         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
1667 }