2007-04-23 Murray Cumming <murrayc@murrayc.com>
[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 typedef struct _GetMsgAsyncHelper {
66         ModestWindow *window;
67         TnyIterator *iter;
68         GFunc func;
69         gpointer user_data;
70 } GetMsgAsyncHelper;
71
72 typedef enum _ReplyForwardAction {
73         ACTION_REPLY,
74         ACTION_REPLY_TO_ALL,
75         ACTION_FORWARD
76 } ReplyForwardAction;
77
78 typedef struct _ReplyForwardHelper {
79 guint reply_forward_type;
80         ReplyForwardAction action;
81         gchar *account_name;
82 } ReplyForwardHelper;
83
84
85 static void     reply_forward_func     (gpointer data, gpointer user_data);
86 static void     read_msg_func          (gpointer data, gpointer user_data);
87 static void     get_msg_cb             (TnyFolder *folder, TnyMsg *msg, GError **err, 
88                                         gpointer user_data);
89 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
90
91 static gchar*   ask_for_folder_name    (GtkWindow *parent_window, const gchar *title);
92
93
94 void   
95 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
96 {
97         GtkWidget *about;
98         const gchar *authors[] = {
99                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
100                 NULL
101         };
102         about = gtk_about_dialog_new ();
103         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
104         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
105         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
106                                         _("Copyright (c) 2006, Nokia Corporation\n"
107                                           "All rights reserved."));
108         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
109                                        _("a modest e-mail client\n\n"
110                                          "design and implementation: Dirk-Jan C. Binnema\n"
111                                          "contributions from the fine people at KernelConcepts and Igalia\n"
112                                          "uses the tinymail email framework written by Philip van Hoof"));
113         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
114         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
115         
116         gtk_dialog_run (GTK_DIALOG (about));
117         gtk_widget_destroy(about);
118 }
119
120
121 static TnyList *
122 get_selected_headers (ModestWindow *win)
123 {
124         if (MODEST_IS_MAIN_WINDOW(win)) {
125                 GtkWidget *header_view;         
126                 
127                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
128                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
129                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
130                 
131         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
132                 /* for MsgViewWindows, we simply return a list with one element */
133                 TnyMsg *msg;
134                 TnyHeader *header;
135                 TnyList *list = NULL;
136                 
137                 msg  = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
138                 if (msg) {
139                         header = tny_msg_get_header (msg);
140                         list = tny_simple_list_new ();
141                         tny_list_prepend (list, G_OBJECT(header));
142                         g_object_unref (G_OBJECT(header));
143                 }
144                 return list;
145
146         } else
147                 return NULL;
148 }
149
150 void
151 modest_ui_actions_on_delete (GtkAction *action, ModestWindow *win)
152 {
153         TnyList *header_list;
154         TnyIterator *iter;
155
156         g_return_if_fail (MODEST_IS_WINDOW(win));
157                 
158         header_list = get_selected_headers (win);
159         
160         if (header_list) {
161                 iter = tny_list_create_iterator (header_list);
162                 do {
163                         TnyHeader *header;
164                         ModestMailOperation *mail_op;
165
166                         header = TNY_HEADER (tny_iterator_get_current (iter));
167                         /* TODO: thick grain mail operation involving
168                            a list of objects. Composite pattern ??? */
169                         /* TODO: add confirmation dialog */
170                         mail_op = modest_mail_operation_new ();
171                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
172                                                          mail_op);
173
174                         /* Always delete. TODO: Move to trash still not supported */
175                         modest_mail_operation_remove_msg (mail_op, header, FALSE);
176
177                         /* Frees */
178                         g_object_unref (G_OBJECT (mail_op));
179                         g_object_unref (G_OBJECT (header));
180
181                         tny_iterator_next (iter);
182
183                 } while (!tny_iterator_is_done (iter));
184
185                 /* Free iter */
186                 g_object_unref (G_OBJECT (iter));
187         }
188
189         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
190                 gtk_widget_destroy (GTK_WIDGET(win));
191         } 
192 }
193
194
195 void
196 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
197 {
198         gtk_main_quit ();
199 }
200
201 void
202 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
203 {
204         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
205                 gtk_widget_destroy (GTK_WIDGET (win));
206         } else if (MODEST_IS_WINDOW (win)) {
207                 gtk_widget_destroy (GTK_WIDGET (win));
208         } else {
209                 g_return_if_reached ();
210         }
211 }
212
213 void
214 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
215 {
216         GtkClipboard *clipboard = NULL;
217         gchar *selection = NULL;
218
219         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
220         selection = gtk_clipboard_wait_for_text (clipboard);
221
222         modest_address_book_add_address (selection);
223         g_free (selection);
224 }
225
226 void
227 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
228 {
229         
230         /* This is currently only implemented for Maemo,
231          * because it requires a providers preset file which is not publically available.
232          */
233 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
234         GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr());
235         gboolean accounts_exist = account_names != NULL;
236         g_slist_free (account_names);
237         
238 /* To test, while modest_account_mgr_account_names() is broken: accounts_exist = TRUE; */
239         if (!accounts_exist) {
240                 /* If there are no accounts yet, just show the easy-setup wizard, as per the UI spec: */
241                 ModestEasysetupWizardDialog *wizard = modest_easysetup_wizard_dialog_new ();
242                 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
243                 gtk_dialog_run (GTK_DIALOG (wizard));
244                 gtk_widget_destroy (GTK_WIDGET (wizard));
245         } else  {
246                 /* Show the list of accounts: */
247                 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
248                 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW(win));
249                 gtk_dialog_run (account_win);
250                 gtk_widget_destroy (GTK_WIDGET(account_win));
251         }
252 #else
253         GtkWidget *dialog, *label;
254         
255         /* Create the widgets */
256         
257         dialog = gtk_dialog_new_with_buttons ("Message",
258                                               GTK_WINDOW(win),
259                                               GTK_DIALOG_DESTROY_WITH_PARENT,
260                                               GTK_STOCK_OK,
261                                               GTK_RESPONSE_NONE,
262                                               NULL);
263         label = gtk_label_new ("Hello World!");
264         
265         /* Ensure that the dialog box is destroyed when the user responds. */
266         
267         g_signal_connect_swapped (dialog, "response", 
268                                   G_CALLBACK (gtk_widget_destroy),
269                                   dialog);
270         
271         /* Add the label, and show everything we've added to the dialog. */
272         
273         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
274                            label);
275         gtk_widget_show_all (dialog);
276 #endif /* MODEST_PLATFORM_MAEMO */
277 }
278
279 void
280 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
281 {
282         ModestWindow *msg_win;
283         TnyMsg *msg = NULL;
284         TnyFolder *folder = NULL;
285         gchar *account_name = NULL;
286         gchar *from_str = NULL;
287         GError *err = NULL;
288         TnyAccount *account = NULL;
289         ModestWindowMgr *mgr;
290         
291         account_name = g_strdup(modest_window_get_active_account (win));
292         if (!account_name)
293                 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
294         if (!account_name) {
295                 g_printerr ("modest: no account found\n");
296                 goto cleanup;
297         }
298         
299         account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
300                                                                        account_name,
301                                                                        TNY_ACCOUNT_TYPE_STORE);
302         if (!account) {
303                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
304                 goto cleanup;
305         }
306
307         from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
308         if (!from_str) {
309                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
310                 goto cleanup;
311         }
312
313         msg = modest_tny_msg_new ("", from_str, "", "", "", "", NULL);
314         if (!msg) {
315                 g_printerr ("modest: failed to create new msg\n");
316                 goto cleanup;
317         }
318         
319         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
320         if (!folder) {
321                 g_printerr ("modest: failed to find Drafts folder\n");
322                 goto cleanup;
323         }
324         
325         tny_folder_add_msg (folder, msg, &err);
326         if (err) {
327                 g_printerr ("modest: error adding msg to Drafts folder: %s",
328                             err->message);
329                 g_error_free (err);
330                 goto cleanup;
331         }
332
333         /* Create and register edit window */
334         msg_win = modest_msg_edit_window_new (msg, account_name);
335         mgr = modest_runtime_get_window_mgr ();
336         modest_window_mgr_register_window (mgr, msg_win);
337
338         if (win)
339                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
340                                               GTK_WINDOW (win));        
341         gtk_widget_show_all (GTK_WIDGET (msg_win));
342
343 cleanup:
344         g_free (account_name);
345         g_free (from_str);
346         if (account)
347                 g_object_unref (G_OBJECT(account));
348         if (msg)
349                 g_object_unref (G_OBJECT(msg));
350         if (folder)
351                 g_object_unref (G_OBJECT(folder));
352 }
353
354
355 void
356 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
357 {
358         modest_runtime_not_implemented (GTK_WINDOW(win)); /* FIXME */
359 }
360
361
362
363 static void
364 reply_forward_func (gpointer data, gpointer user_data)
365 {
366         TnyMsg *msg, *new_msg;
367         GetMsgAsyncHelper *helper;
368         ReplyForwardHelper *rf_helper;
369         ModestWindow *msg_win;
370         ModestEditType edit_type;
371         gchar *from;
372         GError *err = NULL;
373         TnyFolder *folder = NULL;
374         TnyAccount *account = NULL;
375         ModestWindowMgr *mgr;
376         
377         msg = TNY_MSG (data);
378         helper = (GetMsgAsyncHelper *) user_data;
379         rf_helper = (ReplyForwardHelper *) helper->user_data;
380
381         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
382                                                    rf_helper->account_name);
383         /* Create reply mail */
384         switch (rf_helper->action) {
385         case ACTION_REPLY:
386                 new_msg = 
387                         modest_tny_msg_create_reply_msg (msg,  from, 
388                                                          rf_helper->reply_forward_type,
389                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
390                 break;
391         case ACTION_REPLY_TO_ALL:
392                 new_msg = 
393                         modest_tny_msg_create_reply_msg (msg, from, rf_helper->reply_forward_type,
394                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
395                 edit_type = MODEST_EDIT_TYPE_REPLY;
396                 break;
397         case ACTION_FORWARD:
398                 new_msg = 
399                         modest_tny_msg_create_forward_msg (msg, from, rf_helper->reply_forward_type);
400                 edit_type = MODEST_EDIT_TYPE_FORWARD;
401                 break;
402         default:
403                 g_return_if_reached ();
404                 return;
405         }
406
407         if (!new_msg) {
408                 g_printerr ("modest: failed to create message\n");
409                 goto cleanup;
410         }
411
412         account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
413                                                                        rf_helper->account_name,
414                                                                        TNY_ACCOUNT_TYPE_STORE);
415         if (!account) {
416                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
417                 goto cleanup;
418         }
419
420         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
421         if (!folder) {
422                 g_printerr ("modest: failed to find Drafts folder\n");
423                 goto cleanup;
424         }
425         
426         tny_folder_add_msg (folder, msg, &err);
427         if (err) {
428                 g_printerr ("modest: error adding msg to Drafts folder: %s",
429                             err->message);
430                 g_error_free (err);
431                 goto cleanup;
432         }       
433
434         /* Create and register the windows */                   
435         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
436         mgr = modest_runtime_get_window_mgr ();
437         modest_window_mgr_register_window (mgr, msg_win);
438
439         /* Show edit window */
440         gtk_widget_show_all (GTK_WIDGET (msg_win));
441
442 cleanup:
443         if (new_msg)
444                 g_object_unref (G_OBJECT (new_msg));
445         if (folder)
446                 g_object_unref (G_OBJECT (folder));
447         if (account)
448                 g_object_unref (G_OBJECT (account));
449         
450         g_free (rf_helper->account_name);
451         g_slice_free (ReplyForwardHelper, rf_helper);
452 }
453 /*
454  * Common code for the reply and forward actions
455  */
456 static void
457 reply_forward (ReplyForwardAction action, ModestWindow *win)
458 {
459         TnyList *header_list;
460         guint reply_forward_type;
461         TnyHeader *header;
462         TnyFolder *folder;
463         GetMsgAsyncHelper *helper;
464         ReplyForwardHelper *rf_helper;
465         
466         g_return_if_fail (MODEST_IS_WINDOW(win));
467
468         header_list = get_selected_headers (win);
469         if (!header_list)
470                 return;
471         
472         reply_forward_type = modest_conf_get_int (modest_runtime_get_conf (),
473                                                   (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
474                                                   NULL);
475         /* We assume that we can only select messages of the
476            same folder and that we reply all of them from the
477            same account. In fact the interface currently only
478            allows single selection */
479         
480         /* Fill helpers */
481         rf_helper = g_slice_new0 (ReplyForwardHelper);
482         rf_helper->reply_forward_type = reply_forward_type;
483         rf_helper->action = action;
484
485         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
486         if (!rf_helper->account_name)
487                 rf_helper->account_name =
488                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
489
490         helper = g_slice_new0 (GetMsgAsyncHelper);
491         helper->window = win;
492         helper->func = reply_forward_func;
493         helper->iter = tny_list_create_iterator (header_list);
494         helper->user_data = rf_helper;
495
496         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
497                 TnyMsg *msg;
498                 msg = modest_msg_view_window_get_message(MODEST_MSG_VIEW_WINDOW(win));
499                 if (!msg) {
500                         g_printerr ("modest: no message found\n");
501                         return;
502                 } else
503                         reply_forward_func (msg, helper);
504         } else {
505                 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
506                 folder = tny_header_get_folder (header);
507                 if (folder) {
508                         /* The callback will call it per each header */
509                         tny_folder_get_msg_async (folder, header, get_msg_cb, NULL, helper);
510                         g_object_unref (G_OBJECT (folder));
511                 } else 
512                         g_printerr ("modest: no folder for header\n");
513                 
514                 /* Clean */
515                 g_object_unref (G_OBJECT (header));
516         }
517 }
518
519
520 void
521 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
522 {
523         g_return_if_fail (MODEST_IS_WINDOW(win));
524
525         reply_forward (ACTION_REPLY, win);
526 }
527
528 void
529 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
530 {
531         g_return_if_fail (MODEST_IS_WINDOW(win));
532
533         reply_forward (ACTION_FORWARD, win);
534 }
535
536 void
537 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
538 {
539         g_return_if_fail (MODEST_IS_WINDOW(win));
540
541         reply_forward (ACTION_REPLY_TO_ALL, win);
542 }
543
544 void 
545 modest_ui_actions_on_next (GtkAction *action, 
546                            ModestWindow *window)
547 {
548         if (MODEST_IS_MAIN_WINDOW (window)) {
549                 GtkWidget *header_view;
550
551                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
552                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
553                 if (!header_view)
554                         return;
555         
556                 modest_header_view_select_next (MODEST_HEADER_VIEW(header_view)); 
557         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
558                 modest_msg_view_window_select_next_message (MODEST_MSG_VIEW_WINDOW (window));
559         } else {
560                 g_return_if_reached ();
561         }
562 }
563
564 void 
565 modest_ui_actions_on_prev (GtkAction *action, 
566                            ModestWindow *window)
567 {
568         g_return_if_fail (MODEST_IS_WINDOW(window));
569
570         if (MODEST_IS_MAIN_WINDOW (window)) {
571                 GtkWidget *header_view;
572                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
573                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
574                 if (!header_view)
575                         return;
576                 
577                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
578         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
579                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
580         } else {
581                 g_return_if_reached ();
582         }
583 }
584
585 void 
586 modest_ui_actions_on_sort (GtkAction *action, 
587                            ModestWindow *window)
588 {
589         g_return_if_fail (MODEST_IS_WINDOW(window));
590         /* FIXME: unimplemented */
591 }
592
593
594 static gboolean
595 action_send (const gchar* account_name)
596 {
597         TnyAccount *tny_account;
598         ModestTnySendQueue *send_queue;
599
600         g_return_val_if_fail (account_name, FALSE);
601
602         tny_account = 
603                 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
604                                                                      account_name,
605                                                                      TNY_ACCOUNT_TYPE_TRANSPORT);
606         if (!tny_account) {
607                 g_printerr ("modest: cannot get tny transport account for %s\n", account_name);
608                 return FALSE;
609         }
610         send_queue = modest_tny_send_queue_new (TNY_CAMEL_TRANSPORT_ACCOUNT(tny_account));
611         if (!send_queue) {
612                 g_object_unref (G_OBJECT(tny_account));
613                 g_printerr ("modest: cannot get send queue for %s\n", account_name);
614                 return FALSE;
615         }
616         
617         //modest_tny_send_queue_flush (send_queue);
618
619         g_object_unref (G_OBJECT(send_queue));
620         g_object_unref (G_OBJECT(tny_account));
621
622         return TRUE;
623 }
624
625
626 static gboolean
627 action_receive (const gchar* account_name)
628 {
629         TnyAccount *tny_account;
630         ModestMailOperation *mail_op;
631
632         g_return_val_if_fail (account_name, FALSE);
633
634         tny_account = 
635                 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
636                                                                      account_name,
637                                                                      TNY_ACCOUNT_TYPE_STORE);
638         if (!tny_account) {
639                 g_printerr ("modest: cannot get tny store account for %s\n", account_name);
640                 return FALSE;
641         }
642
643         /* Create the mail operation */
644         mail_op = modest_mail_operation_new ();
645         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
646         modest_mail_operation_update_account (mail_op, TNY_STORE_ACCOUNT(tny_account));
647
648         g_object_unref (G_OBJECT(tny_account));
649         g_object_unref (G_OBJECT (mail_op));
650                 
651         return TRUE;
652 }
653
654
655
656 void
657 modest_ui_actions_on_send_receive (GtkAction *action,  ModestWindow *win)
658 {
659         gchar *account_name;
660
661         
662         g_message ("online? %s", 
663                 tny_device_is_online(modest_runtime_get_device()) ? "yes":"no");
664                                                                 
665         account_name =
666                 g_strdup(modest_window_get_active_account(MODEST_WINDOW(win)));
667         if (!account_name)
668                 account_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
669         if (!account_name) {
670                 g_printerr ("modest: cannot get account\n");
671                 return;
672         }
673
674         if (!action_send(account_name))
675                 g_printerr ("modest: failed to send\n");
676         if (!action_receive(account_name))
677                 g_printerr ("modest: failed to receive\n");
678 }
679
680
681
682 void
683 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
684 {
685         ModestConf *conf;
686         GtkWidget *header_view;
687         
688         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
689
690         header_view = modest_main_window_get_child_widget (main_window,
691                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
692         if (!header_view)
693                 return;
694
695         conf = modest_runtime_get_conf ();
696         
697         /* what is saved/restored is depending on the style; thus; we save with
698          * old style, then update the style, and restore for this new style
699          */
700         modest_widget_memory_save (conf, G_OBJECT(header_view), "header-view");
701         
702         if (modest_header_view_get_style
703             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
704                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
705                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
706         else
707                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
708                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
709
710         modest_widget_memory_restore (conf, G_OBJECT(header_view),
711                                       "header-view");
712 }
713
714
715
716 /*
717  * Marks a message as read and passes it to the msg preview widget
718  */
719 static void
720 read_msg_func (gpointer data, gpointer user_data)
721 {
722         TnyMsg *msg;
723         TnyHeader *header;
724         GetMsgAsyncHelper *helper;
725         TnyHeaderFlags header_flags;
726         GtkWidget *msg_preview;
727         
728         msg = TNY_MSG (data);
729         helper = (GetMsgAsyncHelper *) user_data;
730
731         msg_preview = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (helper->window),
732                                                            MODEST_WIDGET_TYPE_MSG_PREVIEW);
733         if (!msg_preview)
734                 return;
735         
736         header = TNY_HEADER (tny_iterator_get_current (helper->iter));
737         header_flags = tny_header_get_flags (header);
738         tny_header_set_flags (header, header_flags | TNY_HEADER_FLAG_SEEN);
739         g_object_unref (G_OBJECT (header));
740
741         /* Set message on msg view */
742         modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), msg);
743 }
744
745 /*
746  * This function is a generic handler for the tny_folder_get_msg_async
747  * call. It expects as user_data a #GetMsgAsyncHelper. This helper
748  * contains a user provided function that is called inside this
749  * method. This will allow us to use this callback in many different
750  * places. This callback performs the common actions for the
751  * get_msg_async call, more specific actions will be done by the user
752  * function
753  */
754 static void
755 get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
756 {
757         GetMsgAsyncHelper *helper;
758
759         helper = (GetMsgAsyncHelper *) user_data;
760
761         if ((*err && ((*err)->code == TNY_FOLDER_ERROR_GET_MSG)) || !msg) {
762                 modest_ui_actions_on_item_not_found (NULL,
763                                                      MODEST_ITEM_TYPE_MESSAGE,
764                                                      helper->window);
765                 return;
766         }
767
768         /* Call user function */
769         helper->func (msg, user_data);
770
771         /* Process next element (if exists) */
772         tny_iterator_next (helper->iter);
773         if (tny_iterator_is_done (helper->iter)) {
774                 TnyList *headers;
775                 headers = tny_iterator_get_list (helper->iter);
776                 /* Free resources */
777                 g_object_unref (G_OBJECT (headers));
778                 g_object_unref (G_OBJECT (helper->iter));
779                 g_slice_free (GetMsgAsyncHelper, helper);
780         } else {
781                 TnyHeader *header;
782                 header = TNY_HEADER (tny_iterator_get_current (helper->iter)); 
783                 tny_folder_get_msg_async (folder, header,                         
784                                           get_msg_cb, NULL, helper);
785                 g_object_unref (G_OBJECT(header));
786         }
787 }
788
789 void 
790 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
791                                       TnyHeader *header,
792                                       ModestMainWindow *main_window)
793 {
794         TnyFolder *folder;
795         GetMsgAsyncHelper *helper;
796         TnyList *list;
797
798         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
799
800         /* when there's no header, clear the msgview */
801         if (!header) {
802                 GtkWidget *msg_preview;
803
804                 /* Clear msg preview if exists */
805                 msg_preview = modest_main_window_get_child_widget(main_window,
806                                                                   MODEST_WIDGET_TYPE_MSG_PREVIEW);
807         
808                 if (msg_preview)
809                         modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), NULL);
810                 return;
811         }
812
813         /* Update Main window title */
814         if (GTK_WIDGET_HAS_FOCUS (header_view)) {
815                 const gchar *subject = tny_header_get_subject (header);
816                 if (subject && strcmp (subject, ""))
817                         gtk_window_set_title (GTK_WINDOW (main_window), subject);
818                 else
819                         gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
820         }
821
822         /* Create list */
823         list = tny_simple_list_new ();
824         tny_list_prepend (list, G_OBJECT (header));
825
826         /* Fill helper data */
827         helper = g_slice_new0 (GetMsgAsyncHelper);
828         helper->window = MODEST_WINDOW (main_window);
829         helper->iter = tny_list_create_iterator (list);
830         helper->func = read_msg_func;
831
832         folder = tny_header_get_folder (TNY_HEADER(header));
833
834         tny_folder_get_msg_async (TNY_FOLDER(folder),
835                                   header, get_msg_cb,
836                                   NULL, helper);
837
838         /* Frees */
839         g_object_unref (G_OBJECT (folder));
840 }
841
842
843
844 void 
845 modest_ui_actions_on_header_activated (ModestHeaderView *folder_view, TnyHeader *header,
846                                        ModestMainWindow *main_window)
847 {
848         ModestWindow *win = NULL;
849         TnyFolder *folder = NULL;
850         TnyMsg    *msg    = NULL;
851         ModestWindowMgr *mgr;
852         
853         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
854         
855         if (!header)
856                 return;
857
858         folder = tny_header_get_folder (header);
859         if (!folder) {
860                 g_printerr ("modest: cannot get folder for header\n");
861                 return;
862         }
863
864         /* FIXME: make async?; check error  */
865         msg = tny_folder_get_msg (folder, header, NULL);
866         if (!msg) {
867                 g_printerr ("modest: cannot get msg for header\n");
868                 goto cleanup;
869         }
870
871         /* Look if we already have a message view for that header */    
872         mgr = modest_runtime_get_window_mgr ();
873         win = modest_window_mgr_find_window_by_msguid (mgr, tny_header_get_uid (header));
874
875         /* If not, create a new window */
876         if (!win) {
877                 gchar *account;
878
879                 account =  g_strdup(modest_window_get_active_account(MODEST_WINDOW(main_window)));
880                 if (!account)
881                         account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
882
883                 win = modest_msg_view_window_new (msg, account);
884                 modest_window_mgr_register_window (mgr, win);
885
886                 gtk_window_set_transient_for (GTK_WINDOW (win),
887                                               GTK_WINDOW (main_window));
888         }
889
890         gtk_widget_show_all (GTK_WIDGET(win));
891
892         g_object_unref (G_OBJECT (msg));
893         
894 cleanup:
895         g_object_unref (G_OBJECT (folder));
896 }
897
898 void 
899 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
900                                                TnyFolderStore *folder_store, 
901                                                gboolean selected,
902                                                ModestMainWindow *main_window)
903 {
904         ModestConf *conf;
905         GtkWidget *header_view;
906         
907         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
908
909         header_view = modest_main_window_get_child_widget(main_window,
910                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
911         if (!header_view)
912                 return;
913         
914         conf = modest_runtime_get_conf ();
915
916         if (TNY_IS_FOLDER (folder_store)) {
917
918                 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
919
920                 if (selected) {
921                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), 
922                                                        TNY_FOLDER (folder_store));
923                         modest_widget_memory_restore (conf, G_OBJECT(header_view),
924                                                       "header-view");
925                 } else {
926                         modest_widget_memory_save (conf, G_OBJECT (header_view), "header-view");
927                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
928                 }
929         } else if (TNY_IS_ACCOUNT (folder_store)) {
930
931                 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
932         }
933 }
934
935 void 
936 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
937                                      ModestWindow *win)
938 {
939         GtkWidget *dialog;
940         gchar *txt, *item;
941         gboolean online;
942
943         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
944         
945         if (g_main_depth > 0)   
946                 gdk_threads_enter ();
947         online = tny_device_is_online (modest_runtime_get_device());
948
949         if (online) {
950                 /* already online -- the item is simply not there... */
951                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
952                                                  GTK_DIALOG_MODAL,
953                                                  GTK_MESSAGE_WARNING,
954                                                  GTK_BUTTONS_OK,
955                                                  _("The %s you selected cannot be found"),
956                                                  item);
957                 gtk_dialog_run (GTK_DIALOG(dialog));
958         } else {
959                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
960                                                       GTK_WINDOW (win),
961                                                       GTK_DIALOG_MODAL,
962                                                       GTK_STOCK_CANCEL,
963                                                       GTK_RESPONSE_REJECT,
964                                                       GTK_STOCK_OK,
965                                                       GTK_RESPONSE_ACCEPT,
966                                                       NULL);
967                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
968                                          "Do you want to get online?"), item);
969                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
970                                     gtk_label_new (txt), FALSE, FALSE, 0);
971                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
972                 g_free (txt);
973
974                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
975                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
976 //                      tny_device_force_online (modest_runtime_get_device());
977                 }
978         }
979         gtk_widget_destroy (dialog);
980         if (g_main_depth > 0)   
981                 gdk_threads_leave ();
982 }
983
984 void
985 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
986                                      ModestWindow *win)
987 {
988         g_message ("%s %s", __FUNCTION__, link);
989 }       
990
991
992 void
993 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
994                                         ModestWindow *win)
995 {
996         modest_platform_activate_uri (link);
997 }
998
999 void
1000 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1001                                           ModestWindow *win)
1002 {
1003         modest_platform_show_uri_popup (link);
1004 }
1005
1006 void
1007 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1008                                              ModestWindow *win)
1009 {
1010         g_message (__FUNCTION__);
1011         
1012 }
1013
1014 void
1015 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1016                                           const gchar *address,
1017                                           ModestWindow *win)
1018 {
1019         g_message ("%s %s", __FUNCTION__, address);
1020 }
1021
1022 void
1023 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1024 {
1025         TnyTransportAccount *transport_account;
1026         ModestMailOperation *mail_operation;
1027         MsgData *data;
1028         gchar *account_name, *from;
1029         ModestAccountMgr *account_mgr;
1030
1031         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1032         
1033         data = modest_msg_edit_window_get_msg_data (edit_window);
1034
1035         /* FIXME: Code added just for testing. The final version will
1036            use the send queue provided by tinymail and some
1037            classifier */
1038         account_mgr = modest_runtime_get_account_mgr();
1039         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1040         if (!account_name) 
1041                 account_name = modest_account_mgr_get_default_account (account_mgr);
1042         if (!account_name) {
1043                 g_printerr ("modest: no account found\n");
1044                 modest_msg_edit_window_free_msg_data (edit_window, data);
1045                 return;
1046         }
1047         transport_account =
1048                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
1049                                       (modest_runtime_get_account_store(),
1050                                        account_name,
1051                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1052         if (!transport_account) {
1053                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1054                 g_free (account_name);
1055                 modest_msg_edit_window_free_msg_data (edit_window, data);
1056                 return;
1057         }
1058         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1059
1060         /* Create the mail operation */         
1061         mail_operation = modest_mail_operation_new ();
1062         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1063
1064         modest_mail_operation_send_new_mail (mail_operation,
1065                                              transport_account,
1066                                              from,
1067                                              data->to, 
1068                                              data->cc, 
1069                                              data->bcc,
1070                                              data->subject, 
1071                                              data->plain_body, 
1072                                              data->html_body,
1073                                              data->attachments,
1074                                              data->priority_flags);
1075         /* Frees */
1076         g_free (from);
1077         g_free (account_name);
1078         g_object_unref (G_OBJECT (transport_account));
1079         g_object_unref (G_OBJECT (mail_operation));
1080
1081         modest_msg_edit_window_free_msg_data (edit_window, data);
1082
1083         /* Save settings and close the window */
1084         gtk_widget_destroy (GTK_WIDGET (edit_window));
1085 }
1086
1087 void 
1088 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1089                                   ModestMsgEditWindow *window)
1090 {
1091         ModestMsgEditFormatState *format_state = NULL;
1092
1093         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1094         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1095
1096         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1097                 return;
1098
1099         format_state = modest_msg_edit_window_get_format_state (window);
1100         g_return_if_fail (format_state != NULL);
1101
1102         format_state->bold = gtk_toggle_action_get_active (action);
1103         modest_msg_edit_window_set_format_state (window, format_state);
1104         g_free (format_state);
1105         
1106 }
1107
1108 void 
1109 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1110                                      ModestMsgEditWindow *window)
1111 {
1112         ModestMsgEditFormatState *format_state = NULL;
1113
1114         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1115         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1116
1117         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1118                 return;
1119
1120         format_state = modest_msg_edit_window_get_format_state (window);
1121         g_return_if_fail (format_state != NULL);
1122
1123         format_state->italics = gtk_toggle_action_get_active (action);
1124         modest_msg_edit_window_set_format_state (window, format_state);
1125         g_free (format_state);
1126         
1127 }
1128
1129 void 
1130 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
1131                                      ModestMsgEditWindow *window)
1132 {
1133         ModestMsgEditFormatState *format_state = NULL;
1134
1135         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1136         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1137
1138         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1139                 return;
1140
1141         format_state = modest_msg_edit_window_get_format_state (window);
1142         g_return_if_fail (format_state != NULL);
1143
1144         format_state->bullet = gtk_toggle_action_get_active (action);
1145         modest_msg_edit_window_set_format_state (window, format_state);
1146         g_free (format_state);
1147         
1148 }
1149
1150 void 
1151 modest_ui_actions_on_change_justify (GtkRadioAction *action,
1152                                      GtkRadioAction *selected,
1153                                      ModestMsgEditWindow *window)
1154 {
1155         ModestMsgEditFormatState *format_state = NULL;
1156         GtkJustification value;
1157
1158         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1159
1160         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1161                 return;
1162
1163         value = gtk_radio_action_get_current_value (selected);
1164
1165         format_state = modest_msg_edit_window_get_format_state (window);
1166         g_return_if_fail (format_state != NULL);
1167
1168         format_state->justification = value;
1169         modest_msg_edit_window_set_format_state (window, format_state);
1170         g_free (format_state);
1171 }
1172
1173 void 
1174 modest_ui_actions_on_select_editor_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_color (window);
1184 }
1185
1186 void 
1187 modest_ui_actions_on_select_editor_background_color (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_select_background_color (window);
1197 }
1198
1199 void 
1200 modest_ui_actions_on_insert_image (GtkAction *action,
1201                                    ModestMsgEditWindow *window)
1202 {
1203         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1204         g_return_if_fail (GTK_IS_ACTION (action));
1205
1206         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1207                 return;
1208
1209         modest_msg_edit_window_insert_image (window);
1210 }
1211
1212 /*
1213  * Shows a dialog with an entry that asks for some text. The returned
1214  * value must be freed by the caller. The dialog window title will be
1215  * set to @title.
1216  */
1217 static gchar *
1218 ask_for_folder_name (GtkWindow *parent_window,
1219                      const gchar *title)
1220 {
1221         GtkWidget *dialog, *entry;
1222         gchar *folder_name = NULL;
1223
1224         /* Ask for folder name */
1225         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1226                                               parent_window,
1227                                               GTK_DIALOG_MODAL,
1228                                               GTK_STOCK_CANCEL,
1229                                               GTK_RESPONSE_REJECT,
1230                                               GTK_STOCK_OK,
1231                                               GTK_RESPONSE_ACCEPT,
1232                                               NULL);
1233         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1234                             gtk_label_new(title),
1235                             FALSE, FALSE, 0);
1236                 
1237         entry = gtk_entry_new_with_max_length (40);
1238         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1239                             entry,
1240                             TRUE, FALSE, 0);    
1241         
1242         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1243         
1244         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
1245                 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1246
1247         gtk_widget_destroy (dialog);
1248
1249         return folder_name;
1250 }
1251
1252 void 
1253 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1254 {
1255         TnyFolderStore *parent_folder;
1256         GtkWidget *folder_view;
1257         
1258         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1259
1260         folder_view = modest_main_window_get_child_widget (main_window,
1261                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1262         if (!folder_view)
1263                 return;
1264
1265         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1266         
1267         if (parent_folder) {
1268                 gchar *folder_name;
1269
1270                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1271                                                    _("Please enter a name for the new folder"));
1272
1273                 if (folder_name != NULL && strlen (folder_name) > 0) {
1274                         TnyFolder *new_folder;
1275                         ModestMailOperation *mail_op;
1276
1277                         mail_op = modest_mail_operation_new ();
1278                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
1279                                                          mail_op);
1280
1281                         new_folder = modest_mail_operation_create_folder (mail_op,
1282                                                                           parent_folder,
1283                                                                           (const gchar *) folder_name);
1284                         if (new_folder) 
1285                                 g_object_unref (new_folder);
1286                         g_object_unref (mail_op);
1287                         g_free (folder_name);
1288                 }
1289                 g_object_unref (parent_folder);
1290         }
1291 }
1292
1293 void 
1294 modest_ui_actions_on_rename_folder (GtkAction *action,
1295                                      ModestMainWindow *main_window)
1296 {
1297         TnyFolderStore *folder;
1298         GtkWidget *folder_view;
1299         
1300         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1301
1302         folder_view = modest_main_window_get_child_widget (main_window,
1303                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1304         if (!folder_view)
1305                 return;
1306         
1307         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1308         
1309         if (folder && TNY_IS_FOLDER (folder)) {
1310                 gchar *folder_name;
1311                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1312                                                    _("Please enter a new name for the folder"));
1313
1314                 if (folder_name != NULL && strlen (folder_name) > 0) {
1315                         ModestMailOperation *mail_op;
1316
1317                         mail_op = modest_mail_operation_new ();
1318                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1319                                                          mail_op);
1320
1321                         modest_mail_operation_rename_folder (mail_op,
1322                                                              TNY_FOLDER (folder),
1323                                                              (const gchar *) folder_name);
1324
1325                         g_object_unref (mail_op);
1326                         g_free (folder_name);
1327                 }
1328                 g_object_unref (folder);
1329         }
1330 }
1331
1332 static void
1333 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
1334 {
1335         TnyFolderStore *folder;
1336         ModestMailOperation *mail_op;
1337         GtkWidget *folder_view;
1338         
1339         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1340
1341         folder_view = modest_main_window_get_child_widget (main_window,
1342                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1343         if (!folder_view)
1344                 return;
1345
1346         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1347         
1348         mail_op = modest_mail_operation_new ();
1349         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1350                                          mail_op);
1351         modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
1352
1353         g_object_unref (G_OBJECT (mail_op));
1354         g_object_unref (G_OBJECT (folder));
1355 }
1356
1357 void 
1358 modest_ui_actions_on_delete_folder (GtkAction *action,
1359                                      ModestMainWindow *main_window)
1360 {
1361         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1362
1363         delete_folder (main_window, FALSE);
1364 }
1365
1366 void 
1367 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1368 {
1369         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1370         
1371         delete_folder (main_window, TRUE);
1372 }
1373
1374 void
1375 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
1376                                          const gchar* account_name,
1377                                          gchar **password, 
1378                                          gboolean *cancel, 
1379                                          gboolean *remember,
1380                                          ModestMainWindow *main_window)
1381 {
1382         gchar *txt;
1383         GtkWidget *dialog, *entry, *remember_pass_check;
1384
1385         dialog = gtk_dialog_new_with_buttons (_("Password requested"),
1386                                               NULL,
1387                                               GTK_DIALOG_MODAL,
1388                                               GTK_STOCK_CANCEL,
1389                                               GTK_RESPONSE_REJECT,
1390                                               GTK_STOCK_OK,
1391                                               GTK_RESPONSE_ACCEPT,
1392                                               NULL);
1393         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1394         
1395         txt = g_strdup_printf (_("Please enter your password for %s"), account_name);
1396         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1397                             FALSE, FALSE, 0);
1398         g_free (txt);
1399
1400         entry = gtk_entry_new_with_max_length (40);
1401         gtk_entry_set_visibility (GTK_ENTRY(entry), FALSE);
1402         gtk_entry_set_invisible_char (GTK_ENTRY(entry), 0x2022); /* bullet unichar */
1403         
1404         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry,
1405                             TRUE, FALSE, 0);    
1406
1407         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1408         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1409                             TRUE, FALSE, 0);
1410
1411         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1412         
1413         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1414                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry)));
1415                 *cancel   = FALSE;
1416         } else {
1417                 *password = NULL;
1418                 *cancel   = TRUE;
1419         }
1420
1421         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
1422                 *remember = TRUE;
1423         else
1424                 *remember = FALSE;
1425
1426         gtk_widget_destroy (dialog);
1427 }
1428
1429 void
1430 modest_ui_actions_on_cut (GtkAction *action,
1431                           ModestWindow *window)
1432 {
1433         GtkWidget *focused_widget;
1434
1435         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1436         if (GTK_IS_EDITABLE (focused_widget)) {
1437                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
1438         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1439                 GtkTextBuffer *buffer;
1440                 GtkClipboard *clipboard;
1441
1442                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1443                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1444                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
1445         }
1446 }
1447
1448 void
1449 modest_ui_actions_on_copy (GtkAction *action,
1450                            ModestWindow *window)
1451 {
1452         GtkClipboard *clipboard;
1453         GtkWidget *focused_widget;
1454
1455         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1456         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1457         if (GTK_IS_LABEL (focused_widget)) {
1458                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
1459         } else if (GTK_IS_EDITABLE (focused_widget)) {
1460                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
1461         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1462                 GtkTextBuffer *buffer;
1463
1464                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1465                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
1466         }
1467 }
1468
1469 void
1470 modest_ui_actions_on_undo (GtkAction *action,
1471                            ModestWindow *window)
1472 {
1473         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
1474                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
1475         } else {
1476                 g_return_if_reached ();
1477         }
1478 }
1479
1480 void
1481 modest_ui_actions_on_paste (GtkAction *action,
1482                             ModestWindow *window)
1483 {
1484         GtkWidget *focused_widget;
1485
1486         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1487         if (GTK_IS_EDITABLE (focused_widget)) {
1488                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
1489         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1490                 GtkTextBuffer *buffer;
1491                 GtkClipboard *clipboard;
1492
1493                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1494                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1495                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
1496         }
1497 }
1498
1499 void
1500 modest_ui_actions_on_select_all (GtkAction *action,
1501                                  ModestWindow *window)
1502 {
1503         GtkWidget *focused_widget;
1504
1505         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1506         if (GTK_IS_LABEL (focused_widget)) {
1507                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
1508         } else if (GTK_IS_EDITABLE (focused_widget)) {
1509                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
1510         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1511                 GtkTextBuffer *buffer;
1512                 GtkTextIter start, end;
1513
1514                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1515                 gtk_text_buffer_get_start_iter (buffer, &start);
1516                 gtk_text_buffer_get_end_iter (buffer, &end);
1517                 gtk_text_buffer_select_range (buffer, &start, &end);
1518         }
1519 }
1520
1521 void
1522 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
1523                                   GtkRadioAction *selected,
1524                                   ModestWindow *window)
1525 {
1526         gint value;
1527
1528         value = gtk_radio_action_get_current_value (selected);
1529         if (MODEST_IS_WINDOW (window)) {
1530                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
1531         }
1532 }
1533
1534 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
1535                                                         GtkRadioAction *selected,
1536                                                         ModestWindow *window)
1537 {
1538         TnyHeaderFlags flags;
1539         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1540
1541         flags = gtk_radio_action_get_current_value (selected);
1542         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
1543 }
1544
1545 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
1546                                                            GtkRadioAction *selected,
1547                                                            ModestWindow *window)
1548 {
1549         gint file_format;
1550
1551         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1552
1553         file_format = gtk_radio_action_get_current_value (selected);
1554         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
1555 }
1556
1557
1558 void     
1559 modest_ui_actions_on_zoom_plus (GtkAction *action,
1560                                 ModestWindow *window)
1561 {
1562         g_return_if_fail (MODEST_IS_WINDOW (window));
1563
1564         modest_window_zoom_plus (MODEST_WINDOW (window));
1565 }
1566
1567 void     
1568 modest_ui_actions_on_zoom_minus (GtkAction *action,
1569                                  ModestWindow *window)
1570 {
1571         g_return_if_fail (MODEST_IS_WINDOW (window));
1572
1573         modest_window_zoom_minus (MODEST_WINDOW (window));
1574 }
1575
1576 void     
1577 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
1578                                            ModestWindow *window)
1579 {
1580         ModestWindowMgr *mgr;
1581         gboolean fullscreen, active;
1582         g_return_if_fail (MODEST_IS_WINDOW (window));
1583
1584         mgr = modest_runtime_get_window_mgr ();
1585
1586         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
1587         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1588
1589         if (active != fullscreen) {
1590                 modest_window_mgr_set_fullscreen_mode (mgr, active);
1591                 gtk_window_present (GTK_WINDOW (window));
1592         }
1593 }
1594
1595 void
1596 modest_ui_actions_on_change_fullscreen (GtkAction *action,
1597                                         ModestWindow *window)
1598 {
1599         ModestWindowMgr *mgr;
1600         gboolean fullscreen;
1601
1602         g_return_if_fail (MODEST_IS_WINDOW (window));
1603
1604         mgr = modest_runtime_get_window_mgr ();
1605         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1606         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
1607
1608         gtk_window_present (GTK_WINDOW (window));
1609 }
1610
1611 static void
1612 show_header_details (TnyHeader *header, 
1613                      GtkWindow *window)
1614 {
1615         GtkWidget *dialog;
1616         
1617         dialog = modest_msg_view_details_dialog_new (window, header);
1618         g_object_unref (header);
1619         gtk_widget_show_all (dialog);
1620
1621         gtk_dialog_run (GTK_DIALOG (dialog));
1622
1623         gtk_widget_destroy (dialog);
1624 }
1625
1626 void     
1627 modest_ui_actions_on_details (GtkAction *action, 
1628                               ModestWindow *win)
1629 {
1630         TnyList * headers_list;
1631         TnyIterator *iter;
1632         TnyHeader *header;              
1633
1634         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1635                 TnyMsg *msg;
1636
1637                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
1638                 if (!msg) {
1639                         return;
1640                 } else {
1641                         headers_list = get_selected_headers (win);
1642                         if (!headers_list)
1643                                 return;
1644
1645                         iter = tny_list_create_iterator (headers_list);
1646
1647                         header = TNY_HEADER (tny_iterator_get_current (iter));
1648                         show_header_details (header, GTK_WINDOW (win));
1649                         g_object_unref (header);
1650
1651                         g_object_unref (iter);
1652                 }
1653         } else if (MODEST_IS_MAIN_WINDOW (win)) {
1654                 GtkWidget *folder_view, *header_view;
1655
1656                 /* Check which widget has the focus */
1657                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1658                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
1659                 if (gtk_widget_is_focus (folder_view)) {
1660                         TnyFolder *folder;
1661
1662                         folder = TNY_FOLDER (modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view)));
1663
1664                         /* Show only when it's a folder */
1665                         if (!folder || !TNY_IS_FOLDER (folder))
1666                                 return;
1667
1668                         /* TODO */
1669                 } else {
1670                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1671                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1672                         if (!gtk_widget_is_focus (header_view))
1673                                 return;
1674
1675                         headers_list = get_selected_headers (win);
1676                         if (!headers_list)
1677                                 return;
1678
1679                         iter = tny_list_create_iterator (headers_list);
1680                         while (!tny_iterator_is_done (iter)) {
1681
1682                                 header = TNY_HEADER (tny_iterator_get_current (iter));
1683                                 show_header_details (header, GTK_WINDOW (win));
1684                                 g_object_unref (header);
1685
1686                                 tny_iterator_next (iter);
1687                         }
1688                         g_object_unref (iter);
1689                 }
1690         }
1691 }
1692
1693 void     
1694 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
1695                                      ModestMsgEditWindow *window)
1696 {
1697         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1698
1699         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
1700 }
1701
1702 void     
1703 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
1704                                       ModestMsgEditWindow *window)
1705 {
1706         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1707
1708         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
1709 }
1710
1711 void
1712 modest_ui_actions_toggle_folders_view (GtkAction *action, 
1713                                        ModestMainWindow *main_window)
1714 {
1715         ModestConf *conf;
1716         
1717         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1718
1719         conf = modest_runtime_get_conf ();
1720         
1721         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
1722                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
1723         else
1724                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
1725 }
1726
1727 void 
1728 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
1729                                      ModestWindow *window)
1730 {
1731         gboolean active, fullscreen = FALSE;
1732         ModestWindowMgr *mgr;
1733
1734         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
1735
1736         /* Check if we want to toggle the toolbar vuew in fullscreen
1737            or normal mode */
1738         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
1739                      "ViewShowToolbarFullScreen")) {
1740                 fullscreen = TRUE;
1741         }
1742
1743         /* Toggle toolbar */
1744         mgr = modest_runtime_get_window_mgr ();
1745         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
1746 }
1747
1748 void     
1749 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
1750                                            ModestMsgEditWindow *window)
1751 {
1752         modest_msg_edit_window_select_font (window);
1753 }
1754
1755 void
1756 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
1757                                                   const gchar *display_name,
1758                                                   GtkWindow *window)
1759 {
1760         /* Do not change the application name if the widget has not
1761            the focus. This callback could be called even if the folder
1762            view has not the focus, because the handled signal could be
1763            emitted when the folder view is redrawn */
1764         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
1765                 if (display_name)
1766                         gtk_window_set_title (window, display_name);
1767                 else
1768                         gtk_window_set_title (window, " ");
1769         }
1770 }
1771
1772 void
1773 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
1774 {
1775         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1776         modest_msg_edit_window_select_contacts (window);
1777 }