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