build fixes for maemo
[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-msg.h>
38 #include <modest-tny-account.h>
39 #include <modest-address-book.h>
40
41 #include "modest-ui-actions.h"
42
43 #include "modest-tny-platform-factory.h"
44 #include "modest-platform.h"
45
46 #include <widgets/modest-main-window.h>
47 #include <widgets/modest-msg-view-window.h>
48 #include <widgets/modest-account-view-window.h>
49 #include <widgets/modest-msg-view-details-dialog.h>
50
51 #include "modest-account-mgr-helpers.h"
52 #include "modest-mail-operation.h"
53
54 #ifdef MODEST_HAVE_EASYSETUP
55 #include "easysetup/modest-easysetup-wizard.h"
56 #endif /*MODEST_HAVE_EASYSETUP*/
57
58 #include <modest-widget-memory.h>
59 #include <tny-error.h>
60 #include <tny-simple-list.h>
61 #include <tny-msg-view.h>
62 #include <tny-device.h>
63
64
65 typedef struct _GetMsgAsyncHelper {
66         ModestWindow *window;
67         TnyIterator *iter;
68         GFunc func;
69         gpointer user_data;
70 } GetMsgAsyncHelper;
71
72 typedef enum _ReplyForwardAction {
73         ACTION_REPLY,
74         ACTION_REPLY_TO_ALL,
75         ACTION_FORWARD
76 } ReplyForwardAction;
77
78 typedef struct _ReplyForwardHelper {
79 guint reply_forward_type;
80         ReplyForwardAction action;
81         gchar *account_name;
82 } ReplyForwardHelper;
83
84
85 static void     reply_forward_func     (gpointer data, gpointer user_data);
86 static void     read_msg_func          (gpointer data, gpointer user_data);
87 static void     get_msg_cb             (TnyFolder *folder, TnyMsg *msg, GError **err, 
88                                         gpointer user_data);
89 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
90 static void     modest_ui_actions_message_details_cb (gpointer msg_data, 
91                                                       gpointer helper_data);
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         /* FIXME: save size of main window */
200 /*      save_sizes (main_window); */
201 /*      gtk_widget_destroy (GTK_WIDGET (win)); */
202         gtk_main_quit ();
203 }
204
205 void
206 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
207 {
208         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
209                 gtk_widget_destroy (GTK_WIDGET (win));
210         } else if (MODEST_IS_WINDOW (win)) {
211                 gtk_widget_destroy (GTK_WIDGET (win));
212         } else {
213                 g_return_if_reached ();
214         }
215 }
216
217 void
218 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
219 {
220         GtkClipboard *clipboard = NULL;
221         gchar *selection = NULL;
222
223         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
224         selection = gtk_clipboard_wait_for_text (clipboard);
225
226         modest_address_book_add_address (selection);
227         g_free (selection);
228 }
229
230 void
231 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
232 {
233         
234         /* This is currently only implemented for Maemo,
235          * because it requires a providers preset file which is not publically available.
236          */
237 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
238         GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr());
239         gboolean accounts_exist = account_names != NULL;
240         g_slist_free (account_names);
241         
242 /* To test, while modest_account_mgr_account_names() is broken: accounts_exist = TRUE; */
243         if (!accounts_exist) {
244                 /* If there are no accounts yet, just show the easy-setup wizard, as per the UI spec: */
245                 ModestEasysetupWizardDialog *wizard = modest_easysetup_wizard_dialog_new ();
246                 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
247                 gtk_dialog_run (GTK_DIALOG (wizard));
248                 gtk_widget_destroy (GTK_WIDGET (wizard));
249         } else  {
250                 /* Show the list of accounts: */
251                 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
252                 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW(win));
253                 gtk_dialog_run (account_win);
254                 gtk_widget_destroy (GTK_WIDGET(account_win));
255         }
256 #else
257         GtkWidget *dialog, *label;
258         
259         /* Create the widgets */
260         
261         dialog = gtk_dialog_new_with_buttons ("Message",
262                                               GTK_WINDOW(win),
263                                               GTK_DIALOG_DESTROY_WITH_PARENT,
264                                               GTK_STOCK_OK,
265                                               GTK_RESPONSE_NONE,
266                                               NULL);
267         label = gtk_label_new ("Hello World!");
268         
269         /* Ensure that the dialog box is destroyed when the user responds. */
270         
271         g_signal_connect_swapped (dialog, "response", 
272                                   G_CALLBACK (gtk_widget_destroy),
273                                   dialog);
274         
275         /* Add the label, and show everything we've added to the dialog. */
276         
277         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
278                            label);
279         gtk_widget_show_all (dialog);
280 #endif /* MODEST_PLATFORM_MAEMO */
281 }
282
283 void
284 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
285 {
286         ModestWindow *msg_win;
287         TnyMsg *msg = NULL;
288         TnyFolder *folder = NULL;
289         gchar *account_name = NULL;
290         gchar *from_str = NULL;
291         GError *err = NULL;
292         TnyAccount *account;
293         ModestWindowMgr *mgr;
294         
295         account_name = g_strdup(modest_window_get_active_account (win));
296         if (!account_name)
297                 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
298         
299         account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
300                                                                        account_name,
301                                                                        TNY_ACCOUNT_TYPE_STORE);
302         if (!account) {
303                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
304                 goto cleanup;
305         }
306
307         from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
308
309         msg    = modest_tny_msg_new ("", from_str, "", "", "", "", NULL);
310         if (!msg) {
311                 g_printerr ("modest: failed to create new msg\n");
312                 goto cleanup;
313         }
314         
315         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
316         if (!folder) {
317                 g_printerr ("modest: failed to find Drafts folder\n");
318                 goto cleanup;
319         }
320         
321         tny_folder_add_msg (folder, msg, &err);
322         if (err) {
323                 g_printerr ("modest: error adding msg to Drafts folder: %s",
324                             err->message);
325                 g_error_free (err);
326                 goto cleanup;
327         }
328
329         /* Create and register edit window */
330         msg_win = modest_msg_edit_window_new (msg, account_name);
331         mgr = modest_runtime_get_window_mgr ();
332         modest_window_mgr_register_window (mgr, msg_win);
333
334         if (win)
335                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
336                                               GTK_WINDOW (win));        
337         gtk_widget_show_all (GTK_WIDGET (msg_win));
338
339 cleanup:
340         g_free (account_name);
341         g_free (from_str);
342         if (account)
343                 g_object_unref (G_OBJECT(account));
344         if (msg)
345                 g_object_unref (G_OBJECT(msg));
346         if (folder)
347                 g_object_unref (G_OBJECT(folder));
348 }
349
350
351 void
352 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
353 {
354         modest_runtime_not_implemented (GTK_WINDOW(win)); /* FIXME */
355 }
356
357
358
359 static void
360 reply_forward_func (gpointer data, gpointer user_data)
361 {
362         TnyMsg *msg, *new_msg;
363         GetMsgAsyncHelper *helper;
364         ReplyForwardHelper *rf_helper;
365         ModestWindow *msg_win;
366         ModestEditType edit_type;
367         gchar *from;
368         GError *err = NULL;
369         TnyFolder *folder = NULL;
370         TnyAccount *account = NULL;
371         ModestWindowMgr *mgr;
372         
373         msg = TNY_MSG (data);
374         helper = (GetMsgAsyncHelper *) user_data;
375         rf_helper = (ReplyForwardHelper *) helper->user_data;
376
377         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
378                                                    rf_helper->account_name);
379         /* Create reply mail */
380         switch (rf_helper->action) {
381         case ACTION_REPLY:
382                 new_msg = 
383                         modest_tny_msg_create_reply_msg (msg,  from, 
384                                                          rf_helper->reply_forward_type,
385                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
386                 break;
387         case ACTION_REPLY_TO_ALL:
388                 new_msg = 
389                         modest_tny_msg_create_reply_msg (msg, from, rf_helper->reply_forward_type,
390                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
391                 edit_type = MODEST_EDIT_TYPE_REPLY;
392                 break;
393         case ACTION_FORWARD:
394                 new_msg = 
395                         modest_tny_msg_create_forward_msg (msg, from, rf_helper->reply_forward_type);
396                 edit_type = MODEST_EDIT_TYPE_FORWARD;
397                 break;
398         default:
399                 g_return_if_reached ();
400                 return;
401         }
402
403         if (!new_msg) {
404                 g_printerr ("modest: failed to create message\n");
405                 goto cleanup;
406         }
407
408         account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
409                                                                        rf_helper->account_name,
410                                                                        TNY_ACCOUNT_TYPE_STORE);
411         if (!account) {
412                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
413                 goto cleanup;
414         }
415
416         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
417         if (!folder) {
418                 g_printerr ("modest: failed to find Drafts folder\n");
419                 goto cleanup;
420         }
421         
422         tny_folder_add_msg (folder, msg, &err);
423         if (err) {
424                 g_printerr ("modest: error adding msg to Drafts folder: %s",
425                             err->message);
426                 g_error_free (err);
427                 goto cleanup;
428         }       
429
430         /* Create and register the windows */                   
431         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
432         mgr = modest_runtime_get_window_mgr ();
433         modest_window_mgr_register_window (mgr, msg_win);
434
435         /* Show edit window */
436         gtk_widget_show_all (GTK_WIDGET (msg_win));
437
438 cleanup:
439         if (new_msg)
440                 g_object_unref (G_OBJECT (new_msg));
441         if (folder)
442                 g_object_unref (G_OBJECT (folder));
443         if (account)
444                 g_object_unref (G_OBJECT (account));
445         
446         g_free (rf_helper->account_name);
447         g_slice_free (ReplyForwardHelper, rf_helper);
448 }
449 /*
450  * Common code for the reply and forward actions
451  */
452 static void
453 reply_forward (ReplyForwardAction action, ModestWindow *win)
454 {
455         TnyList *header_list;
456         guint reply_forward_type;
457         TnyHeader *header;
458         TnyFolder *folder;
459         GetMsgAsyncHelper *helper;
460         ReplyForwardHelper *rf_helper;
461         
462         g_return_if_fail (MODEST_IS_WINDOW(win));
463
464         header_list = get_selected_headers (win);
465         if (!header_list)
466                 return;
467         
468         reply_forward_type = modest_conf_get_int (modest_runtime_get_conf (),
469                                                   (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
470                                                   NULL);
471         /* We assume that we can only select messages of the
472            same folder and that we reply all of them from the
473            same account. In fact the interface currently only
474            allows single selection */
475         
476         /* Fill helpers */
477         rf_helper = g_slice_new0 (ReplyForwardHelper);
478         rf_helper->reply_forward_type = reply_forward_type;
479         rf_helper->action = action;
480
481         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
482         if (!rf_helper->account_name)
483                 rf_helper->account_name =
484                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
485
486         helper = g_slice_new0 (GetMsgAsyncHelper);
487         helper->window = win;
488         helper->func = reply_forward_func;
489         helper->iter = tny_list_create_iterator (header_list);
490         helper->user_data = rf_helper;
491
492         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
493                 TnyMsg *msg;
494                 msg = modest_msg_view_window_get_message(MODEST_MSG_VIEW_WINDOW(win));
495                 if (!msg) {
496                         g_printerr ("modest: no message found\n");
497                         return;
498                 } else
499                         reply_forward_func (msg, helper);
500         } else {
501                 header = TNY_HEADER (tny_iterator_get_current (helper->iter));
502                 folder = tny_header_get_folder (header);
503                 if (folder) {
504                         /* The callback will call it per each header */
505                         tny_folder_get_msg_async (folder, header, get_msg_cb, helper);
506                         g_object_unref (G_OBJECT (folder));
507                 } else 
508                         g_printerr ("modest: no folder for header\n");
509                 
510                 /* Clean */
511                 g_object_unref (G_OBJECT (header));
512         }
513 }
514
515
516 void
517 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
518 {
519         g_return_if_fail (MODEST_IS_WINDOW(win));
520
521         reply_forward (ACTION_REPLY, win);
522 }
523
524 void
525 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
526 {
527         g_return_if_fail (MODEST_IS_WINDOW(win));
528
529         reply_forward (ACTION_FORWARD, win);
530 }
531
532 void
533 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
534 {
535         g_return_if_fail (MODEST_IS_WINDOW(win));
536
537         reply_forward (ACTION_REPLY_TO_ALL, win);
538 }
539
540 void 
541 modest_ui_actions_on_next (GtkAction *action, 
542                            ModestWindow *window)
543 {
544         if (MODEST_IS_MAIN_WINDOW (window)) {
545                 GtkWidget *header_view;
546
547                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
548                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
549                 if (!header_view)
550                         return;
551         
552                 modest_header_view_select_next (MODEST_HEADER_VIEW(header_view)); 
553         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
554                 modest_msg_view_window_select_next_message (MODEST_MSG_VIEW_WINDOW (window));
555         } else {
556                 g_return_if_reached ();
557         }
558 }
559
560 void 
561 modest_ui_actions_on_prev (GtkAction *action, 
562                            ModestWindow *window)
563 {
564         g_return_if_fail (MODEST_IS_WINDOW(window));
565
566         if (MODEST_IS_MAIN_WINDOW (window)) {
567                 GtkWidget *header_view;
568                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
569                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
570                 if (!header_view)
571                         return;
572                 
573                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
574         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
575                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
576         } else {
577                 g_return_if_reached ();
578         }
579 }
580
581
582 static gboolean
583 action_send (const gchar* account_name)
584 {
585         TnyAccount *tny_account;
586         ModestTnySendQueue *send_queue;
587
588         g_return_val_if_fail (account_name, FALSE);
589
590         tny_account = 
591                 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
592                                                                      account_name,
593                                                                      TNY_ACCOUNT_TYPE_TRANSPORT);
594         if (!tny_account) {
595                 g_printerr ("modest: cannot get tny transport account for %s\n", account_name);
596                 return FALSE;
597         }
598         send_queue = modest_tny_send_queue_new (TNY_CAMEL_TRANSPORT_ACCOUNT(tny_account));
599         if (!send_queue) {
600                 g_object_unref (G_OBJECT(tny_account));
601                 g_printerr ("modest: cannot get send queue for %s\n", account_name);
602                 return FALSE;
603         }
604         
605         //modest_tny_send_queue_flush (send_queue);
606
607         g_object_unref (G_OBJECT(send_queue));
608         g_object_unref (G_OBJECT(tny_account));
609
610         return TRUE;
611 }
612
613
614 static gboolean
615 action_receive (const gchar* account_name)
616 {
617         TnyAccount *tny_account;
618         ModestMailOperation *mail_op;
619
620         g_return_val_if_fail (account_name, FALSE);
621
622         tny_account = 
623                 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
624                                                                      account_name,
625                                                                      TNY_ACCOUNT_TYPE_STORE);
626         if (!tny_account) {
627                 g_printerr ("modest: cannot get tny store account for %s\n", account_name);
628                 return FALSE;
629         }
630
631         /* Create the mail operation */
632         mail_op = modest_mail_operation_new ();
633         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
634         modest_mail_operation_update_account (mail_op, TNY_STORE_ACCOUNT(tny_account));
635         g_object_unref (G_OBJECT(tny_account));
636         g_object_unref (G_OBJECT (mail_op));
637                 
638         return TRUE;
639 }
640
641
642
643 void
644 modest_ui_actions_on_send_receive (GtkAction *action,  ModestWindow *win)
645 {
646         gchar *account_name;
647         
648         account_name =
649                 g_strdup(modest_window_get_active_account(MODEST_WINDOW(win)));
650         if (!account_name)
651                 account_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
652         if (!account_name) {
653                 g_printerr ("modest: cannot get account\n");
654                 return;
655         }
656
657         if (!action_send(account_name))
658                 g_printerr ("modest: failed to send\n");
659         if (!action_receive(account_name))
660                 g_printerr ("modest: failed to receive\n");
661 }
662
663
664
665 void
666 modest_ui_actions_toggle_view (GtkAction *action, ModestMainWindow *main_window)
667 {
668         ModestConf *conf;
669         GtkWidget *header_view;
670         
671         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
672
673         header_view = modest_main_window_get_child_widget (main_window,
674                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
675         if (!header_view)
676                 return;
677
678         conf = modest_runtime_get_conf ();
679         
680         /* what is saved/restored is depending on the style; thus; we save with
681          * old style, then update the style, and restore for this new style
682          */
683         modest_widget_memory_save (conf, G_OBJECT(header_view), "header-view");
684         
685         if (modest_header_view_get_style
686             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
687                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
688                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
689         else
690                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
691                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
692
693         modest_widget_memory_restore (conf, G_OBJECT(header_view),
694                                       "header-view");
695 }
696
697
698
699 /*
700  * Marks a message as read and passes it to the msg preview widget
701  */
702 static void
703 read_msg_func (gpointer data, gpointer user_data)
704 {
705         TnyMsg *msg;
706         TnyHeader *header;
707         GetMsgAsyncHelper *helper;
708         TnyHeaderFlags header_flags;
709         GtkWidget *msg_preview;
710         
711         msg = TNY_MSG (data);
712         helper = (GetMsgAsyncHelper *) user_data;
713
714         msg_preview = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (helper->window),
715                                                            MODEST_WIDGET_TYPE_MSG_PREVIEW);
716         if (!msg_preview)
717                 return;
718         
719         header = TNY_HEADER (tny_iterator_get_current (helper->iter));
720         header_flags = tny_header_get_flags (header);
721         tny_header_set_flags (header, header_flags | TNY_HEADER_FLAG_SEEN);
722         g_object_unref (G_OBJECT (header));
723
724         /* Set message on msg view */
725         modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), msg);
726 }
727
728 /*
729  * This function is a generic handler for the tny_folder_get_msg_async
730  * call. It expects as user_data a #GetMsgAsyncHelper. This helper
731  * contains a user provided function that is called inside this
732  * method. This will allow us to use this callback in many different
733  * places. This callback performs the common actions for the
734  * get_msg_async call, more specific actions will be done by the user
735  * function
736  */
737 static void
738 get_msg_cb (TnyFolder *folder, TnyMsg *msg, GError **err, gpointer user_data)
739 {
740         GetMsgAsyncHelper *helper;
741
742         helper = (GetMsgAsyncHelper *) user_data;
743
744         if ((*err && ((*err)->code == TNY_FOLDER_ERROR_GET_MSG)) || !msg) {
745                 modest_ui_actions_on_item_not_found (NULL,
746                                                      MODEST_ITEM_TYPE_MESSAGE,
747                                                      helper->window);
748                 return;
749         }
750
751         /* Call user function */
752         helper->func (msg, user_data);
753
754         /* Process next element (if exists) */
755         tny_iterator_next (helper->iter);
756         if (tny_iterator_is_done (helper->iter)) {
757                 TnyList *headers;
758                 headers = tny_iterator_get_list (helper->iter);
759                 /* Free resources */
760                 g_object_unref (G_OBJECT (headers));
761                 g_object_unref (G_OBJECT (helper->iter));
762                 g_slice_free (GetMsgAsyncHelper, helper);
763         } else {
764                 TnyHeader *header;
765                 header = TNY_HEADER (tny_iterator_get_current (helper->iter)); 
766                 tny_folder_get_msg_async (folder, header,                         
767                                           get_msg_cb, helper);
768                 g_object_unref (G_OBJECT(header));
769         }
770 }
771
772 void 
773 modest_ui_actions_on_header_selected (ModestHeaderView *folder_view, 
774                                       TnyHeader *header,
775                                       ModestMainWindow *main_window)
776 {
777         GtkWidget *msg_preview;
778         TnyFolder *folder;
779         GetMsgAsyncHelper *helper;
780         TnyList *list;
781
782         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
783         
784         msg_preview = modest_main_window_get_child_widget(main_window,
785                                                           MODEST_WIDGET_TYPE_MSG_PREVIEW);
786         if (!msg_preview)
787                 return;
788         
789         /* when there's no header, clear the msgview */
790         if (!header) {
791                 modest_msg_view_set_message (MODEST_MSG_VIEW(msg_preview), NULL);
792                 return;
793         }
794
795         folder = tny_header_get_folder (TNY_HEADER(header));
796
797         /* Create list */
798         list = tny_simple_list_new ();
799         tny_list_prepend (list, G_OBJECT (header));
800
801         /* Fill helper data */
802         helper = g_slice_new0 (GetMsgAsyncHelper);
803         helper->window = MODEST_WINDOW (main_window);
804         helper->iter = tny_list_create_iterator (list);
805         helper->func = read_msg_func;
806
807         tny_folder_get_msg_async (TNY_FOLDER(folder),
808                                   header, get_msg_cb,
809                                   helper);
810
811         /* Frees */
812         g_object_unref (G_OBJECT (folder));
813 }
814
815
816
817 void 
818 modest_ui_actions_on_header_activated (ModestHeaderView *folder_view, TnyHeader *header,
819                                        ModestMainWindow *main_window)
820 {
821         ModestWindow *win;
822         TnyFolder *folder = NULL;
823         TnyMsg    *msg    = NULL;
824         gchar *account    = NULL;
825         GtkTreeModel *model = NULL;
826         GtkTreeSelection *sel = NULL;
827         GtkTreeIter iter;
828         ModestWindowMgr *mgr;
829         
830         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
831         
832         if (!header)
833                 return;
834
835         folder = tny_header_get_folder (header);
836         if (!folder) {
837                 g_printerr ("modest: cannot get folder for header\n");
838                 goto cleanup;
839         }
840
841         /* FIXME: make async?; check error  */
842         msg = tny_folder_get_msg (folder, header, NULL);
843         if (!msg) {
844                 g_printerr ("modest: cannot get msg for header\n");
845                 goto cleanup;
846         }
847
848         account =  g_strdup(modest_window_get_active_account(MODEST_WINDOW(main_window)));
849         if (!account)
850                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
851
852         /* Create and register message view window */   
853         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_view));
854         if (gtk_tree_selection_get_selected (sel, &model, &iter)) {
855                 win = modest_msg_view_window_new_with_header_model (msg, account, model, iter);
856         } else {
857                 win = modest_msg_view_window_new (msg, account);
858         }
859         mgr = modest_runtime_get_window_mgr ();
860         modest_window_mgr_register_window (mgr, win);
861
862         gtk_window_set_transient_for (GTK_WINDOW (win),
863                                       GTK_WINDOW (main_window));
864
865         gtk_widget_show_all (GTK_WIDGET(win));
866         
867 cleanup:
868         g_free (account);
869         
870         if (folder)
871                 g_object_unref (G_OBJECT (folder));
872         if (msg)
873                 g_object_unref (G_OBJECT (msg));
874 }
875
876 void 
877 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
878                                                TnyFolder *folder, 
879                                                gboolean selected,
880                                                ModestMainWindow *main_window)
881 {
882         gchar *txt;
883         ModestConf *conf;
884         GtkWidget *header_view;
885         
886         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
887
888         header_view = modest_main_window_get_child_widget(main_window,
889                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
890         if (!header_view)
891                 return;
892         
893         conf = modest_runtime_get_conf ();
894
895         if (!selected) { /* the folder was unselected; save it's settings  */
896                 modest_widget_memory_save (conf, G_OBJECT (header_view), "header-view");
897                 gtk_window_set_title (GTK_WINDOW(main_window), "Modest");
898                 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
899         } else {  /* the folder was selected */
900                 if (folder) { /* folder may be NULL */
901                         guint num, unread;
902                         gchar *title;
903
904                         num    = tny_folder_get_all_count    (folder);
905                         unread = tny_folder_get_unread_count (folder);
906                         
907                         title = g_strdup_printf ("Modest: %s",
908                                                  tny_folder_get_name (folder));
909                         
910                         gtk_window_set_title (GTK_WINDOW(main_window), title);
911                         g_free (title);
912                         
913                         txt = g_strdup_printf (_("%d %s, %d unread"),
914                                                num, num==1 ? _("item") : _("items"), unread);           
915                         //gtk_label_set_label (GTK_LABEL(folder_info_label), txt);
916                         g_free (txt);
917                 }
918                 modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), folder);
919                 modest_widget_memory_restore (conf, G_OBJECT(header_view),
920                                               "header-view");
921         }
922 }
923
924 void 
925 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
926                                      ModestWindow *win)
927 {
928         GtkWidget *dialog;
929         gchar *txt, *item;
930         gboolean online;
931
932         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
933         
934         if (g_main_depth > 0)   
935                 gdk_threads_enter ();
936         online = tny_device_is_online (modest_runtime_get_device());
937
938         if (online) {
939                 /* already online -- the item is simply not there... */
940                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
941                                                  GTK_DIALOG_MODAL,
942                                                  GTK_MESSAGE_WARNING,
943                                                  GTK_BUTTONS_OK,
944                                                  _("The %s you selected cannot be found"),
945                                                  item);
946                 gtk_dialog_run (GTK_DIALOG(dialog));
947         } else {
948                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
949                                                       GTK_WINDOW (win),
950                                                       GTK_DIALOG_MODAL,
951                                                       GTK_STOCK_CANCEL,
952                                                       GTK_RESPONSE_REJECT,
953                                                       GTK_STOCK_OK,
954                                                       GTK_RESPONSE_ACCEPT,
955                                                       NULL);
956                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
957                                          "Do you want to get online?"), item);
958                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
959                                     gtk_label_new (txt), FALSE, FALSE, 0);
960                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
961                 g_free (txt);
962
963                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
964                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
965 //                      tny_device_force_online (modest_runtime_get_device());
966                 }
967         }
968         gtk_widget_destroy (dialog);
969         if (g_main_depth > 0)   
970                 gdk_threads_leave ();
971 }
972
973 void
974 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
975                                      ModestWindow *win)
976 {
977         g_message ("%s %s", __FUNCTION__, link);
978 }       
979
980
981 void
982 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
983                                         ModestWindow *win)
984 {
985         modest_platform_activate_uri (link);
986 }
987
988 void
989 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
990                                           ModestWindow *win)
991 {
992         modest_platform_show_uri_popup (link);
993 }
994
995 void
996 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
997                                              ModestWindow *win)
998 {
999         g_message (__FUNCTION__);
1000         
1001 }
1002
1003 void
1004 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1005                                           const gchar *address,
1006                                           ModestWindow *win)
1007 {
1008         g_message ("%s %s", __FUNCTION__, address);
1009 }
1010
1011 void
1012 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1013 {
1014         TnyTransportAccount *transport_account;
1015         ModestMailOperation *mail_operation;
1016         MsgData *data;
1017         gchar *account_name, *from;
1018         ModestAccountMgr *account_mgr;
1019
1020         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1021         
1022         data = modest_msg_edit_window_get_msg_data (edit_window);
1023
1024         /* FIXME: Code added just for testing. The final version will
1025            use the send queue provided by tinymail and some
1026            classifier */
1027         account_mgr = modest_runtime_get_account_mgr();
1028         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1029         if (!account_name) 
1030                 account_name = modest_account_mgr_get_default_account (account_mgr);
1031         if (!account_name) {
1032                 g_printerr ("modest: no account found\n");
1033                 modest_msg_edit_window_free_msg_data (edit_window, data);
1034                 return;
1035         }
1036         transport_account =
1037                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
1038                                       (modest_runtime_get_account_store(),
1039                                        account_name,
1040                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1041         if (!transport_account) {
1042                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1043                 g_free (account_name);
1044                 modest_msg_edit_window_free_msg_data (edit_window, data);
1045                 return;
1046         }
1047         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1048
1049         /* Create the mail operation */         
1050         mail_operation = modest_mail_operation_new ();
1051         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1052
1053         modest_mail_operation_send_new_mail (mail_operation,
1054                                              transport_account,
1055                                              from,
1056                                              data->to, 
1057                                              data->cc, 
1058                                              data->bcc,
1059                                              data->subject, 
1060                                              data->plain_body, 
1061                                              data->html_body,
1062                                              data->attachments);
1063         /* Frees */
1064         g_free (from);
1065         g_free (account_name);
1066         g_object_unref (G_OBJECT (transport_account));
1067         g_object_unref (G_OBJECT (mail_operation));
1068
1069         modest_msg_edit_window_free_msg_data (edit_window, data);
1070
1071         /* Save settings and close the window */
1072         gtk_widget_destroy (GTK_WIDGET (edit_window));
1073 }
1074
1075 void 
1076 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1077                                   ModestMsgEditWindow *window)
1078 {
1079         ModestMsgEditFormatState *format_state = NULL;
1080
1081         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1082         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1083
1084         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1085                 return;
1086
1087         format_state = modest_msg_edit_window_get_format_state (window);
1088         g_return_if_fail (format_state != NULL);
1089
1090         format_state->bold = gtk_toggle_action_get_active (action);
1091         modest_msg_edit_window_set_format_state (window, format_state);
1092         g_free (format_state);
1093         
1094 }
1095
1096 void 
1097 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1098                                      ModestMsgEditWindow *window)
1099 {
1100         ModestMsgEditFormatState *format_state = NULL;
1101
1102         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1103         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1104
1105         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1106                 return;
1107
1108         format_state = modest_msg_edit_window_get_format_state (window);
1109         g_return_if_fail (format_state != NULL);
1110
1111         format_state->italics = gtk_toggle_action_get_active (action);
1112         modest_msg_edit_window_set_format_state (window, format_state);
1113         g_free (format_state);
1114         
1115 }
1116
1117 void 
1118 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
1119                                      ModestMsgEditWindow *window)
1120 {
1121         ModestMsgEditFormatState *format_state = NULL;
1122
1123         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1124         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1125
1126         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1127                 return;
1128
1129         format_state = modest_msg_edit_window_get_format_state (window);
1130         g_return_if_fail (format_state != NULL);
1131
1132         format_state->bullet = gtk_toggle_action_get_active (action);
1133         modest_msg_edit_window_set_format_state (window, format_state);
1134         g_free (format_state);
1135         
1136 }
1137
1138 void 
1139 modest_ui_actions_on_change_justify (GtkRadioAction *action,
1140                                      GtkRadioAction *selected,
1141                                      ModestMsgEditWindow *window)
1142 {
1143         ModestMsgEditFormatState *format_state = NULL;
1144         GtkJustification value;
1145
1146         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1147
1148         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1149                 return;
1150
1151         value = gtk_radio_action_get_current_value (selected);
1152
1153         format_state = modest_msg_edit_window_get_format_state (window);
1154         g_return_if_fail (format_state != NULL);
1155
1156         format_state->justification = value;
1157         modest_msg_edit_window_set_format_state (window, format_state);
1158         g_free (format_state);
1159 }
1160
1161 void 
1162 modest_ui_actions_on_select_editor_color (GtkAction *action,
1163                                           ModestMsgEditWindow *window)
1164 {
1165         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1166         g_return_if_fail (GTK_IS_ACTION (action));
1167
1168         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1169                 return;
1170
1171         modest_msg_edit_window_select_color (window);
1172 }
1173
1174 void 
1175 modest_ui_actions_on_select_editor_background_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_background_color (window);
1185 }
1186
1187 void 
1188 modest_ui_actions_on_insert_image (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_insert_image (window);
1198 }
1199
1200 /*
1201  * Shows a dialog with an entry that asks for some text. The returned
1202  * value must be freed by the caller. The dialog window title will be
1203  * set to @title.
1204  */
1205 static gchar *
1206 ask_for_folder_name (GtkWindow *parent_window,
1207                      const gchar *title)
1208 {
1209         GtkWidget *dialog, *entry;
1210         gchar *folder_name = NULL;
1211
1212         /* Ask for folder name */
1213         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1214                                               parent_window,
1215                                               GTK_DIALOG_MODAL,
1216                                               GTK_STOCK_CANCEL,
1217                                               GTK_RESPONSE_REJECT,
1218                                               GTK_STOCK_OK,
1219                                               GTK_RESPONSE_ACCEPT,
1220                                               NULL);
1221         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1222                             gtk_label_new(title),
1223                             FALSE, FALSE, 0);
1224                 
1225         entry = gtk_entry_new_with_max_length (40);
1226         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1227                             entry,
1228                             TRUE, FALSE, 0);    
1229         
1230         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1231         
1232         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
1233                 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1234
1235         gtk_widget_destroy (dialog);
1236
1237         return folder_name;
1238 }
1239
1240 void 
1241 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1242 {
1243         TnyFolder *parent_folder;
1244         GtkWidget *folder_view;
1245         
1246         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1247
1248         folder_view = modest_main_window_get_child_widget (main_window,
1249                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1250         if (!folder_view)
1251                 return;
1252
1253         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1254         
1255         if (parent_folder) {
1256                 gchar *folder_name;
1257
1258                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1259                                                    _("Please enter a name for the new folder"));
1260
1261                 if (folder_name != NULL && strlen (folder_name) > 0) {
1262                         TnyFolder *new_folder;
1263                         ModestMailOperation *mail_op;
1264
1265                         mail_op = modest_mail_operation_new ();
1266                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
1267                                                          mail_op);
1268
1269                         new_folder = modest_mail_operation_create_folder (mail_op,
1270                                                                           TNY_FOLDER_STORE (parent_folder),
1271                                                                           (const gchar *) folder_name);
1272                         if (new_folder) 
1273                                 g_object_unref (new_folder);
1274                         g_object_unref (mail_op);
1275                         g_free (folder_name);
1276                 }
1277                 g_object_unref (parent_folder);
1278         }
1279 }
1280
1281 void 
1282 modest_ui_actions_on_rename_folder (GtkAction *action,
1283                                      ModestMainWindow *main_window)
1284 {
1285         TnyFolder *folder;
1286         GtkWidget *folder_view;
1287         
1288         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1289
1290         folder_view = modest_main_window_get_child_widget (main_window,
1291                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1292         if (!folder_view)
1293                 return;
1294         
1295         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1296         
1297         if (folder) {
1298                 gchar *folder_name;
1299                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1300                                                    _("Please enter a new name for the folder"));
1301
1302                 if (folder_name != NULL && strlen (folder_name) > 0) {
1303                         ModestMailOperation *mail_op;
1304
1305                         mail_op = modest_mail_operation_new ();
1306                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1307                                                          mail_op);
1308
1309                         modest_mail_operation_rename_folder (mail_op,
1310                                                              folder,
1311                                                              (const gchar *) folder_name);
1312
1313                         g_object_unref (mail_op);
1314                         g_free (folder_name);
1315                 }
1316                 g_object_unref (folder);
1317         }
1318 }
1319
1320 static void
1321 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
1322 {
1323         TnyFolder *folder;
1324         ModestMailOperation *mail_op;
1325         GtkWidget *folder_view;
1326         
1327         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1328
1329         folder_view = modest_main_window_get_child_widget (main_window,
1330                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1331         if (!folder_view)
1332                 return;
1333
1334         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1335         
1336         mail_op = modest_mail_operation_new ();
1337         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1338                                          mail_op);
1339         modest_mail_operation_remove_folder (mail_op, folder, move_to_trash);
1340
1341         g_object_unref (G_OBJECT (mail_op));
1342         g_object_unref (G_OBJECT (folder));
1343 }
1344
1345 void 
1346 modest_ui_actions_on_delete_folder (GtkAction *action,
1347                                      ModestMainWindow *main_window)
1348 {
1349         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1350
1351         delete_folder (main_window, FALSE);
1352 }
1353
1354 void 
1355 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1356 {
1357         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1358         
1359         delete_folder (main_window, TRUE);
1360 }
1361
1362 void
1363 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
1364                                          const gchar* account_name,
1365                                          gchar **password, 
1366                                          gboolean *cancel, 
1367                                          gboolean *remember,
1368                                          ModestMainWindow *main_window)
1369 {
1370         gchar *txt;
1371         GtkWidget *dialog, *entry, *remember_pass_check;
1372
1373         dialog = gtk_dialog_new_with_buttons (_("Password requested"),
1374                                               NULL,
1375                                               GTK_DIALOG_MODAL,
1376                                               GTK_STOCK_CANCEL,
1377                                               GTK_RESPONSE_REJECT,
1378                                               GTK_STOCK_OK,
1379                                               GTK_RESPONSE_ACCEPT,
1380                                               NULL);
1381         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1382         
1383         txt = g_strdup_printf (_("Please enter your password for %s"), account_name);
1384         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1385                             FALSE, FALSE, 0);
1386         g_free (txt);
1387
1388         entry = gtk_entry_new_with_max_length (40);
1389         gtk_entry_set_visibility (GTK_ENTRY(entry), FALSE);
1390         gtk_entry_set_invisible_char (GTK_ENTRY(entry), 0x2022); /* bullet unichar */
1391         
1392         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry,
1393                             TRUE, FALSE, 0);    
1394
1395         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1396         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1397                             TRUE, FALSE, 0);
1398
1399         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1400         
1401         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1402                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry)));
1403                 *cancel   = FALSE;
1404         } else {
1405                 *password = NULL;
1406                 *cancel   = TRUE;
1407         }
1408
1409         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
1410                 *remember = TRUE;
1411         else
1412                 *remember = FALSE;
1413
1414         gtk_widget_destroy (dialog);
1415 }
1416
1417 void
1418 modest_ui_actions_on_cut (GtkAction *action,
1419                           ModestWindow *window)
1420 {
1421         GtkWidget *focused_widget;
1422
1423         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1424         if (GTK_IS_EDITABLE (focused_widget)) {
1425                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
1426         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1427                 GtkTextBuffer *buffer;
1428                 GtkClipboard *clipboard;
1429
1430                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1431                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1432                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
1433         }
1434 }
1435
1436 void
1437 modest_ui_actions_on_copy (GtkAction *action,
1438                            ModestWindow *window)
1439 {
1440         GtkClipboard *clipboard;
1441         GtkWidget *focused_widget;
1442
1443         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1444         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1445         if (GTK_IS_LABEL (focused_widget)) {
1446                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
1447         } else if (GTK_IS_EDITABLE (focused_widget)) {
1448                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
1449         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1450                 GtkTextBuffer *buffer;
1451
1452                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1453                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
1454         }
1455 }
1456
1457 void
1458 modest_ui_actions_on_paste (GtkAction *action,
1459                             ModestWindow *window)
1460 {
1461         GtkWidget *focused_widget;
1462
1463         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1464         if (GTK_IS_EDITABLE (focused_widget)) {
1465                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
1466         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1467                 GtkTextBuffer *buffer;
1468                 GtkClipboard *clipboard;
1469
1470                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1471                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1472                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
1473         }
1474 }
1475
1476 void
1477 modest_ui_actions_on_select_all (GtkAction *action,
1478                                  ModestWindow *window)
1479 {
1480         GtkWidget *focused_widget;
1481
1482         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1483         if (GTK_IS_LABEL (focused_widget)) {
1484                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
1485         } else if (GTK_IS_EDITABLE (focused_widget)) {
1486                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
1487         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1488                 GtkTextBuffer *buffer;
1489                 GtkTextIter start, end;
1490
1491                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1492                 gtk_text_buffer_get_start_iter (buffer, &start);
1493                 gtk_text_buffer_get_end_iter (buffer, &end);
1494                 gtk_text_buffer_select_range (buffer, &start, &end);
1495         }
1496 }
1497
1498 void
1499 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
1500                                   GtkRadioAction *selected,
1501                                   ModestWindow *window)
1502 {
1503         gint value;
1504
1505         value = gtk_radio_action_get_current_value (selected);
1506         if (MODEST_IS_WINDOW (window)) {
1507                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
1508         }
1509 }
1510
1511 void     
1512 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
1513                                            ModestWindow *window)
1514 {
1515         g_return_if_fail (MODEST_IS_WINDOW (window));
1516
1517         if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle))) {
1518                 gtk_window_fullscreen (GTK_WINDOW (window));
1519         } else {
1520                 gtk_window_unfullscreen (GTK_WINDOW (window));
1521         }
1522 }
1523
1524 static void
1525 modest_ui_actions_message_details_cb (gpointer msg_data, 
1526                                       gpointer helper_data)
1527 {
1528         GtkWidget *dialog;
1529         TnyMsg *msg = (TnyMsg *) msg_data;
1530         TnyHeader *header;
1531         GetMsgAsyncHelper *helper = (GetMsgAsyncHelper *) helper_data;
1532         
1533         header = tny_msg_get_header (msg);
1534         
1535         dialog = modest_msg_view_details_dialog_new (GTK_WINDOW (helper->window), header);
1536         g_object_unref (header);
1537         gtk_widget_show_all (dialog);
1538
1539         gtk_dialog_run (GTK_DIALOG (dialog));
1540
1541         gtk_widget_destroy (dialog);
1542 }
1543
1544 void     
1545 modest_ui_actions_on_message_details (GtkAction *action, 
1546                                       ModestWindow *win)
1547 {
1548         TnyList * headers_list;
1549         GetMsgAsyncHelper *helper;
1550
1551         headers_list = get_selected_headers (win);
1552         if (!headers_list)
1553                 return;
1554
1555         helper = g_slice_new0 (GetMsgAsyncHelper);
1556         helper->window = win;
1557         helper->func = modest_ui_actions_message_details_cb;
1558         helper->iter = tny_list_create_iterator (headers_list);
1559         helper->user_data = NULL;
1560
1561         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1562                 TnyMsg *msg;
1563
1564                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
1565                 if (!msg)
1566                         return;
1567                 else {
1568                         modest_ui_actions_message_details_cb (msg, helper);
1569                 }
1570         } else {
1571                 /* here we should add an implementation to run the message details dialog
1572                    from the main window */
1573                 g_return_if_reached ();
1574         }
1575 }