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