* Change headers list tree view rows layout (flags, header, date).
[modest] / src / modest-ui-actions.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif /*HAVE_CONFIG_H*/
33
34 #include <glib/gi18n.h>
35 #include <string.h>
36 #include <modest-runtime.h>
37 #include <modest-tny-folder.h>
38 #include <modest-tny-msg.h>
39 #include <modest-tny-account.h>
40 #include <modest-address-book.h>
41
42 #include "modest-ui-actions.h"
43
44 #include "modest-tny-platform-factory.h"
45 #include "modest-platform.h"
46
47 #include <widgets/modest-main-window.h>
48 #include <widgets/modest-msg-view-window.h>
49 #include <widgets/modest-account-view-window.h>
50 #include <widgets/modest-msg-view-details-dialog.h>
51
52 #include "modest-account-mgr-helpers.h"
53 #include "modest-mail-operation.h"
54
55 #ifdef MODEST_HAVE_EASYSETUP
56 #include "easysetup/modest-easysetup-wizard.h"
57 #endif /*MODEST_HAVE_EASYSETUP*/
58
59 #include <modest-widget-memory.h>
60 #include <tny-error.h>
61 #include <tny-simple-list.h>
62 #include <tny-msg-view.h>
63 #include <tny-device.h>
64
65
66 typedef struct _GetMsgAsyncHelper {
67         ModestWindow *window;
68         TnyIterator *iter;
69         GFunc func;
70         gpointer user_data;
71 } GetMsgAsyncHelper;
72
73 typedef enum _ReplyForwardAction {
74         ACTION_REPLY,
75         ACTION_REPLY_TO_ALL,
76         ACTION_FORWARD
77 } ReplyForwardAction;
78
79 typedef struct _ReplyForwardHelper {
80 guint reply_forward_type;
81         ReplyForwardAction action;
82         gchar *account_name;
83 } ReplyForwardHelper;
84
85
86 static void     reply_forward_func     (gpointer data, gpointer user_data);
87 static void     read_msg_func          (gpointer data, gpointer user_data);
88 static void     get_msg_cb             (TnyFolder *folder, TnyMsg *msg, GError **err, 
89                                         gpointer user_data);
90 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
91 static void     modest_ui_actions_message_details_cb (gpointer msg_data, 
92                                                       gpointer helper_data);
93 static gchar*   ask_for_folder_name    (GtkWindow *parent_window, const gchar *title);
94
95
96 void   
97 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
98 {
99         GtkWidget *about;
100         const gchar *authors[] = {
101                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
102                 NULL
103         };
104         about = gtk_about_dialog_new ();
105         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
106         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
107         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
108                                         _("Copyright (c) 2006, Nokia Corporation\n"
109                                           "All rights reserved."));
110         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
111                                        _("a modest e-mail client\n\n"
112                                          "design and implementation: Dirk-Jan C. Binnema\n"
113                                          "contributions from the fine people at KernelConcepts and Igalia\n"
114                                          "uses the tinymail email framework written by Philip van Hoof"));
115         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
116         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
117         
118         gtk_dialog_run (GTK_DIALOG (about));
119         gtk_widget_destroy(about);
120 }
121
122
123 static TnyList *
124 get_selected_headers (ModestWindow *win)
125 {
126         if (MODEST_IS_MAIN_WINDOW(win)) {
127                 GtkWidget *header_view;         
128                 
129                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
130                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
131                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
132                 
133         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
134                 /* for MsgViewWindows, we simply return a list with one element */
135                 TnyMsg *msg;
136                 TnyHeader *header;
137                 TnyList *list = NULL;
138                 
139                 msg  = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
140                 if (msg) {
141                         header = tny_msg_get_header (msg);
142                         list = tny_simple_list_new ();
143                         tny_list_prepend (list, G_OBJECT(header));
144                         g_object_unref (G_OBJECT(header));
145                 }
146                 return list;
147
148         } else
149                 return NULL;
150 }
151
152 void
153 modest_ui_actions_on_delete (GtkAction *action, ModestWindow *win)
154 {
155         TnyList *header_list;
156         TnyIterator *iter;
157
158         g_return_if_fail (MODEST_IS_WINDOW(win));
159                 
160         header_list = get_selected_headers (win);
161         
162         if (header_list) {
163                 iter = tny_list_create_iterator (header_list);
164                 do {
165                         TnyHeader *header;
166                         ModestMailOperation *mail_op;
167
168                         header = TNY_HEADER (tny_iterator_get_current (iter));
169                         /* TODO: thick grain mail operation involving
170                            a list of objects. Composite pattern ??? */
171                         /* TODO: add confirmation dialog */
172                         mail_op = modest_mail_operation_new ();
173                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
174                                                          mail_op);
175
176                         /* Always delete. TODO: Move to trash still not supported */
177                         modest_mail_operation_remove_msg (mail_op, header, FALSE);
178
179                         /* Frees */
180                         g_object_unref (G_OBJECT (mail_op));
181                         g_object_unref (G_OBJECT (header));
182
183                         tny_iterator_next (iter);
184
185                 } while (!tny_iterator_is_done (iter));
186
187                 /* Free iter */
188                 g_object_unref (G_OBJECT (iter));
189         }
190
191         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
192                 gtk_widget_destroy (GTK_WIDGET(win));
193         } 
194 }
195
196
197 void
198 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
199 {
200         gtk_main_quit ();
201 }
202
203 void
204 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
205 {
206         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
207                 gtk_widget_destroy (GTK_WIDGET (win));
208         } else if (MODEST_IS_WINDOW (win)) {
209                 gtk_widget_destroy (GTK_WIDGET (win));
210         } else {
211                 g_return_if_reached ();
212         }
213 }
214
215 void
216 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
217 {
218         GtkClipboard *clipboard = NULL;
219         gchar *selection = NULL;
220
221         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
222         selection = gtk_clipboard_wait_for_text (clipboard);
223
224         modest_address_book_add_address (selection);
225         g_free (selection);
226 }
227
228 void
229 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
230 {
231         
232         /* This is currently only implemented for Maemo,
233          * because it requires a providers preset file which is not publically available.
234          */
235 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
236         GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr());
237         gboolean accounts_exist = account_names != NULL;
238         g_slist_free (account_names);
239         
240 /* To test, while modest_account_mgr_account_names() is broken: accounts_exist = TRUE; */
241         if (!accounts_exist) {
242                 /* If there are no accounts yet, just show the easy-setup wizard, as per the UI spec: */
243                 ModestEasysetupWizardDialog *wizard = modest_easysetup_wizard_dialog_new ();
244                 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
245                 gtk_dialog_run (GTK_DIALOG (wizard));
246                 gtk_widget_destroy (GTK_WIDGET (wizard));
247         } else  {
248                 /* Show the list of accounts: */
249                 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
250                 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW(win));
251                 gtk_dialog_run (account_win);
252                 gtk_widget_destroy (GTK_WIDGET(account_win));
253         }
254 #else
255         GtkWidget *dialog, *label;
256         
257         /* Create the widgets */
258         
259         dialog = gtk_dialog_new_with_buttons ("Message",
260                                               GTK_WINDOW(win),
261                                               GTK_DIALOG_DESTROY_WITH_PARENT,
262                                               GTK_STOCK_OK,
263                                               GTK_RESPONSE_NONE,
264                                               NULL);
265         label = gtk_label_new ("Hello World!");
266         
267         /* Ensure that the dialog box is destroyed when the user responds. */
268         
269         g_signal_connect_swapped (dialog, "response", 
270                                   G_CALLBACK (gtk_widget_destroy),
271                                   dialog);
272         
273         /* Add the label, and show everything we've added to the dialog. */
274         
275         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
276                            label);
277         gtk_widget_show_all (dialog);
278 #endif /* MODEST_PLATFORM_MAEMO */
279 }
280
281 void
282 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
283 {
284         ModestWindow *msg_win;
285         TnyMsg *msg = NULL;
286         TnyFolder *folder = NULL;
287         gchar *account_name = NULL;
288         gchar *from_str = NULL;
289         GError *err = NULL;
290         TnyAccount *account = NULL;
291         ModestWindowMgr *mgr;
292         
293         account_name = g_strdup(modest_window_get_active_account (win));
294         if (!account_name)
295                 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
296         if (!account_name) {
297                 g_printerr ("modest: no account found\n");
298                 goto cleanup;
299         }
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 static gboolean
585 action_send (const gchar* account_name)
586 {
587         TnyAccount *tny_account;
588         ModestTnySendQueue *send_queue;
589
590         g_return_val_if_fail (account_name, FALSE);
591
592         tny_account = 
593                 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
594                                                                      account_name,
595                                                                      TNY_ACCOUNT_TYPE_TRANSPORT);
596         if (!tny_account) {
597                 g_printerr ("modest: cannot get tny transport account for %s\n", account_name);
598                 return FALSE;
599         }
600         send_queue = modest_tny_send_queue_new (TNY_CAMEL_TRANSPORT_ACCOUNT(tny_account));
601         if (!send_queue) {
602                 g_object_unref (G_OBJECT(tny_account));
603                 g_printerr ("modest: cannot get send queue for %s\n", account_name);
604                 return FALSE;
605         }
606         
607         //modest_tny_send_queue_flush (send_queue);
608
609         g_object_unref (G_OBJECT(send_queue));
610         g_object_unref (G_OBJECT(tny_account));
611
612         return TRUE;
613 }
614
615
616 static gboolean
617 action_receive (const gchar* account_name)
618 {
619         TnyAccount *tny_account;
620         ModestMailOperation *mail_op;
621
622         g_return_val_if_fail (account_name, FALSE);
623
624         tny_account = 
625                 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
626                                                                      account_name,
627                                                                      TNY_ACCOUNT_TYPE_STORE);
628         if (!tny_account) {
629                 g_printerr ("modest: cannot get tny store account for %s\n", account_name);
630                 return FALSE;
631         }
632
633         /* Create the mail operation */
634         mail_op = modest_mail_operation_new ();
635         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
636         modest_mail_operation_update_account (mail_op, TNY_STORE_ACCOUNT(tny_account));
637
638         g_object_unref (G_OBJECT(tny_account));
639         g_object_unref (G_OBJECT (mail_op));
640                 
641         return TRUE;
642 }
643
644
645
646 void
647 modest_ui_actions_on_send_receive (GtkAction *action,  ModestWindow *win)
648 {
649         gchar *account_name;
650         
651         account_name =
652                 g_strdup(modest_window_get_active_account(MODEST_WINDOW(win)));
653         if (!account_name)
654                 account_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
655         if (!account_name) {
656                 g_printerr ("modest: cannot get account\n");
657                 return;
658         }
659
660         if (!action_send(account_name))
661                 g_printerr ("modest: failed to send\n");
662         if (!action_receive(account_name))
663                 g_printerr ("modest: failed to receive\n");
664 }
665
666
667
668 void
669 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
670 {
671         ModestConf *conf;
672         GtkWidget *header_view;
673         
674         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
675
676         header_view = modest_main_window_get_child_widget (main_window,
677                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
678         if (!header_view)
679                 return;
680
681         conf = modest_runtime_get_conf ();
682         
683         /* what is saved/restored is depending on the style; thus; we save with
684          * old style, then update the style, and restore for this new style
685          */
686         modest_widget_memory_save (conf, G_OBJECT(header_view), "header-view");
687         
688         if (modest_header_view_get_style
689             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
690                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
691                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
692         else
693                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
694                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
695
696         modest_widget_memory_restore (conf, G_OBJECT(header_view),
697                                       "header-view");
698 }
699
700
701
702 /*
703  * Marks a message as read and passes it to the msg preview widget
704  */
705 static void
706 read_msg_func (gpointer data, gpointer user_data)
707 {
708         TnyMsg *msg;
709         TnyHeader *header;
710         GetMsgAsyncHelper *helper;
711         TnyHeaderFlags header_flags;
712         GtkWidget *msg_preview;
713         
714         msg = TNY_MSG (data);
715         helper = (GetMsgAsyncHelper *) user_data;
716
717         msg_preview = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (helper->window),
718                                                            MODEST_WIDGET_TYPE_MSG_PREVIEW);
719         if (!msg_preview)
720                 return;
721         
722         header = TNY_HEADER (tny_iterator_get_current (helper->iter));
723         header_flags = tny_header_get_flags (header);
724         tny_header_set_flags (header, header_flags | TNY_HEADER_FLAG_SEEN);
725         g_object_unref (G_OBJECT (header));
726
727         /* Set message on msg view */
728         modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), msg);
729 }
730
731 /*
732  * This function is a generic handler for the tny_folder_get_msg_async
733  * call. It expects as user_data a #GetMsgAsyncHelper. This helper
734  * contains a user provided function that is called inside this
735  * method. This will allow us to use this callback in many different
736  * places. This callback performs the common actions for the
737  * get_msg_async call, more specific actions will be done by the user
738  * function
739  */
740 static void
741 get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
742 {
743         GetMsgAsyncHelper *helper;
744
745         helper = (GetMsgAsyncHelper *) user_data;
746
747         if ((*err && ((*err)->code == TNY_FOLDER_ERROR_GET_MSG)) || !msg) {
748                 modest_ui_actions_on_item_not_found (NULL,
749                                                      MODEST_ITEM_TYPE_MESSAGE,
750                                                      helper->window);
751                 return;
752         }
753
754         /* Call user function */
755         helper->func (msg, user_data);
756
757         /* Process next element (if exists) */
758         tny_iterator_next (helper->iter);
759         if (tny_iterator_is_done (helper->iter)) {
760                 TnyList *headers;
761                 headers = tny_iterator_get_list (helper->iter);
762                 /* Free resources */
763                 g_object_unref (G_OBJECT (headers));
764                 g_object_unref (G_OBJECT (helper->iter));
765                 g_slice_free (GetMsgAsyncHelper, helper);
766         } else {
767                 TnyHeader *header;
768                 header = TNY_HEADER (tny_iterator_get_current (helper->iter)); 
769                 tny_folder_get_msg_async (folder, header,                         
770                                           get_msg_cb, helper);
771                 g_object_unref (G_OBJECT(header));
772         }
773 }
774
775 void 
776 modest_ui_actions_on_header_selected (ModestHeaderView *folder_view, 
777                                       TnyHeader *header,
778                                       ModestMainWindow *main_window)
779 {
780         GtkWidget *msg_preview;
781         TnyFolder *folder;
782         GetMsgAsyncHelper *helper;
783         TnyList *list;
784
785         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
786         
787         msg_preview = modest_main_window_get_child_widget(main_window,
788                                                           MODEST_WIDGET_TYPE_MSG_PREVIEW);
789         if (!msg_preview)
790                 return;
791         
792         /* when there's no header, clear the msgview */
793         if (!header) {
794                 modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), NULL);
795                 return;
796         }
797
798         folder = tny_header_get_folder (TNY_HEADER(header));
799
800         /* Create list */
801         list = tny_simple_list_new ();
802         tny_list_prepend (list, G_OBJECT (header));
803
804         /* Fill helper data */
805         helper = g_slice_new0 (GetMsgAsyncHelper);
806         helper->window = MODEST_WINDOW (main_window);
807         helper->iter = tny_list_create_iterator (list);
808         helper->func = read_msg_func;
809
810         tny_folder_get_msg_async (TNY_FOLDER(folder),
811                                   header, get_msg_cb,
812                                   helper);
813
814         /* Frees */
815         g_object_unref (G_OBJECT (folder));
816 }
817
818
819
820 void 
821 modest_ui_actions_on_header_activated (ModestHeaderView *folder_view, TnyHeader *header,
822                                        ModestMainWindow *main_window)
823 {
824         ModestWindow *win = NULL;
825         TnyFolder *folder = NULL;
826         TnyMsg    *msg    = NULL;
827         ModestWindowMgr *mgr;
828         
829         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
830         
831         if (!header)
832                 return;
833
834         folder = tny_header_get_folder (header);
835         if (!folder) {
836                 g_printerr ("modest: cannot get folder for header\n");
837                 return;
838         }
839
840         /* FIXME: make async?; check error  */
841         msg = tny_folder_get_msg (folder, header, NULL);
842         if (!msg) {
843                 g_printerr ("modest: cannot get msg for header\n");
844                 goto cleanup;
845         }
846
847         /* Look if we already have a message view for that header */    
848         mgr = modest_runtime_get_window_mgr ();
849         win = modest_window_mgr_find_window_by_msguid (mgr, tny_header_get_uid (header));
850
851         /* If not, create a new window */
852         if (!win) {
853                 gchar *account;
854
855                 account =  g_strdup(modest_window_get_active_account(MODEST_WINDOW(main_window)));
856                 if (!account)
857                         account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
858
859                 win = modest_msg_view_window_new (msg, account);
860                 modest_window_mgr_register_window (mgr, win);
861
862                 gtk_window_set_transient_for (GTK_WINDOW (win),
863                                               GTK_WINDOW (main_window));
864         }
865
866         gtk_widget_show_all (GTK_WIDGET(win));
867
868         g_object_unref (G_OBJECT (msg));
869         
870 cleanup:
871         g_object_unref (G_OBJECT (folder));
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);
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_folders_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         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
1644                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
1645         else
1646                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
1647 }
1648
1649 void 
1650 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
1651                                      ModestWindow *window)
1652 {
1653         gboolean active, fullscreen = FALSE;
1654         ModestWindowMgr *mgr;
1655
1656         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
1657
1658         /* Check if we want to toggle the toolbar vuew in fullscreen
1659            or normal mode */
1660         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
1661                      "ViewShowToolbarFullScreen")) {
1662                 fullscreen = TRUE;
1663         }
1664
1665         /* Toggle toolbar */
1666         mgr = modest_runtime_get_window_mgr ();
1667         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
1668 }