* Major API change in tinymail
[modest] / src / modest-ui-actions.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif /*HAVE_CONFIG_H*/
33
34 #include <glib/gi18n.h>
35 #include <string.h>
36 #include <modest-runtime.h>
37 #include <modest-tny-folder.h>
38 #include <modest-tny-msg.h>
39 #include <modest-tny-account.h>
40 #include <modest-address-book.h>
41
42 #include "modest-ui-actions.h"
43
44 #include "modest-tny-platform-factory.h"
45 #include "modest-platform.h"
46
47 #include <widgets/modest-main-window.h>
48 #include <widgets/modest-msg-view-window.h>
49 #include <widgets/modest-account-view-window.h>
50 #include <widgets/modest-msg-view-details-dialog.h>
51
52 #include "modest-account-mgr-helpers.h"
53 #include "modest-mail-operation.h"
54
55 #ifdef MODEST_HAVE_EASYSETUP
56 #include "easysetup/modest-easysetup-wizard.h"
57 #endif /*MODEST_HAVE_EASYSETUP*/
58
59 #include <modest-widget-memory.h>
60 #include <tny-error.h>
61 #include <tny-simple-list.h>
62 #include <tny-msg-view.h>
63 #include <tny-device.h>
64
65 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         if (!from_str) {
310                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
311                 goto cleanup;
312         }
313
314         msg = modest_tny_msg_new ("", from_str, "", "", "", "", NULL);
315         if (!msg) {
316                 g_printerr ("modest: failed to create new msg\n");
317                 goto cleanup;
318         }
319         
320         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
321         if (!folder) {
322                 g_printerr ("modest: failed to find Drafts folder\n");
323                 goto cleanup;
324         }
325         
326         tny_folder_add_msg (folder, msg, &err);
327         if (err) {
328                 g_printerr ("modest: error adding msg to Drafts folder: %s",
329                             err->message);
330                 g_error_free (err);
331                 goto cleanup;
332         }
333
334         /* Create and register edit window */
335         msg_win = modest_msg_edit_window_new (msg, account_name);
336         mgr = modest_runtime_get_window_mgr ();
337         modest_window_mgr_register_window (mgr, msg_win);
338
339         if (win)
340                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
341                                               GTK_WINDOW (win));        
342         gtk_widget_show_all (GTK_WIDGET (msg_win));
343
344 cleanup:
345         g_free (account_name);
346         g_free (from_str);
347         if (account)
348                 g_object_unref (G_OBJECT(account));
349         if (msg)
350                 g_object_unref (G_OBJECT(msg));
351         if (folder)
352                 g_object_unref (G_OBJECT(folder));
353 }
354
355
356 void
357 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
358 {
359         modest_runtime_not_implemented (GTK_WINDOW(win)); /* FIXME */
360 }
361
362
363
364 static void
365 reply_forward_func (gpointer data, gpointer user_data)
366 {
367         TnyMsg *msg, *new_msg;
368         GetMsgAsyncHelper *helper;
369         ReplyForwardHelper *rf_helper;
370         ModestWindow *msg_win;
371         ModestEditType edit_type;
372         gchar *from;
373         GError *err = NULL;
374         TnyFolder *folder = NULL;
375         TnyAccount *account = NULL;
376         ModestWindowMgr *mgr;
377         
378         msg = TNY_MSG (data);
379         helper = (GetMsgAsyncHelper *) user_data;
380         rf_helper = (ReplyForwardHelper *) helper->user_data;
381
382         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
383                                                    rf_helper->account_name);
384         /* Create reply mail */
385         switch (rf_helper->action) {
386         case ACTION_REPLY:
387                 new_msg = 
388                         modest_tny_msg_create_reply_msg (msg,  from, 
389                                                          rf_helper->reply_forward_type,
390                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
391                 break;
392         case ACTION_REPLY_TO_ALL:
393                 new_msg = 
394                         modest_tny_msg_create_reply_msg (msg, from, rf_helper->reply_forward_type,
395                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
396                 edit_type = MODEST_EDIT_TYPE_REPLY;
397                 break;
398         case ACTION_FORWARD:
399                 new_msg = 
400                         modest_tny_msg_create_forward_msg (msg, from, rf_helper->reply_forward_type);
401                 edit_type = MODEST_EDIT_TYPE_FORWARD;
402                 break;
403         default:
404                 g_return_if_reached ();
405                 return;
406         }
407
408         if (!new_msg) {
409                 g_printerr ("modest: failed to create message\n");
410                 goto cleanup;
411         }
412
413         account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
414                                                                        rf_helper->account_name,
415                                                                        TNY_ACCOUNT_TYPE_STORE);
416         if (!account) {
417                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
418                 goto cleanup;
419         }
420
421         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
422         if (!folder) {
423                 g_printerr ("modest: failed to find Drafts folder\n");
424                 goto cleanup;
425         }
426         
427         tny_folder_add_msg (folder, msg, &err);
428         if (err) {
429                 g_printerr ("modest: error adding msg to Drafts folder: %s",
430                             err->message);
431                 g_error_free (err);
432                 goto cleanup;
433         }       
434
435         /* Create and register the windows */                   
436         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
437         mgr = modest_runtime_get_window_mgr ();
438         modest_window_mgr_register_window (mgr, msg_win);
439
440         /* Show edit window */
441         gtk_widget_show_all (GTK_WIDGET (msg_win));
442
443 cleanup:
444         if (new_msg)
445                 g_object_unref (G_OBJECT (new_msg));
446         if (folder)
447                 g_object_unref (G_OBJECT (folder));
448         if (account)
449                 g_object_unref (G_OBJECT (account));
450         
451         g_free (rf_helper->account_name);
452         g_slice_free (ReplyForwardHelper, rf_helper);
453 }
454 /*
455  * Common code for the reply and forward actions
456  */
457 static void
458 reply_forward (ReplyForwardAction action, ModestWindow *win)
459 {
460         TnyList *header_list;
461         guint reply_forward_type;
462         TnyHeader *header;
463         TnyFolder *folder;
464         GetMsgAsyncHelper *helper;
465         ReplyForwardHelper *rf_helper;
466         
467         g_return_if_fail (MODEST_IS_WINDOW(win));
468
469         header_list = get_selected_headers (win);
470         if (!header_list)
471                 return;
472         
473         reply_forward_type = modest_conf_get_int (modest_runtime_get_conf (),
474                                                   (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
475                                                   NULL);
476         /* We assume that we can only select messages of the
477            same folder and that we reply all of them from the
478            same account. In fact the interface currently only
479            allows single selection */
480         
481         /* Fill helpers */
482         rf_helper = g_slice_new0 (ReplyForwardHelper);
483         rf_helper->reply_forward_type = reply_forward_type;
484         rf_helper->action = action;
485
486         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
487         if (!rf_helper->account_name)
488                 rf_helper->account_name =
489                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
490
491         helper = g_slice_new0 (GetMsgAsyncHelper);
492         helper->window = win;
493         helper->func = reply_forward_func;
494         helper->iter = tny_list_create_iterator (header_list);
495         helper->user_data = rf_helper;
496
497         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
498                 TnyMsg *msg;
499                 msg = modest_msg_view_window_get_message(MODEST_MSG_VIEW_WINDOW(win));
500                 if (!msg) {
501                         g_printerr ("modest: no message found\n");
502                         return;
503                 } else
504                         reply_forward_func (msg, helper);
505         } else {
506                 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
507                 folder = tny_header_get_folder (header);
508                 if (folder) {
509                         /* The callback will call it per each header */
510                         tny_folder_get_msg_async (folder, header, get_msg_cb, NULL, helper);
511                         g_object_unref (G_OBJECT (folder));
512                 } else 
513                         g_printerr ("modest: no folder for header\n");
514                 
515                 /* Clean */
516                 g_object_unref (G_OBJECT (header));
517         }
518 }
519
520
521 void
522 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
523 {
524         g_return_if_fail (MODEST_IS_WINDOW(win));
525
526         reply_forward (ACTION_REPLY, win);
527 }
528
529 void
530 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
531 {
532         g_return_if_fail (MODEST_IS_WINDOW(win));
533
534         reply_forward (ACTION_FORWARD, win);
535 }
536
537 void
538 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
539 {
540         g_return_if_fail (MODEST_IS_WINDOW(win));
541
542         reply_forward (ACTION_REPLY_TO_ALL, win);
543 }
544
545 void 
546 modest_ui_actions_on_next (GtkAction *action, 
547                            ModestWindow *window)
548 {
549         if (MODEST_IS_MAIN_WINDOW (window)) {
550                 GtkWidget *header_view;
551
552                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
553                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
554                 if (!header_view)
555                         return;
556         
557                 modest_header_view_select_next (MODEST_HEADER_VIEW(header_view)); 
558         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
559                 modest_msg_view_window_select_next_message (MODEST_MSG_VIEW_WINDOW (window));
560         } else {
561                 g_return_if_reached ();
562         }
563 }
564
565 void 
566 modest_ui_actions_on_prev (GtkAction *action, 
567                            ModestWindow *window)
568 {
569         g_return_if_fail (MODEST_IS_WINDOW(window));
570
571         if (MODEST_IS_MAIN_WINDOW (window)) {
572                 GtkWidget *header_view;
573                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
574                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
575                 if (!header_view)
576                         return;
577                 
578                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
579         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
580                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
581         } else {
582                 g_return_if_reached ();
583         }
584 }
585
586
587 static gboolean
588 action_send (const gchar* account_name)
589 {
590         TnyAccount *tny_account;
591         ModestTnySendQueue *send_queue;
592
593         g_return_val_if_fail (account_name, FALSE);
594
595         tny_account = 
596                 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
597                                                                      account_name,
598                                                                      TNY_ACCOUNT_TYPE_TRANSPORT);
599         if (!tny_account) {
600                 g_printerr ("modest: cannot get tny transport account for %s\n", account_name);
601                 return FALSE;
602         }
603         send_queue = modest_tny_send_queue_new (TNY_CAMEL_TRANSPORT_ACCOUNT(tny_account));
604         if (!send_queue) {
605                 g_object_unref (G_OBJECT(tny_account));
606                 g_printerr ("modest: cannot get send queue for %s\n", account_name);
607                 return FALSE;
608         }
609         
610         //modest_tny_send_queue_flush (send_queue);
611
612         g_object_unref (G_OBJECT(send_queue));
613         g_object_unref (G_OBJECT(tny_account));
614
615         return TRUE;
616 }
617
618
619 static gboolean
620 action_receive (const gchar* account_name)
621 {
622         TnyAccount *tny_account;
623         ModestMailOperation *mail_op;
624
625         g_return_val_if_fail (account_name, FALSE);
626
627         tny_account = 
628                 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
629                                                                      account_name,
630                                                                      TNY_ACCOUNT_TYPE_STORE);
631         if (!tny_account) {
632                 g_printerr ("modest: cannot get tny store account for %s\n", account_name);
633                 return FALSE;
634         }
635
636         /* Create the mail operation */
637         mail_op = modest_mail_operation_new ();
638         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
639         modest_mail_operation_update_account (mail_op, TNY_STORE_ACCOUNT(tny_account));
640
641         g_object_unref (G_OBJECT(tny_account));
642         g_object_unref (G_OBJECT (mail_op));
643                 
644         return TRUE;
645 }
646
647
648
649 void
650 modest_ui_actions_on_send_receive (GtkAction *action,  ModestWindow *win)
651 {
652         gchar *account_name;
653
654         
655         g_message ("online? %s", 
656                 tny_device_is_online(modest_runtime_get_device()) ? "yes":"no");
657                                                                 
658         account_name =
659                 g_strdup(modest_window_get_active_account(MODEST_WINDOW(win)));
660         if (!account_name)
661                 account_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
662         if (!account_name) {
663                 g_printerr ("modest: cannot get account\n");
664                 return;
665         }
666
667         if (!action_send(account_name))
668                 g_printerr ("modest: failed to send\n");
669         if (!action_receive(account_name))
670                 g_printerr ("modest: failed to receive\n");
671 }
672
673
674
675 void
676 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
677 {
678         ModestConf *conf;
679         GtkWidget *header_view;
680         
681         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
682
683         header_view = modest_main_window_get_child_widget (main_window,
684                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
685         if (!header_view)
686                 return;
687
688         conf = modest_runtime_get_conf ();
689         
690         /* what is saved/restored is depending on the style; thus; we save with
691          * old style, then update the style, and restore for this new style
692          */
693         modest_widget_memory_save (conf, G_OBJECT(header_view), "header-view");
694         
695         if (modest_header_view_get_style
696             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
697                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
698                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
699         else
700                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
701                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
702
703         modest_widget_memory_restore (conf, G_OBJECT(header_view),
704                                       "header-view");
705 }
706
707
708
709 /*
710  * Marks a message as read and passes it to the msg preview widget
711  */
712 static void
713 read_msg_func (gpointer data, gpointer user_data)
714 {
715         TnyMsg *msg;
716         TnyHeader *header;
717         GetMsgAsyncHelper *helper;
718         TnyHeaderFlags header_flags;
719         GtkWidget *msg_preview;
720         
721         msg = TNY_MSG (data);
722         helper = (GetMsgAsyncHelper *) user_data;
723
724         msg_preview = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (helper->window),
725                                                            MODEST_WIDGET_TYPE_MSG_PREVIEW);
726         if (!msg_preview)
727                 return;
728         
729         header = TNY_HEADER (tny_iterator_get_current (helper->iter));
730         header_flags = tny_header_get_flags (header);
731         tny_header_set_flags (header, header_flags | TNY_HEADER_FLAG_SEEN);
732         g_object_unref (G_OBJECT (header));
733
734         /* Set message on msg view */
735         modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), msg);
736 }
737
738 /*
739  * This function is a generic handler for the tny_folder_get_msg_async
740  * call. It expects as user_data a #GetMsgAsyncHelper. This helper
741  * contains a user provided function that is called inside this
742  * method. This will allow us to use this callback in many different
743  * places. This callback performs the common actions for the
744  * get_msg_async call, more specific actions will be done by the user
745  * function
746  */
747 static void
748 get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
749 {
750         GetMsgAsyncHelper *helper;
751
752         helper = (GetMsgAsyncHelper *) user_data;
753
754         if ((*err && ((*err)->code == TNY_FOLDER_ERROR_GET_MSG)) || !msg) {
755                 modest_ui_actions_on_item_not_found (NULL,
756                                                      MODEST_ITEM_TYPE_MESSAGE,
757                                                      helper->window);
758                 return;
759         }
760
761         /* Call user function */
762         helper->func (msg, user_data);
763
764         /* Process next element (if exists) */
765         tny_iterator_next (helper->iter);
766         if (tny_iterator_is_done (helper->iter)) {
767                 TnyList *headers;
768                 headers = tny_iterator_get_list (helper->iter);
769                 /* Free resources */
770                 g_object_unref (G_OBJECT (headers));
771                 g_object_unref (G_OBJECT (helper->iter));
772                 g_slice_free (GetMsgAsyncHelper, helper);
773         } else {
774                 TnyHeader *header;
775                 header = TNY_HEADER (tny_iterator_get_current (helper->iter)); 
776                 tny_folder_get_msg_async (folder, header,                         
777                                           get_msg_cb, NULL, helper);
778                 g_object_unref (G_OBJECT(header));
779         }
780 }
781
782 void 
783 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
784                                       TnyHeader *header,
785                                       ModestMainWindow *main_window)
786 {
787         TnyFolder *folder;
788         GetMsgAsyncHelper *helper;
789         TnyList *list;
790
791         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
792
793         /* when there's no header, clear the msgview */
794         if (!header) {
795                 GtkWidget *msg_preview;
796
797                 /* Clear msg preview if exists */
798                 msg_preview = modest_main_window_get_child_widget(main_window,
799                                                                   MODEST_WIDGET_TYPE_MSG_PREVIEW);
800         
801                 if (msg_preview)
802                         modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), NULL);
803                 return;
804         }
805
806         /* Update Main window title */
807         if (GTK_WIDGET_HAS_FOCUS (header_view)) {
808                 const gchar *subject = tny_header_get_subject (header);
809                 if (subject && strcmp (subject, ""))
810                         gtk_window_set_title (GTK_WINDOW (main_window), subject);
811                 else
812                         gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
813         }
814
815         /* Create list */
816         list = tny_simple_list_new ();
817         tny_list_prepend (list, G_OBJECT (header));
818
819         /* Fill helper data */
820         helper = g_slice_new0 (GetMsgAsyncHelper);
821         helper->window = MODEST_WINDOW (main_window);
822         helper->iter = tny_list_create_iterator (list);
823         helper->func = read_msg_func;
824
825         folder = tny_header_get_folder (TNY_HEADER(header));
826
827         tny_folder_get_msg_async (TNY_FOLDER(folder),
828                                   header, get_msg_cb,
829                                   NULL, helper);
830
831         /* Frees */
832         g_object_unref (G_OBJECT (folder));
833 }
834
835
836
837 void 
838 modest_ui_actions_on_header_activated (ModestHeaderView *folder_view, TnyHeader *header,
839                                        ModestMainWindow *main_window)
840 {
841         ModestWindow *win = NULL;
842         TnyFolder *folder = NULL;
843         TnyMsg    *msg    = NULL;
844         ModestWindowMgr *mgr;
845         
846         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
847         
848         if (!header)
849                 return;
850
851         folder = tny_header_get_folder (header);
852         if (!folder) {
853                 g_printerr ("modest: cannot get folder for header\n");
854                 return;
855         }
856
857         /* FIXME: make async?; check error  */
858         msg = tny_folder_get_msg (folder, header, NULL);
859         if (!msg) {
860                 g_printerr ("modest: cannot get msg for header\n");
861                 goto cleanup;
862         }
863
864         /* Look if we already have a message view for that header */    
865         mgr = modest_runtime_get_window_mgr ();
866         win = modest_window_mgr_find_window_by_msguid (mgr, tny_header_get_uid (header));
867
868         /* If not, create a new window */
869         if (!win) {
870                 gchar *account;
871
872                 account =  g_strdup(modest_window_get_active_account(MODEST_WINDOW(main_window)));
873                 if (!account)
874                         account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
875
876                 win = modest_msg_view_window_new (msg, account);
877                 modest_window_mgr_register_window (mgr, win);
878
879                 gtk_window_set_transient_for (GTK_WINDOW (win),
880                                               GTK_WINDOW (main_window));
881         }
882
883         gtk_widget_show_all (GTK_WIDGET(win));
884
885         g_object_unref (G_OBJECT (msg));
886         
887 cleanup:
888         g_object_unref (G_OBJECT (folder));
889 }
890
891 void 
892 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
893                                                TnyFolderStore *folder_store, 
894                                                gboolean selected,
895                                                ModestMainWindow *main_window)
896 {
897         ModestConf *conf;
898         GtkWidget *header_view;
899         
900         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
901
902         header_view = modest_main_window_get_child_widget(main_window,
903                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
904         if (!header_view)
905                 return;
906         
907         conf = modest_runtime_get_conf ();
908
909         if (TNY_IS_FOLDER (folder_store)) {
910
911                 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
912
913                 if (selected) {
914                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), 
915                                                        TNY_FOLDER (folder_store));
916                         modest_widget_memory_restore (conf, G_OBJECT(header_view),
917                                                       "header-view");
918                 } else {
919                         modest_widget_memory_save (conf, G_OBJECT (header_view), "header-view");
920                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
921                 }
922         } else if (TNY_IS_ACCOUNT (folder_store)) {
923
924                 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
925
926 /*              if (selected) { */
927                         
928 /*              } else { */
929 /*                      /\* TODO *\/ */
930 /*              }        */
931         }
932 }
933
934 void 
935 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
936                                      ModestWindow *win)
937 {
938         GtkWidget *dialog;
939         gchar *txt, *item;
940         gboolean online;
941
942         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
943         
944         if (g_main_depth > 0)   
945                 gdk_threads_enter ();
946         online = tny_device_is_online (modest_runtime_get_device());
947
948         if (online) {
949                 /* already online -- the item is simply not there... */
950                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
951                                                  GTK_DIALOG_MODAL,
952                                                  GTK_MESSAGE_WARNING,
953                                                  GTK_BUTTONS_OK,
954                                                  _("The %s you selected cannot be found"),
955                                                  item);
956                 gtk_dialog_run (GTK_DIALOG(dialog));
957         } else {
958                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
959                                                       GTK_WINDOW (win),
960                                                       GTK_DIALOG_MODAL,
961                                                       GTK_STOCK_CANCEL,
962                                                       GTK_RESPONSE_REJECT,
963                                                       GTK_STOCK_OK,
964                                                       GTK_RESPONSE_ACCEPT,
965                                                       NULL);
966                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
967                                          "Do you want to get online?"), item);
968                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
969                                     gtk_label_new (txt), FALSE, FALSE, 0);
970                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
971                 g_free (txt);
972
973                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
974                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
975 //                      tny_device_force_online (modest_runtime_get_device());
976                 }
977         }
978         gtk_widget_destroy (dialog);
979         if (g_main_depth > 0)   
980                 gdk_threads_leave ();
981 }
982
983 void
984 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
985                                      ModestWindow *win)
986 {
987         g_message ("%s %s", __FUNCTION__, link);
988 }       
989
990
991 void
992 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
993                                         ModestWindow *win)
994 {
995         modest_platform_activate_uri (link);
996 }
997
998 void
999 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1000                                           ModestWindow *win)
1001 {
1002         modest_platform_show_uri_popup (link);
1003 }
1004
1005 void
1006 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1007                                              ModestWindow *win)
1008 {
1009         g_message (__FUNCTION__);
1010         
1011 }
1012
1013 void
1014 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1015                                           const gchar *address,
1016                                           ModestWindow *win)
1017 {
1018         g_message ("%s %s", __FUNCTION__, address);
1019 }
1020
1021 void
1022 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1023 {
1024         TnyTransportAccount *transport_account;
1025         ModestMailOperation *mail_operation;
1026         MsgData *data;
1027         gchar *account_name, *from;
1028         ModestAccountMgr *account_mgr;
1029
1030         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1031         
1032         data = modest_msg_edit_window_get_msg_data (edit_window);
1033
1034         /* FIXME: Code added just for testing. The final version will
1035            use the send queue provided by tinymail and some
1036            classifier */
1037         account_mgr = modest_runtime_get_account_mgr();
1038         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1039         if (!account_name) 
1040                 account_name = modest_account_mgr_get_default_account (account_mgr);
1041         if (!account_name) {
1042                 g_printerr ("modest: no account found\n");
1043                 modest_msg_edit_window_free_msg_data (edit_window, data);
1044                 return;
1045         }
1046         transport_account =
1047                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
1048                                       (modest_runtime_get_account_store(),
1049                                        account_name,
1050                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1051         if (!transport_account) {
1052                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1053                 g_free (account_name);
1054                 modest_msg_edit_window_free_msg_data (edit_window, data);
1055                 return;
1056         }
1057         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1058
1059         /* Create the mail operation */         
1060         mail_operation = modest_mail_operation_new ();
1061         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1062
1063         modest_mail_operation_send_new_mail (mail_operation,
1064                                              transport_account,
1065                                              from,
1066                                              data->to, 
1067                                              data->cc, 
1068                                              data->bcc,
1069                                              data->subject, 
1070                                              data->plain_body, 
1071                                              data->html_body,
1072                                              data->attachments,
1073                                              data->priority_flags);
1074         /* Frees */
1075         g_free (from);
1076         g_free (account_name);
1077         g_object_unref (G_OBJECT (transport_account));
1078         g_object_unref (G_OBJECT (mail_operation));
1079
1080         modest_msg_edit_window_free_msg_data (edit_window, data);
1081
1082         /* Save settings and close the window */
1083         gtk_widget_destroy (GTK_WIDGET (edit_window));
1084 }
1085
1086 void 
1087 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1088                                   ModestMsgEditWindow *window)
1089 {
1090         ModestMsgEditFormatState *format_state = NULL;
1091
1092         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1093         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1094
1095         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1096                 return;
1097
1098         format_state = modest_msg_edit_window_get_format_state (window);
1099         g_return_if_fail (format_state != NULL);
1100
1101         format_state->bold = gtk_toggle_action_get_active (action);
1102         modest_msg_edit_window_set_format_state (window, format_state);
1103         g_free (format_state);
1104         
1105 }
1106
1107 void 
1108 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1109                                      ModestMsgEditWindow *window)
1110 {
1111         ModestMsgEditFormatState *format_state = NULL;
1112
1113         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1114         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1115
1116         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1117                 return;
1118
1119         format_state = modest_msg_edit_window_get_format_state (window);
1120         g_return_if_fail (format_state != NULL);
1121
1122         format_state->italics = gtk_toggle_action_get_active (action);
1123         modest_msg_edit_window_set_format_state (window, format_state);
1124         g_free (format_state);
1125         
1126 }
1127
1128 void 
1129 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
1130                                      ModestMsgEditWindow *window)
1131 {
1132         ModestMsgEditFormatState *format_state = NULL;
1133
1134         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1135         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1136
1137         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1138                 return;
1139
1140         format_state = modest_msg_edit_window_get_format_state (window);
1141         g_return_if_fail (format_state != NULL);
1142
1143         format_state->bullet = gtk_toggle_action_get_active (action);
1144         modest_msg_edit_window_set_format_state (window, format_state);
1145         g_free (format_state);
1146         
1147 }
1148
1149 void 
1150 modest_ui_actions_on_change_justify (GtkRadioAction *action,
1151                                      GtkRadioAction *selected,
1152                                      ModestMsgEditWindow *window)
1153 {
1154         ModestMsgEditFormatState *format_state = NULL;
1155         GtkJustification value;
1156
1157         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1158
1159         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1160                 return;
1161
1162         value = gtk_radio_action_get_current_value (selected);
1163
1164         format_state = modest_msg_edit_window_get_format_state (window);
1165         g_return_if_fail (format_state != NULL);
1166
1167         format_state->justification = value;
1168         modest_msg_edit_window_set_format_state (window, format_state);
1169         g_free (format_state);
1170 }
1171
1172 void 
1173 modest_ui_actions_on_select_editor_color (GtkAction *action,
1174                                           ModestMsgEditWindow *window)
1175 {
1176         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1177         g_return_if_fail (GTK_IS_ACTION (action));
1178
1179         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1180                 return;
1181
1182         modest_msg_edit_window_select_color (window);
1183 }
1184
1185 void 
1186 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
1187                                                      ModestMsgEditWindow *window)
1188 {
1189         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1190         g_return_if_fail (GTK_IS_ACTION (action));
1191
1192         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1193                 return;
1194
1195         modest_msg_edit_window_select_background_color (window);
1196 }
1197
1198 void 
1199 modest_ui_actions_on_insert_image (GtkAction *action,
1200                                    ModestMsgEditWindow *window)
1201 {
1202         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1203         g_return_if_fail (GTK_IS_ACTION (action));
1204
1205         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1206                 return;
1207
1208         modest_msg_edit_window_insert_image (window);
1209 }
1210
1211 /*
1212  * Shows a dialog with an entry that asks for some text. The returned
1213  * value must be freed by the caller. The dialog window title will be
1214  * set to @title.
1215  */
1216 static gchar *
1217 ask_for_folder_name (GtkWindow *parent_window,
1218                      const gchar *title)
1219 {
1220         GtkWidget *dialog, *entry;
1221         gchar *folder_name = NULL;
1222
1223         /* Ask for folder name */
1224         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1225                                               parent_window,
1226                                               GTK_DIALOG_MODAL,
1227                                               GTK_STOCK_CANCEL,
1228                                               GTK_RESPONSE_REJECT,
1229                                               GTK_STOCK_OK,
1230                                               GTK_RESPONSE_ACCEPT,
1231                                               NULL);
1232         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1233                             gtk_label_new(title),
1234                             FALSE, FALSE, 0);
1235                 
1236         entry = gtk_entry_new_with_max_length (40);
1237         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1238                             entry,
1239                             TRUE, FALSE, 0);    
1240         
1241         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1242         
1243         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
1244                 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1245
1246         gtk_widget_destroy (dialog);
1247
1248         return folder_name;
1249 }
1250
1251 void 
1252 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1253 {
1254         TnyFolderStore *parent_folder;
1255         GtkWidget *folder_view;
1256         
1257         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1258
1259         folder_view = modest_main_window_get_child_widget (main_window,
1260                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1261         if (!folder_view)
1262                 return;
1263
1264         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1265         
1266         if (parent_folder) {
1267                 gchar *folder_name;
1268
1269                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1270                                                    _("Please enter a name for the new folder"));
1271
1272                 if (folder_name != NULL && strlen (folder_name) > 0) {
1273                         TnyFolder *new_folder;
1274                         ModestMailOperation *mail_op;
1275
1276                         mail_op = modest_mail_operation_new ();
1277                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
1278                                                          mail_op);
1279
1280                         new_folder = modest_mail_operation_create_folder (mail_op,
1281                                                                           parent_folder,
1282                                                                           (const gchar *) folder_name);
1283                         if (new_folder) 
1284                                 g_object_unref (new_folder);
1285                         g_object_unref (mail_op);
1286                         g_free (folder_name);
1287                 }
1288                 g_object_unref (parent_folder);
1289         }
1290 }
1291
1292 void 
1293 modest_ui_actions_on_rename_folder (GtkAction *action,
1294                                      ModestMainWindow *main_window)
1295 {
1296         TnyFolderStore *folder;
1297         GtkWidget *folder_view;
1298         
1299         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1300
1301         folder_view = modest_main_window_get_child_widget (main_window,
1302                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1303         if (!folder_view)
1304                 return;
1305         
1306         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1307         
1308         if (folder && TNY_IS_FOLDER (folder)) {
1309                 gchar *folder_name;
1310                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1311                                                    _("Please enter a new name for the folder"));
1312
1313                 if (folder_name != NULL && strlen (folder_name) > 0) {
1314                         ModestMailOperation *mail_op;
1315
1316                         mail_op = modest_mail_operation_new ();
1317                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1318                                                          mail_op);
1319
1320                         modest_mail_operation_rename_folder (mail_op,
1321                                                              TNY_FOLDER (folder),
1322                                                              (const gchar *) folder_name);
1323
1324                         g_object_unref (mail_op);
1325                         g_free (folder_name);
1326                 }
1327                 g_object_unref (folder);
1328         }
1329 }
1330
1331 static void
1332 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
1333 {
1334         TnyFolderStore *folder;
1335         ModestMailOperation *mail_op;
1336         GtkWidget *folder_view;
1337         
1338         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1339
1340         folder_view = modest_main_window_get_child_widget (main_window,
1341                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1342         if (!folder_view)
1343                 return;
1344
1345         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1346         
1347         mail_op = modest_mail_operation_new ();
1348         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1349                                          mail_op);
1350         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
1351
1352         g_object_unref (G_OBJECT (mail_op));
1353         g_object_unref (G_OBJECT (folder));
1354 }
1355
1356 void 
1357 modest_ui_actions_on_delete_folder (GtkAction *action,
1358                                      ModestMainWindow *main_window)
1359 {
1360         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1361
1362         delete_folder (main_window, FALSE);
1363 }
1364
1365 void 
1366 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1367 {
1368         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1369         
1370         delete_folder (main_window, TRUE);
1371 }
1372
1373 void
1374 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
1375                                          const gchar* account_name,
1376                                          gchar **password, 
1377                                          gboolean *cancel, 
1378                                          gboolean *remember,
1379                                          ModestMainWindow *main_window)
1380 {
1381         gchar *txt;
1382         GtkWidget *dialog, *entry, *remember_pass_check;
1383
1384         dialog = gtk_dialog_new_with_buttons (_("Password requested"),
1385                                               NULL,
1386                                               GTK_DIALOG_MODAL,
1387                                               GTK_STOCK_CANCEL,
1388                                               GTK_RESPONSE_REJECT,
1389                                               GTK_STOCK_OK,
1390                                               GTK_RESPONSE_ACCEPT,
1391                                               NULL);
1392         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1393         
1394         txt = g_strdup_printf (_("Please enter your password for %s"), account_name);
1395         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1396                             FALSE, FALSE, 0);
1397         g_free (txt);
1398
1399         entry = gtk_entry_new_with_max_length (40);
1400         gtk_entry_set_visibility (GTK_ENTRY(entry), FALSE);
1401         gtk_entry_set_invisible_char (GTK_ENTRY(entry), 0x2022); /* bullet unichar */
1402         
1403         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry,
1404                             TRUE, FALSE, 0);    
1405
1406         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1407         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1408                             TRUE, FALSE, 0);
1409
1410         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1411         
1412         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1413                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry)));
1414                 *cancel   = FALSE;
1415         } else {
1416                 *password = NULL;
1417                 *cancel   = TRUE;
1418         }
1419
1420         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
1421                 *remember = TRUE;
1422         else
1423                 *remember = FALSE;
1424
1425         gtk_widget_destroy (dialog);
1426 }
1427
1428 void
1429 modest_ui_actions_on_cut (GtkAction *action,
1430                           ModestWindow *window)
1431 {
1432         GtkWidget *focused_widget;
1433
1434         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1435         if (GTK_IS_EDITABLE (focused_widget)) {
1436                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
1437         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1438                 GtkTextBuffer *buffer;
1439                 GtkClipboard *clipboard;
1440
1441                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1442                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1443                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
1444         }
1445 }
1446
1447 void
1448 modest_ui_actions_on_copy (GtkAction *action,
1449                            ModestWindow *window)
1450 {
1451         GtkClipboard *clipboard;
1452         GtkWidget *focused_widget;
1453
1454         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1455         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1456         if (GTK_IS_LABEL (focused_widget)) {
1457                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
1458         } else if (GTK_IS_EDITABLE (focused_widget)) {
1459                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
1460         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1461                 GtkTextBuffer *buffer;
1462
1463                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1464                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
1465         }
1466 }
1467
1468 void
1469 modest_ui_actions_on_undo (GtkAction *action,
1470                            ModestWindow *window)
1471 {
1472         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
1473                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
1474         } else {
1475                 g_return_if_reached ();
1476         }
1477 }
1478
1479 void
1480 modest_ui_actions_on_paste (GtkAction *action,
1481                             ModestWindow *window)
1482 {
1483         GtkWidget *focused_widget;
1484
1485         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1486         if (GTK_IS_EDITABLE (focused_widget)) {
1487                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
1488         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1489                 GtkTextBuffer *buffer;
1490                 GtkClipboard *clipboard;
1491
1492                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1493                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1494                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
1495         }
1496 }
1497
1498 void
1499 modest_ui_actions_on_select_all (GtkAction *action,
1500                                  ModestWindow *window)
1501 {
1502         GtkWidget *focused_widget;
1503
1504         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1505         if (GTK_IS_LABEL (focused_widget)) {
1506                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
1507         } else if (GTK_IS_EDITABLE (focused_widget)) {
1508                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
1509         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1510                 GtkTextBuffer *buffer;
1511                 GtkTextIter start, end;
1512
1513                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1514                 gtk_text_buffer_get_start_iter (buffer, &start);
1515                 gtk_text_buffer_get_end_iter (buffer, &end);
1516                 gtk_text_buffer_select_range (buffer, &start, &end);
1517         }
1518 }
1519
1520 void
1521 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
1522                                   GtkRadioAction *selected,
1523                                   ModestWindow *window)
1524 {
1525         gint value;
1526
1527         value = gtk_radio_action_get_current_value (selected);
1528         if (MODEST_IS_WINDOW (window)) {
1529                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
1530         }
1531 }
1532
1533 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
1534                                                         GtkRadioAction *selected,
1535                                                         ModestWindow *window)
1536 {
1537         TnyHeaderFlags flags;
1538         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1539
1540         flags = gtk_radio_action_get_current_value (selected);
1541         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
1542 }
1543
1544 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
1545                                                            GtkRadioAction *selected,
1546                                                            ModestWindow *window)
1547 {
1548         gint file_format;
1549
1550         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1551
1552         file_format = gtk_radio_action_get_current_value (selected);
1553         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
1554 }
1555
1556
1557 void     
1558 modest_ui_actions_on_zoom_plus (GtkAction *action,
1559                                 ModestWindow *window)
1560 {
1561         g_return_if_fail (MODEST_IS_WINDOW (window));
1562
1563         modest_window_zoom_plus (MODEST_WINDOW (window));
1564 }
1565
1566 void     
1567 modest_ui_actions_on_zoom_minus (GtkAction *action,
1568                                  ModestWindow *window)
1569 {
1570         g_return_if_fail (MODEST_IS_WINDOW (window));
1571
1572         modest_window_zoom_minus (MODEST_WINDOW (window));
1573 }
1574
1575 void     
1576 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
1577                                            ModestWindow *window)
1578 {
1579         ModestWindowMgr *mgr;
1580         gboolean fullscreen, active;
1581         g_return_if_fail (MODEST_IS_WINDOW (window));
1582
1583         mgr = modest_runtime_get_window_mgr ();
1584
1585         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
1586         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1587
1588         if (active != fullscreen) {
1589                 modest_window_mgr_set_fullscreen_mode (mgr, active);
1590                 gtk_window_present (GTK_WINDOW (window));
1591         }
1592 }
1593
1594 void
1595 modest_ui_actions_on_change_fullscreen (GtkAction *action,
1596                                         ModestWindow *window)
1597 {
1598         ModestWindowMgr *mgr;
1599         gboolean fullscreen;
1600
1601         g_return_if_fail (MODEST_IS_WINDOW (window));
1602
1603         mgr = modest_runtime_get_window_mgr ();
1604         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1605         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
1606
1607         gtk_window_present (GTK_WINDOW (window));
1608 }
1609
1610 static void
1611 modest_ui_actions_message_details_cb (gpointer msg_data, 
1612                                       gpointer helper_data)
1613 {
1614         GtkWidget *dialog;
1615         TnyMsg *msg = (TnyMsg *) msg_data;
1616         TnyHeader *header;
1617         GetMsgAsyncHelper *helper = (GetMsgAsyncHelper *) helper_data;
1618         
1619         header = tny_msg_get_header (msg);
1620         
1621         dialog = modest_msg_view_details_dialog_new (GTK_WINDOW (helper->window), header);
1622         g_object_unref (header);
1623         gtk_widget_show_all (dialog);
1624
1625         gtk_dialog_run (GTK_DIALOG (dialog));
1626
1627         gtk_widget_destroy (dialog);
1628 }
1629
1630 void     
1631 modest_ui_actions_on_message_details (GtkAction *action, 
1632                                       ModestWindow *win)
1633 {
1634         TnyList * headers_list;
1635         GetMsgAsyncHelper *helper;
1636
1637         headers_list = get_selected_headers (win);
1638         if (!headers_list)
1639                 return;
1640
1641         helper = g_slice_new0 (GetMsgAsyncHelper);
1642         helper->window = win;
1643         helper->func = modest_ui_actions_message_details_cb;
1644         helper->iter = tny_list_create_iterator (headers_list);
1645         helper->user_data = NULL;
1646
1647         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1648                 TnyMsg *msg;
1649
1650                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
1651                 if (!msg)
1652                         return;
1653                 else {
1654                         modest_ui_actions_message_details_cb (msg, helper);
1655                 }
1656         } else {
1657                 /* here we should add an implementation to run the message details dialog
1658                    from the main window */
1659                 g_return_if_reached ();
1660         }
1661 }
1662
1663 void     
1664 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
1665                                      ModestMsgEditWindow *window)
1666 {
1667         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1668
1669         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
1670 }
1671
1672 void     
1673 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
1674                                       ModestMsgEditWindow *window)
1675 {
1676         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1677
1678         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
1679 }
1680
1681 void
1682 modest_ui_actions_toggle_folders_view (GtkAction *action, 
1683                                        ModestMainWindow *main_window)
1684 {
1685         ModestConf *conf;
1686         
1687         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1688
1689         conf = modest_runtime_get_conf ();
1690         
1691         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
1692                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
1693         else
1694                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
1695 }
1696
1697 void 
1698 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
1699                                      ModestWindow *window)
1700 {
1701         gboolean active, fullscreen = FALSE;
1702         ModestWindowMgr *mgr;
1703
1704         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
1705
1706         /* Check if we want to toggle the toolbar vuew in fullscreen
1707            or normal mode */
1708         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
1709                      "ViewShowToolbarFullScreen")) {
1710                 fullscreen = TRUE;
1711         }
1712
1713         /* Toggle toolbar */
1714         mgr = modest_runtime_get_window_mgr ();
1715         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
1716 }
1717
1718 void     
1719 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
1720                                            ModestMsgEditWindow *window)
1721 {
1722         modest_msg_edit_window_select_font (window);
1723 }
1724
1725 void
1726 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
1727                                                   const gchar *display_name,
1728                                                   GtkWindow *window)
1729 {
1730         /* Do not change the application name if the widget has not
1731            the focus. This callback could be called even if the folder
1732            view has not the focus, because the handled signal could be
1733            emitted when the folder view is redrawn */
1734         if (GTK_WIDGET_HAS_FOCUS (folder_view)) {
1735                 if (display_name)
1736                         gtk_window_set_title (window, display_name);
1737                 else
1738                         gtk_window_set_title (window, " ");
1739         }
1740 }
1741
1742 void
1743 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
1744 {
1745         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1746         modest_msg_edit_window_select_contacts (window);
1747 }