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