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