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