f90427c7446dc99e56ed56cd2196ee58f27e466c
[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_paste (GtkAction *action,
1458                             ModestWindow *window)
1459 {
1460         GtkWidget *focused_widget;
1461
1462         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1463         if (GTK_IS_EDITABLE (focused_widget)) {
1464                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
1465         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1466                 GtkTextBuffer *buffer;
1467                 GtkClipboard *clipboard;
1468
1469                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1470                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1471                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
1472         }
1473 }
1474
1475 void
1476 modest_ui_actions_on_select_all (GtkAction *action,
1477                                  ModestWindow *window)
1478 {
1479         GtkWidget *focused_widget;
1480
1481         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1482         if (GTK_IS_LABEL (focused_widget)) {
1483                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
1484         } else if (GTK_IS_EDITABLE (focused_widget)) {
1485                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
1486         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1487                 GtkTextBuffer *buffer;
1488                 GtkTextIter start, end;
1489
1490                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1491                 gtk_text_buffer_get_start_iter (buffer, &start);
1492                 gtk_text_buffer_get_end_iter (buffer, &end);
1493                 gtk_text_buffer_select_range (buffer, &start, &end);
1494         }
1495 }
1496
1497 void
1498 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
1499                                   GtkRadioAction *selected,
1500                                   ModestWindow *window)
1501 {
1502         gint value;
1503
1504         value = gtk_radio_action_get_current_value (selected);
1505         if (MODEST_IS_WINDOW (window)) {
1506                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
1507         }
1508 }
1509
1510 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
1511                                                         GtkRadioAction *selected,
1512                                                         ModestWindow *window)
1513 {
1514         TnyHeaderFlags flags;
1515         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1516
1517         flags = gtk_radio_action_get_current_value (selected);
1518         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
1519 }
1520
1521
1522 void     
1523 modest_ui_actions_on_zoom_plus (GtkAction *action,
1524                                 ModestWindow *window)
1525 {
1526         g_return_if_fail (MODEST_IS_WINDOW (window));
1527
1528         modest_window_zoom_plus (MODEST_WINDOW (window));
1529 }
1530
1531 void     
1532 modest_ui_actions_on_zoom_minus (GtkAction *action,
1533                                  ModestWindow *window)
1534 {
1535         g_return_if_fail (MODEST_IS_WINDOW (window));
1536
1537         modest_window_zoom_minus (MODEST_WINDOW (window));
1538 }
1539
1540 void     
1541 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
1542                                            ModestWindow *window)
1543 {
1544         ModestWindowMgr *mgr;
1545         gboolean fullscreen, active;
1546         g_return_if_fail (MODEST_IS_WINDOW (window));
1547
1548         mgr = modest_runtime_get_window_mgr ();
1549
1550         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
1551         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1552
1553         if (active != fullscreen) {
1554                 modest_window_mgr_set_fullscreen_mode (mgr, active);
1555                 gtk_window_present (GTK_WINDOW (window));
1556         }
1557 }
1558
1559 void
1560 modest_ui_actions_on_change_fullscreen (GtkAction *action,
1561                                         ModestWindow *window)
1562 {
1563         ModestWindowMgr *mgr;
1564         gboolean fullscreen;
1565
1566         g_return_if_fail (MODEST_IS_WINDOW (window));
1567
1568         mgr = modest_runtime_get_window_mgr ();
1569         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1570         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
1571
1572         gtk_window_present (GTK_WINDOW (window));
1573 }
1574
1575 static void
1576 modest_ui_actions_message_details_cb (gpointer msg_data, 
1577                                       gpointer helper_data)
1578 {
1579         GtkWidget *dialog;
1580         TnyMsg *msg = (TnyMsg *) msg_data;
1581         TnyHeader *header;
1582         GetMsgAsyncHelper *helper = (GetMsgAsyncHelper *) helper_data;
1583         
1584         header = tny_msg_get_header (msg);
1585         
1586         dialog = modest_msg_view_details_dialog_new (GTK_WINDOW (helper->window), header);
1587         g_object_unref (header);
1588         gtk_widget_show_all (dialog);
1589
1590         gtk_dialog_run (GTK_DIALOG (dialog));
1591
1592         gtk_widget_destroy (dialog);
1593 }
1594
1595 void     
1596 modest_ui_actions_on_message_details (GtkAction *action, 
1597                                       ModestWindow *win)
1598 {
1599         TnyList * headers_list;
1600         GetMsgAsyncHelper *helper;
1601
1602         headers_list = get_selected_headers (win);
1603         if (!headers_list)
1604                 return;
1605
1606         helper = g_slice_new0 (GetMsgAsyncHelper);
1607         helper->window = win;
1608         helper->func = modest_ui_actions_message_details_cb;
1609         helper->iter = tny_list_create_iterator (headers_list);
1610         helper->user_data = NULL;
1611
1612         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1613                 TnyMsg *msg;
1614
1615                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
1616                 if (!msg)
1617                         return;
1618                 else {
1619                         modest_ui_actions_message_details_cb (msg, helper);
1620                 }
1621         } else {
1622                 /* here we should add an implementation to run the message details dialog
1623                    from the main window */
1624                 g_return_if_reached ();
1625         }
1626 }
1627
1628 void     
1629 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
1630                                      ModestMsgEditWindow *window)
1631 {
1632         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1633
1634         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
1635 }
1636
1637 void     
1638 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
1639                                       ModestMsgEditWindow *window)
1640 {
1641         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1642
1643         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
1644 }
1645
1646 void
1647 modest_ui_actions_toggle_folders_view (GtkAction *action, 
1648                                        ModestMainWindow *main_window)
1649 {
1650         ModestConf *conf;
1651         
1652         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1653
1654         conf = modest_runtime_get_conf ();
1655         
1656         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
1657                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
1658         else
1659                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
1660 }
1661
1662 void 
1663 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
1664                                      ModestWindow *window)
1665 {
1666         gboolean active, fullscreen = FALSE;
1667         ModestWindowMgr *mgr;
1668
1669         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
1670
1671         /* Check if we want to toggle the toolbar vuew in fullscreen
1672            or normal mode */
1673         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
1674                      "ViewShowToolbarFullScreen")) {
1675                 fullscreen = TRUE;
1676         }
1677
1678         /* Toggle toolbar */
1679         mgr = modest_runtime_get_window_mgr ();
1680         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
1681 }
1682
1683 void
1684 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
1685                                                   const gchar *display_name,
1686                                                   GtkWindow *window)
1687 {
1688         /* Do not change the application name if the widget has not
1689            the focus. This callback could be called even if the folder
1690            view has not the focus, because the handled signal could be
1691            emitted when the folder view is redrawn */
1692         if (GTK_WIDGET_HAS_FOCUS (folder_view)) {
1693                 if (display_name)
1694                         gtk_window_set_title (window, display_name);
1695                 else
1696                         gtk_window_set_title (window, " ");
1697         }
1698 }