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