2007-05-08 Murray Cumming <murrayc@murrayc.com>
[modest] / src / modest-ui-actions.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif /*HAVE_CONFIG_H*/
33
34 #include <glib/gi18n.h>
35 #include <string.h>
36 #include <modest-runtime.h>
37 #include <modest-tny-folder.h>
38 #include <modest-tny-msg.h>
39 #include <modest-tny-account.h>
40 #include <modest-address-book.h>
41
42 #include "modest-ui-actions.h"
43
44 #include "modest-tny-platform-factory.h"
45 #include "modest-platform.h"
46
47 #ifdef MODEST_PLATFORM_MAEMO
48 #include "maemo/modest-osso-state-saving.h"
49 #endif /* MODEST_PLATFORM_MAEMO */
50
51
52 #include <widgets/modest-main-window.h>
53 #include <widgets/modest-msg-view-window.h>
54 #include <widgets/modest-account-view-window.h>
55 #include <widgets/modest-details-dialog.h>
56
57 #include "modest-account-mgr-helpers.h"
58 #include "modest-mail-operation.h"
59 #include "modest-text-utils.h"
60
61 #ifdef MODEST_HAVE_EASYSETUP
62 #include "easysetup/modest-easysetup-wizard.h"
63 #endif /* MODEST_HAVE_EASYSETUP */
64
65 #include <modest-widget-memory.h>
66 #include <tny-error.h>
67 #include <tny-simple-list.h>
68 #include <tny-msg-view.h>
69 #include <tny-device.h>
70
71 typedef struct _GetMsgAsyncHelper {     
72         ModestWindow *window;
73         ModestMailOperation *mail_op;
74         TnyIterator *iter;
75         guint num_ops;
76         GFunc func;     
77         gpointer user_data;
78 } GetMsgAsyncHelper;
79
80 typedef enum _ReplyForwardAction {
81         ACTION_REPLY,
82         ACTION_REPLY_TO_ALL,
83         ACTION_FORWARD
84 } ReplyForwardAction;
85
86 typedef struct _ReplyForwardHelper {
87 guint reply_forward_type;
88         ReplyForwardAction action;
89         gchar *account_name;
90         guint pending_ops;
91 } ReplyForwardHelper;
92
93 typedef struct _HeaderActivatedHelper {
94         GtkTreeModel *model;
95         GtkTreeIter iter;
96         TnyFolder *folder;
97 } HeaderActivatedHelper;
98
99 /*
100  * The do_headers_action uses this kind of functions to perform some
101  * action to each member of a list of headers
102  */
103 typedef void (*HeadersFunc) (TnyHeader *header, ModestWindow *win, gpointer user_data);
104
105 static void
106 do_headers_action (ModestWindow *win, 
107                    HeadersFunc func,
108                    gpointer user_data);
109
110
111 static void     open_msg_func          (const GObject *obj, const TnyMsg *msg, gpointer user_data);
112
113 static void     reply_forward_func     (const GObject *obj, const TnyMsg *msg, gpointer user_data);
114
115 static void     reply_forward          (ReplyForwardAction action, ModestWindow *win);
116
117 static gchar*   ask_for_folder_name    (GtkWindow *parent_window, const gchar *title);
118
119 void   
120 modest_ui_actions_on_about (GtkAction *action, ModestWindow *win)
121 {
122         GtkWidget *about;
123         const gchar *authors[] = {
124                 "Dirk-Jan C. Binnema <dirk-jan.binnema@nokia.com>",
125                 NULL
126         };
127         about = gtk_about_dialog_new ();
128         gtk_about_dialog_set_name (GTK_ABOUT_DIALOG(about), PACKAGE_NAME);
129         gtk_about_dialog_set_version (GTK_ABOUT_DIALOG(about),PACKAGE_VERSION);
130         gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG(about),
131                                         _("Copyright (c) 2006, Nokia Corporation\n"
132                                           "All rights reserved."));
133         gtk_about_dialog_set_comments (GTK_ABOUT_DIALOG(about),
134                                        _("a modest e-mail client\n\n"
135                                          "design and implementation: Dirk-Jan C. Binnema\n"
136                                          "contributions from the fine people at KC and Ig\n"
137                                          "uses the tinymail email framework written by Philip van Hoof"));
138         gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG(about), authors);
139         gtk_about_dialog_set_website (GTK_ABOUT_DIALOG(about), "http://modest.garage.maemo.org");
140         
141         gtk_dialog_run (GTK_DIALOG (about));
142         gtk_widget_destroy(about);
143 }
144
145
146 static TnyList *
147 get_selected_headers (ModestWindow *win)
148 {
149         if (MODEST_IS_MAIN_WINDOW(win)) {
150                 GtkWidget *header_view;         
151                 
152                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(win),
153                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
154                 return modest_header_view_get_selected_headers (MODEST_HEADER_VIEW(header_view));
155                 
156         } else if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
157                 /* for MsgViewWindows, we simply return a list with one element */
158                 TnyMsg *msg;
159                 TnyHeader *header;
160                 TnyList *list = NULL;
161                 
162                 msg  = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW(win));
163                 if (msg) {
164                         header = tny_msg_get_header (msg);
165                         list = tny_simple_list_new ();
166                         tny_list_prepend (list, G_OBJECT(header));
167                         g_object_unref (G_OBJECT(header));
168                 }
169                 return list;
170
171         } else
172                 return NULL;
173 }
174
175 static void
176 headers_action_delete (TnyHeader *header,
177                        ModestWindow *win,
178                        gpointer user_data)
179 {
180         ModestMailOperation *mail_op;
181
182         /* TODO: add confirmation dialog */
183         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_DELETE, G_OBJECT(win));
184         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
185                                          mail_op);
186
187         /* Always delete. TODO: Move to trash still not supported */
188         modest_mail_operation_remove_msg (mail_op, header, FALSE);
189         g_object_unref (G_OBJECT (mail_op));
190 }
191
192 void
193 modest_ui_actions_on_delete (GtkAction *action, ModestWindow *win)
194 {
195         g_return_if_fail (MODEST_IS_WINDOW(win));
196
197         if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
198                 gboolean ret_value;
199                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
200                 return;
201         }
202                 
203         /* Remove each header */
204         do_headers_action (win, headers_action_delete, NULL);
205
206         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
207                 gtk_widget_destroy (GTK_WIDGET(win));
208         } 
209 }
210
211
212 void
213 modest_ui_actions_on_quit (GtkAction *action, ModestWindow *win)
214 {
215         #ifdef MODEST_PLATFORM_MAEMO
216         modest_osso_save_state();
217         #endif /* MODEST_PLATFORM_MAEMO */
218         
219         gtk_main_quit ();
220 }
221
222 void
223 modest_ui_actions_on_close_window (GtkAction *action, ModestWindow *win)
224 {
225         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
226                 gtk_widget_destroy (GTK_WIDGET (win));
227         } else if (MODEST_IS_MSG_EDIT_WINDOW (win)) {
228                 gboolean ret_value;
229                 g_signal_emit_by_name (G_OBJECT (win), "delete-event", NULL, &ret_value);
230         } else if (MODEST_IS_WINDOW (win)) {
231                 gtk_widget_destroy (GTK_WIDGET (win));
232         } else {
233                 g_return_if_reached ();
234         }
235 }
236
237 void
238 modest_ui_actions_on_add_to_contacts (GtkAction *action, ModestWindow *win)
239 {
240         GtkClipboard *clipboard = NULL;
241         gchar *selection = NULL;
242
243         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
244         selection = gtk_clipboard_wait_for_text (clipboard);
245
246         modest_address_book_add_address (selection);
247         g_free (selection);
248 }
249
250 void
251 modest_ui_actions_on_accounts (GtkAction *action, ModestWindow *win)
252 {
253         
254         /* This is currently only implemented for Maemo,
255          * because it requires a providers preset file which is not publically available.
256          */
257 #ifdef MODEST_PLATFORM_MAEMO /* Defined in config.h */
258         GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
259                                 TRUE /* enabled accounts only */);
260         gboolean accounts_exist = account_names != NULL;
261         g_slist_free (account_names);
262         
263         if (!accounts_exist) {
264                 /* If there are no accounts yet, just show the easy-setup wizard, as per the UI spec: */
265                 ModestEasysetupWizardDialog *wizard = modest_easysetup_wizard_dialog_new ();
266                 gtk_window_set_transient_for (GTK_WINDOW (wizard), GTK_WINDOW (win));
267                 gtk_dialog_run (GTK_DIALOG (wizard));
268                 gtk_widget_destroy (GTK_WIDGET (wizard));
269         } else  {
270                 /* Show the list of accounts: */
271                 GtkDialog *account_win = GTK_DIALOG(modest_account_view_window_new ());
272                 gtk_window_set_transient_for (GTK_WINDOW (account_win), GTK_WINDOW(win));
273                 gtk_dialog_run (account_win);
274                 gtk_widget_destroy (GTK_WIDGET(account_win));
275         }
276 #else
277         GtkWidget *dialog, *label;
278         
279         /* Create the widgets */
280         
281         dialog = gtk_dialog_new_with_buttons ("Message",
282                                               GTK_WINDOW(win),
283                                               GTK_DIALOG_DESTROY_WITH_PARENT,
284                                               GTK_STOCK_OK,
285                                               GTK_RESPONSE_NONE,
286                                               NULL);
287         label = gtk_label_new ("Hello World!");
288         
289         /* Ensure that the dialog box is destroyed when the user responds. */
290         
291         g_signal_connect_swapped (dialog, "response", 
292                                   G_CALLBACK (gtk_widget_destroy),
293                                   dialog);
294         
295         /* Add the label, and show everything we've added to the dialog. */
296         
297         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
298                            label);
299         gtk_widget_show_all (dialog);
300 #endif /* MODEST_PLATFORM_MAEMO */
301 }
302
303 void
304 modest_ui_actions_on_new_msg (GtkAction *action, ModestWindow *win)
305 {
306         ModestWindow *msg_win;
307         TnyMsg *msg = NULL;
308         TnyFolder *folder = NULL;
309         gchar *account_name = NULL;
310         gchar *from_str = NULL;
311 /*      GError *err = NULL; */
312         TnyAccount *account = NULL;
313         ModestWindowMgr *mgr;
314         gchar *signature = NULL;
315         
316         account_name = g_strdup(modest_window_get_active_account (win));
317         if (!account_name)
318                 account_name = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
319         if (!account_name) {
320                 g_printerr ("modest: no account found\n");
321                 goto cleanup;
322         }
323         
324         account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
325                                                                        account_name,
326                                                                        TNY_ACCOUNT_TYPE_STORE);
327         if (!account) {
328                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", account_name);
329                 goto cleanup;
330         }
331
332         from_str = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(), account_name);
333         if (!from_str) {
334                 g_printerr ("modest: failed get from string for '%s'\n", account_name);
335                 goto cleanup;
336         }
337
338         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr (), account_name,
339                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
340                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (), account_name,
341                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
342         } else {
343                 signature = g_strdup ("");
344         }
345
346         msg = modest_tny_msg_new ("", from_str, "", "", "", signature, NULL);
347         if (!msg) {
348                 g_printerr ("modest: failed to create new msg\n");
349                 goto cleanup;
350         }
351         
352         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
353         if (!folder) {
354                 g_printerr ("modest: failed to find Drafts folder\n");
355                 goto cleanup;
356         }
357         
358 /*      tny_folder_add_msg (folder, msg, &err); */
359 /*      if (err) { */
360 /*              g_printerr ("modest: error adding msg to Drafts folder: %s", */
361 /*                          err->message); */
362 /*              g_error_free (err); */
363 /*              goto cleanup; */
364 /*      } */
365
366         /* Create and register edit window */
367         msg_win = modest_msg_edit_window_new (msg, account_name);
368         mgr = modest_runtime_get_window_mgr ();
369         modest_window_mgr_register_window (mgr, msg_win);
370
371         if (win)
372                 gtk_window_set_transient_for (GTK_WINDOW (msg_win),
373                                               GTK_WINDOW (win));        
374         gtk_widget_show_all (GTK_WIDGET (msg_win));
375
376 cleanup:
377         g_free (account_name);
378         g_free (from_str);
379         g_free (signature);
380         if (account)
381                 g_object_unref (G_OBJECT(account));
382         if (msg)
383                 g_object_unref (G_OBJECT(msg));
384         if (folder)
385                 g_object_unref (G_OBJECT(folder));
386 }
387
388 static void
389 headers_action_open (TnyHeader *header, 
390                      ModestWindow *win, 
391                      gpointer user_data)
392 {
393         modest_ui_actions_on_header_activated (MODEST_HEADER_VIEW (user_data), 
394                                                header,
395                                                MODEST_MAIN_WINDOW (win));
396 }
397
398 void
399 modest_ui_actions_on_open (GtkAction *action, ModestWindow *win)
400 {
401         GtkWidget *header_view;
402
403         /* Get header view */
404         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
405                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
406
407         /* Open each message */
408         do_headers_action (win, headers_action_open, header_view);
409 }
410
411
412 static void
413 open_msg_func (const GObject *obj, const TnyMsg *msg, gpointer user_data)
414 {
415         ModestWindowMgr *mgr = NULL;
416         ModestWindow *parent_win = NULL;
417         ModestWindow *win = NULL;
418         HeaderActivatedHelper *helper = NULL;
419         TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN;
420         gchar *account = NULL;
421         
422         g_return_if_fail (MODEST_IS_WINDOW(obj));
423         g_return_if_fail (user_data != NULL);
424         parent_win = MODEST_WINDOW(obj);
425         helper = (HeaderActivatedHelper *) user_data;
426
427         /* Get account */
428         account =  g_strdup(modest_window_get_active_account(MODEST_WINDOW(parent_win)));
429         if (!account)
430                 account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
431         
432         /* Gets foldert type (OUTBOX headers will be opened in edit window */
433 /*      folder_type = modest_tny_folder_guess_folder_type (helper->folder); */
434         if (modest_tny_folder_is_local_folder (helper->folder))
435                 folder_type = modest_tny_folder_get_local_folder_type (helper->folder);
436
437         switch (folder_type) {
438         case TNY_FOLDER_TYPE_DRAFTS:
439                 win = modest_msg_edit_window_new ((TnyMsg *) msg, account);
440                 break;
441         default:
442                 if (helper->model != NULL)
443                         win = modest_msg_view_window_new_with_header_model ((TnyMsg *) msg, account, helper->model, helper->iter);
444                 else
445                         win = modest_msg_view_window_new ((TnyMsg *) msg, account);
446         }
447                 
448         /* Register and show new window */
449         if (win != NULL) {
450                 mgr = modest_runtime_get_window_mgr ();
451                 modest_window_mgr_register_window (mgr, win);
452                 gtk_window_set_transient_for (GTK_WINDOW (win), GTK_WINDOW (parent_win));
453                 gtk_widget_show_all (GTK_WIDGET(win));
454         }
455
456         /* Free */
457         g_free(account);
458 /*      g_object_unref (G_OBJECT(msg)); */
459         g_object_unref (G_OBJECT(helper->folder));
460         g_slice_free (HeaderActivatedHelper, helper);
461 }
462
463 static void
464 reply_forward_func (const GObject *obj, const TnyMsg *msg, gpointer user_data)
465 {
466         TnyMsg *new_msg;
467         ReplyForwardHelper *rf_helper;
468         ModestWindow *msg_win;
469         ModestEditType edit_type;
470         gchar *from;
471         GError *err = NULL;
472         TnyFolder *folder = NULL;
473         TnyAccount *account = NULL;
474         ModestWindowMgr *mgr;
475         gchar *signature = NULL;
476                         
477         g_return_if_fail (user_data != NULL);
478         rf_helper = (ReplyForwardHelper *) user_data;
479
480         rf_helper->pending_ops--;
481
482         from = modest_account_mgr_get_from_string (modest_runtime_get_account_mgr(),
483                                                    rf_helper->account_name);
484         if (modest_account_mgr_get_bool (modest_runtime_get_account_mgr(),
485                                          rf_helper->account_name,
486                                          MODEST_ACCOUNT_USE_SIGNATURE, FALSE)) {
487                 signature = modest_account_mgr_get_string (modest_runtime_get_account_mgr (),
488                                                            rf_helper->account_name,
489                                                            MODEST_ACCOUNT_SIGNATURE, FALSE);
490         }
491
492         /* Create reply mail */
493         switch (rf_helper->action) {
494         case ACTION_REPLY:
495                 new_msg = 
496                         modest_tny_msg_create_reply_msg ((TnyMsg *) msg,  from, signature,
497                                                          rf_helper->reply_forward_type,
498                                                          MODEST_TNY_MSG_REPLY_MODE_SENDER);
499                 break;
500         case ACTION_REPLY_TO_ALL:
501                 new_msg = 
502                         modest_tny_msg_create_reply_msg ((TnyMsg *) msg, from, signature, rf_helper->reply_forward_type,
503                                                          MODEST_TNY_MSG_REPLY_MODE_ALL);
504                 edit_type = MODEST_EDIT_TYPE_REPLY;
505                 break;
506         case ACTION_FORWARD:
507                 new_msg = 
508                         modest_tny_msg_create_forward_msg ((TnyMsg *) msg, from, signature, rf_helper->reply_forward_type);
509                 edit_type = MODEST_EDIT_TYPE_FORWARD;
510                 break;
511         default:
512                 g_return_if_reached ();
513                 return;
514         }
515
516         g_free (signature);
517
518         if (!new_msg) {
519                 g_printerr ("modest: failed to create message\n");
520                 goto cleanup;
521         }
522
523         account = modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
524                                                                        rf_helper->account_name,
525                                                                        TNY_ACCOUNT_TYPE_STORE);
526         if (!account) {
527                 g_printerr ("modest: failed to get tnyaccount for '%s'\n", rf_helper->account_name);
528                 goto cleanup;
529         }
530
531         folder = modest_tny_account_get_special_folder (account, TNY_FOLDER_TYPE_DRAFTS);
532         if (!folder) {
533                 g_printerr ("modest: failed to find Drafts folder\n");
534                 goto cleanup;
535         }
536         
537         tny_folder_add_msg (folder, (TnyMsg *) msg, &err);
538         if (err) {
539                 g_printerr ("modest: error adding msg to Drafts folder: %s",
540                             err->message);
541                 g_error_free (err);
542                 goto cleanup;
543         }       
544
545         /* Create and register the windows */                   
546         msg_win = modest_msg_edit_window_new (new_msg, rf_helper->account_name);
547         mgr = modest_runtime_get_window_mgr ();
548         modest_window_mgr_register_window (mgr, msg_win);
549
550         /* Show edit window */
551         gtk_widget_show_all (GTK_WIDGET (msg_win));
552
553 cleanup:
554         if (new_msg)
555                 g_object_unref (G_OBJECT (new_msg));
556         if (folder)
557                 g_object_unref (G_OBJECT (folder));
558         if (account)
559                 g_object_unref (G_OBJECT (account));
560         
561         if (rf_helper->pending_ops == 0) {
562                 g_free (rf_helper->account_name);
563                 g_slice_free (ReplyForwardHelper, rf_helper);
564         }
565 }
566 /*
567  * Common code for the reply and forward actions
568  */
569 static void
570 reply_forward (ReplyForwardAction action, ModestWindow *win)
571 {
572         ModestMailOperation *mail_op = NULL;
573         TnyList *header_list = NULL;
574         ReplyForwardHelper *rf_helper = NULL;
575         guint reply_forward_type;
576         
577         g_return_if_fail (MODEST_IS_WINDOW(win));
578
579         header_list = get_selected_headers (win);
580         if (!header_list)
581                 return;
582         
583         reply_forward_type = modest_conf_get_int (modest_runtime_get_conf (),
584                                                   (action == ACTION_FORWARD) ? MODEST_CONF_FORWARD_TYPE : MODEST_CONF_REPLY_TYPE,
585                                                   NULL);
586         /* We assume that we can only select messages of the
587            same folder and that we reply all of them from the
588            same account. In fact the interface currently only
589            allows single selection */
590         
591         /* Fill helpers */
592         rf_helper = g_slice_new0 (ReplyForwardHelper);
593         rf_helper->reply_forward_type = reply_forward_type;
594         rf_helper->action = action;
595         rf_helper->pending_ops = tny_list_get_length (header_list);
596         rf_helper->account_name = g_strdup (modest_window_get_active_account (win));
597         if (!rf_helper->account_name)
598                 rf_helper->account_name =
599                         modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
600
601         if (MODEST_IS_MSG_VIEW_WINDOW(win)) {
602                 TnyMsg *msg;
603                 msg = modest_msg_view_window_get_message(MODEST_MSG_VIEW_WINDOW(win));
604                 if (!msg) {
605                         g_printerr ("modest: no message found\n");
606                         return;
607                 } else
608                         reply_forward_func (G_OBJECT(win), msg, rf_helper);
609         } else {
610                                 
611                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
612                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
613                 modest_mail_operation_process_msg (mail_op, header_list, reply_forward_func, rf_helper);
614
615                 /* Clean */
616                 g_object_unref(mail_op);
617         }
618 }
619
620 void
621 modest_ui_actions_on_reply (GtkAction *action, ModestWindow *win)
622 {
623         g_return_if_fail (MODEST_IS_WINDOW(win));
624
625         reply_forward (ACTION_REPLY, win);
626 }
627
628 void
629 modest_ui_actions_on_forward (GtkAction *action, ModestWindow *win)
630 {
631         g_return_if_fail (MODEST_IS_WINDOW(win));
632
633         reply_forward (ACTION_FORWARD, win);
634 }
635
636 void
637 modest_ui_actions_on_reply_all (GtkAction *action, ModestWindow *win)
638 {
639         g_return_if_fail (MODEST_IS_WINDOW(win));
640
641         reply_forward (ACTION_REPLY_TO_ALL, win);
642 }
643
644 void 
645 modest_ui_actions_on_next (GtkAction *action, 
646                            ModestWindow *window)
647 {
648         if (MODEST_IS_MAIN_WINDOW (window)) {
649                 GtkWidget *header_view;
650
651                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
652                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
653                 if (!header_view)
654                         return;
655         
656                 modest_header_view_select_next (MODEST_HEADER_VIEW(header_view)); 
657         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
658                 modest_msg_view_window_select_next_message (MODEST_MSG_VIEW_WINDOW (window));
659         } else {
660                 g_return_if_reached ();
661         }
662 }
663
664 void 
665 modest_ui_actions_on_prev (GtkAction *action, 
666                            ModestWindow *window)
667 {
668         g_return_if_fail (MODEST_IS_WINDOW(window));
669
670         if (MODEST_IS_MAIN_WINDOW (window)) {
671                 GtkWidget *header_view;
672                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
673                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
674                 if (!header_view)
675                         return;
676                 
677                 modest_header_view_select_prev (MODEST_HEADER_VIEW(header_view)); 
678         } else if (MODEST_IS_MSG_VIEW_WINDOW (window)) {
679                 modest_msg_view_window_select_previous_message (MODEST_MSG_VIEW_WINDOW (window));
680         } else {
681                 g_return_if_reached ();
682         }
683 }
684
685 void 
686 modest_ui_actions_on_sort (GtkAction *action, 
687                            ModestWindow *window)
688 {
689         g_return_if_fail (MODEST_IS_WINDOW(window));
690
691         if (MODEST_IS_MAIN_WINDOW (window)) {
692                 GtkWidget *header_view;
693                 header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW(window),
694                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
695                 if (!header_view)
696                         return;
697
698                 /* Show sorting dialog */
699                 modest_platform_run_sort_dialog (GTK_WINDOW (window), MODEST_SORT_HEADERS);     
700         }
701 }
702
703
704 static gboolean
705 action_send (const gchar* account_name)
706 {
707         TnyAccount *tny_account;
708         ModestTnySendQueue *send_queue;
709
710         g_return_val_if_fail (account_name, FALSE);
711
712         /* Get the transport account according to the open connection, 
713          * because the account might specify connection-specific SMTP servers.
714          */
715         tny_account = 
716                 modest_tny_account_store_get_transport_account_for_open_connection (modest_runtime_get_account_store(),
717                                                                      account_name);
718         if (!tny_account) {
719                 g_printerr ("modest: cannot get tny transport account for %s\n", account_name);
720                 return FALSE;
721         }
722         
723         send_queue = modest_tny_send_queue_new (TNY_CAMEL_TRANSPORT_ACCOUNT(tny_account));
724         if (!send_queue) {
725                 g_object_unref (G_OBJECT(tny_account));
726                 g_printerr ("modest: cannot get send queue for %s\n", account_name);
727                 return FALSE;
728         }
729         
730         modest_tny_send_queue_flush (send_queue);
731
732         g_object_unref (G_OBJECT(send_queue));
733         g_object_unref (G_OBJECT(tny_account));
734
735         return TRUE;
736 }
737
738
739 static gboolean
740 action_receive (const gchar* account_name, 
741                 ModestWindow *win)
742 {
743         TnyAccount *tny_account;
744         ModestMailOperation *mail_op;
745
746         g_return_val_if_fail (account_name, FALSE);
747
748         tny_account = 
749                 modest_tny_account_store_get_tny_account_by_account (modest_runtime_get_account_store(),
750                                                                      account_name,
751                                                                      TNY_ACCOUNT_TYPE_STORE);
752         if (!tny_account) {
753                 g_printerr ("modest: cannot get tny store account for %s\n", account_name);
754                 return FALSE;
755         }
756
757         /* Create the mail operation */
758         /* TODO: The spec wants us to first do any pending deletions, before receiving. */
759         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
760         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
761         modest_mail_operation_update_account (mail_op, TNY_STORE_ACCOUNT(tny_account));
762
763         g_object_unref (G_OBJECT(tny_account));
764         g_object_unref (G_OBJECT (mail_op));
765                 
766         return TRUE;
767 }
768
769 /** Check that an appropriate connection is open.
770  */
771 gboolean check_for_connection (const gchar *account_name)
772 {
773         TnyDevice *device = modest_runtime_get_device ();
774
775 /*
776         g_assert (TNY_IS_MAEMO_CONIC_DEVICE (device));
777         
778         TnyMaemoConicDevice *maemo_device = TNY_MAEMO_CONIC_DEVICE (device);
779 */
780         
781         if (tny_device_is_online (device))
782                 return TRUE;
783         else {
784                 modest_platform_connect_and_wait (NULL);
785                 
786                 /* TODO: Wait until a result. */
787                 return TRUE;
788         }
789 }
790         
791 static void
792 do_send_receive_current_or_default (ModestWindow *win)
793 {
794         gchar *account_name;
795
796         g_message ("%s: online? %s", __FUNCTION__,  
797                 tny_device_is_online(modest_runtime_get_device()) ? "yes":"no");
798                                 
799         /* As per the UI spec, only the active account should be affected, 
800          * else the default folder if there is no active account: */                            
801         account_name =
802                 g_strdup(modest_window_get_active_account(MODEST_WINDOW(win)));
803         if (!account_name)
804                 account_name  = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr());
805         if (!account_name) {
806                 g_printerr ("modest: cannot get default account\n");
807                 return;
808         }
809         
810         /* Do not continue if no suitable connection is open: */
811         if (check_for_connection (account_name)) {
812                 /* As per the UI spec,
813                  * for POP accounts, we should receive,
814                  * for IMAP we should synchronize everything, including receiving,
815                  * for SMTP we should send,
816                  * first receiving, then sending:
817                  */
818                 if (!action_receive(account_name, win))
819                         g_printerr ("modest: failed to receive\n");
820                 if (!action_send(account_name))
821                         g_printerr ("modest: failed to send\n");
822                 
823                 g_free (account_name);
824         }
825 }
826
827
828 static void
829 do_send_receive_auto (ModestWindow *win)
830 {
831         g_message ("%s: online? %s", __FUNCTION__,  
832                 tny_device_is_online(modest_runtime_get_device()) ? "yes":"no");
833
834         /* TODO: Delete the item->data strings as well as the list? */
835         GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(), 
836                                 TRUE /* enabled accounts only */);
837         GSList *iter = account_names;
838         while (iter) {                  
839                 const gchar * account_name = (const char*) iter->data;
840                 
841                 /* Do not continue if no suitable connection is open: */
842                 if (account_name && check_for_connection (account_name)) {
843                         /* As per the UI spec,
844                          * for POP accounts, we should receive,
845                          * for IMAP we should synchronize everything, including receiving,
846                          * for SMTP we should send,
847                          * first receiving, then sending:
848                          */
849                         if (!action_receive(account_name, win))
850                                 g_printerr ("modest: failed to receive for account %s\n", account_name);
851                         if (!action_send(account_name))
852                                 g_printerr ("modest: failed to send for account %s\n", account_name);
853                 }
854         }
855         
856         
857         g_slist_free (account_names);
858 }
859
860 void
861 do_send_receive (ModestWindow *win)
862 {
863         const gboolean auto_update = TRUE; /* TODO: Get gconf setting. */
864         if (auto_update)
865                 do_send_receive_current_or_default (win);
866         else
867                 do_send_receive_auto (win);
868 }
869
870 void
871 modest_ui_actions_on_send_receive (GtkAction *action,  ModestWindow *win)
872 {
873         /* Check that at least one account exists: */
874         GSList *account_names = modest_account_mgr_account_names (modest_runtime_get_account_mgr(),
875                                 TRUE /* enabled accounts only */);
876         gboolean accounts_exist = account_names != NULL;
877         g_slist_free (account_names);
878         
879         /* If not, allow the user to create an account before trying to send/receive. */
880         if (!accounts_exist) {
881                 modest_ui_actions_on_accounts (NULL, win);
882         }
883                 
884         do_send_receive (win);
885 }
886
887
888
889
890 void
891 modest_ui_actions_toggle_header_list_view (GtkAction *action, ModestMainWindow *main_window)
892 {
893         ModestConf *conf;
894         GtkWidget *header_view;
895         
896         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
897
898         header_view = modest_main_window_get_child_widget (main_window,
899                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
900         if (!header_view)
901                 return;
902
903         conf = modest_runtime_get_conf ();
904         
905         /* what is saved/restored is depending on the style; thus; we save with
906          * old style, then update the style, and restore for this new style
907          */
908         modest_widget_memory_save (conf, G_OBJECT(header_view), MODEST_CONF_HEADER_VIEW_KEY);
909         
910         if (modest_header_view_get_style
911             (MODEST_HEADER_VIEW(header_view)) == MODEST_HEADER_VIEW_STYLE_DETAILS)
912                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
913                                               MODEST_HEADER_VIEW_STYLE_TWOLINES);
914         else
915                 modest_header_view_set_style (MODEST_HEADER_VIEW(header_view),
916                                               MODEST_HEADER_VIEW_STYLE_DETAILS);
917
918         modest_widget_memory_restore (conf, G_OBJECT(header_view),
919                                       MODEST_CONF_HEADER_VIEW_KEY);
920 }
921
922
923 void 
924 modest_ui_actions_on_header_selected (ModestHeaderView *header_view, 
925                                       TnyHeader *header,
926                                       ModestMainWindow *main_window)
927 {
928         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
929
930         /* If no header has been selected then exit */
931         if (!header)
932                 return;
933
934         /* Update Main window title */
935         if (GTK_WIDGET_HAS_FOCUS (header_view)) {
936                 const gchar *subject = tny_header_get_subject (header);
937                 if (subject && strcmp (subject, ""))
938                         gtk_window_set_title (GTK_WINDOW (main_window), subject);
939                 else
940                         gtk_window_set_title (GTK_WINDOW (main_window), _("mail_va_no_subject"));
941         }
942 }
943
944
945
946 /* void */
947 /* modest_ui_actions_on_header_activated (ModestHeaderView *header_view, TnyHeader *header, */
948 /*                                     ModestMainWindow *main_window) */
949 /* { */
950 /*      ModestWindow *win = NULL; */
951 /*      TnyFolder *folder = NULL; */
952 /*      TnyMsg    *msg    = NULL; */
953 /*      TnyFolderType folder_type = TNY_FOLDER_TYPE_UNKNOWN; */
954 /*      ModestWindowMgr *mgr; */
955 /*      GtkTreeModel *model; */
956 /*      GtkTreeIter iter; */
957 /*      GtkTreeSelection *sel = NULL; */
958 /*      GList *sel_list = NULL; */
959         
960 /*      g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window)); */
961         
962 /*      if (!header) */
963 /*              return; */
964
965 /*      folder = tny_header_get_folder (header); */
966 /*      if (!folder) { */
967 /*              g_printerr ("modest: cannot get folder for header\n"); */
968 /*              return; */
969 /*      } */
970 /*      if (modest_tny_folder_is_local_folder (folder)) */
971 /*              folder_type = modest_tny_folder_get_local_folder_type (folder); */
972
973 /*      /\* FIXME: make async?; check error  *\/ */
974 /*      msg = tny_folder_get_msg (folder, header, NULL); */
975 /*      if (!msg) { */
976 /*              g_printerr ("modest: cannot get msg for header\n"); */
977 /*              goto cleanup; */
978 /*      } */
979
980 /*      /\* Look if we already have a message view for that header *\/ */
981 /*      mgr = modest_runtime_get_window_mgr (); */
982 /*      win = modest_window_mgr_find_window_by_msguid (mgr, tny_header_get_uid (header)); */
983
984 /*      /\* If not, create a new window *\/ */
985 /*      if (!win) { */
986 /*              gchar *account; */
987
988 /*              account =  g_strdup(modest_window_get_active_account(MODEST_WINDOW(main_window))); */
989 /*              if (!account) */
990 /*                      account = modest_account_mgr_get_default_account (modest_runtime_get_account_mgr()); */
991
992 /*              sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view)); */
993 /*              sel_list = gtk_tree_selection_get_selected_rows (sel, &model); */
994 /*              if (sel_list != NULL) { */
995 /*                      gtk_tree_model_get_iter (model, &iter, (GtkTreePath *) sel_list->data); */
996                         
997 /*                      switch (folder_type) { */
998 /*                      case TNY_FOLDER_TYPE_DRAFTS: */
999 /*                              win = modest_msg_edit_window_new (msg, account); */
1000 /*                              break; */
1001 /*                      default: */
1002 /*                              win = modest_msg_view_window_new_with_header_model (msg, account, model, iter); */
1003 /*                      } */
1004
1005 /*                      g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL); */
1006 /*                      g_list_free (sel_list); */
1007 /*              } else { */
1008 /*                      win = modest_msg_view_window_new (msg, account); */
1009 /*              } */
1010 /*              modest_window_mgr_register_window (mgr, win); */
1011
1012 /*              gtk_window_set_transient_for (GTK_WINDOW (win), */
1013 /*                                            GTK_WINDOW (main_window)); */
1014 /*      } */
1015
1016 /*      gtk_widget_show_all (GTK_WIDGET(win)); */
1017
1018 /*      g_object_unref (G_OBJECT (msg)); */
1019         
1020 /* cleanup: */
1021 /*      g_object_unref (G_OBJECT (folder)); */
1022 /* } */
1023
1024 void
1025 modest_ui_actions_on_header_activated (ModestHeaderView *header_view,
1026                                        TnyHeader *header,
1027                                        ModestMainWindow *main_window)
1028 {
1029         ModestMailOperation *mail_op = NULL;
1030         HeaderActivatedHelper *helper = NULL;
1031         ModestWindowMgr *mgr = NULL;
1032         ModestWindow *win = NULL;
1033         GtkTreeModel *model = NULL;
1034         GtkTreeIter iter;
1035         GtkTreeSelection *sel = NULL;
1036         GList *sel_list = NULL;
1037         
1038         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1039         
1040         if (!header)
1041                 return;
1042
1043         /* Look if we already have a message view for that header */
1044         mgr = modest_runtime_get_window_mgr ();
1045         win = modest_window_mgr_find_window_by_msguid (mgr, tny_header_get_uid (header));
1046         if (win) return;
1047
1048         /* Build helper */
1049         helper = g_slice_new0 (HeaderActivatedHelper);
1050         helper->folder = tny_header_get_folder (header);
1051         helper->model = NULL;
1052
1053         /* Get headers tree model and selected iter to build message view */
1054         sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (header_view));
1055         sel_list = gtk_tree_selection_get_selected_rows (sel, &model);
1056         if (sel_list != NULL) {
1057                 gtk_tree_model_get_iter (model, &iter, (GtkTreePath *) sel_list->data);
1058                 
1059                 /* Fill helpers */
1060                 helper->model = model;
1061                 helper->iter = iter;
1062
1063                 g_list_foreach (sel_list, (GFunc) gtk_tree_path_free, NULL);
1064                 g_list_free (sel_list);
1065         }
1066
1067         /* New mail operation */
1068         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(main_window));
1069         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_op);
1070         modest_mail_operation_get_msg (mail_op, header, open_msg_func, helper);
1071
1072         /* Free */
1073         g_object_unref (mail_op);
1074 }
1075
1076 void 
1077 modest_ui_actions_on_folder_selection_changed (ModestFolderView *folder_view,
1078                                                TnyFolderStore *folder_store, 
1079                                                gboolean selected,
1080                                                ModestMainWindow *main_window)
1081 {
1082         ModestConf *conf;
1083         GtkWidget *header_view;
1084         
1085         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1086
1087         header_view = modest_main_window_get_child_widget(main_window,
1088                                                           MODEST_WIDGET_TYPE_HEADER_VIEW);
1089         if (!header_view)
1090                 return;
1091         
1092         conf = modest_runtime_get_conf ();
1093
1094         if (TNY_IS_FOLDER (folder_store)) {
1095
1096                 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_HEADERS);
1097
1098                 if (selected) {
1099                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view),
1100                                                        TNY_FOLDER (folder_store));
1101                         modest_widget_memory_restore (conf, G_OBJECT(header_view),
1102                                                       MODEST_CONF_HEADER_VIEW_KEY);
1103                 } else {
1104                         modest_widget_memory_save (conf, G_OBJECT (header_view), MODEST_CONF_HEADER_VIEW_KEY);
1105                         modest_header_view_set_folder (MODEST_HEADER_VIEW(header_view), NULL);
1106                 }
1107         } else if (TNY_IS_ACCOUNT (folder_store)) {
1108
1109                 modest_main_window_set_contents_style (main_window, MODEST_MAIN_WINDOW_CONTENTS_STYLE_DETAILS);
1110         }
1111 }
1112
1113 void 
1114 modest_ui_actions_on_item_not_found (ModestHeaderView *header_view,ModestItemType type,
1115                                      ModestWindow *win)
1116 {
1117         GtkWidget *dialog;
1118         gchar *txt, *item;
1119         gboolean online;
1120
1121         item = (type == MODEST_ITEM_TYPE_FOLDER) ? "folder" : "message";
1122         
1123         if (g_main_depth > 0)   
1124                 gdk_threads_enter ();
1125         online = tny_device_is_online (modest_runtime_get_device());
1126
1127         if (online) {
1128                 /* already online -- the item is simply not there... */
1129                 dialog = gtk_message_dialog_new (GTK_WINDOW (win),
1130                                                  GTK_DIALOG_MODAL,
1131                                                  GTK_MESSAGE_WARNING,
1132                                                  GTK_BUTTONS_OK,
1133                                                  _("The %s you selected cannot be found"),
1134                                                  item);
1135                 gtk_dialog_run (GTK_DIALOG(dialog));
1136         } else {
1137                 dialog = gtk_dialog_new_with_buttons (_("Connection requested"),
1138                                                       GTK_WINDOW (win),
1139                                                       GTK_DIALOG_MODAL,
1140                                                       GTK_STOCK_CANCEL,
1141                                                       GTK_RESPONSE_REJECT,
1142                                                       GTK_STOCK_OK,
1143                                                       GTK_RESPONSE_ACCEPT,
1144                                                       NULL);
1145                 txt = g_strdup_printf (_("This %s is not available in offline mode.\n"
1146                                          "Do you want to get online?"), item);
1147                 gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1148                                     gtk_label_new (txt), FALSE, FALSE, 0);
1149                 gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1150                 g_free (txt);
1151
1152                 gtk_window_set_default_size (GTK_WINDOW(dialog), 300, 300);
1153                 if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1154 //                      modest_platform_connect_and_wait ();;
1155                 }
1156         }
1157         gtk_widget_destroy (dialog);
1158         if (g_main_depth > 0)   
1159                 gdk_threads_leave ();
1160 }
1161
1162 void
1163 modest_ui_actions_on_msg_link_hover (ModestMsgView *msgview, const gchar* link,
1164                                      ModestWindow *win)
1165 {
1166         /* g_message ("%s %s", __FUNCTION__, link); */
1167 }       
1168
1169
1170 void
1171 modest_ui_actions_on_msg_link_clicked (ModestMsgView *msgview, const gchar* link,
1172                                         ModestWindow *win)
1173 {
1174         modest_platform_activate_uri (link);
1175 }
1176
1177 void
1178 modest_ui_actions_on_msg_link_contextual (ModestMsgView *msgview, const gchar* link,
1179                                           ModestWindow *win)
1180 {
1181         modest_platform_show_uri_popup (link);
1182 }
1183
1184 void
1185 modest_ui_actions_on_msg_attachment_clicked (ModestMsgView *msgview, TnyMimePart *mime_part,
1186                                              ModestWindow *win)
1187 {
1188         /* g_message (__FUNCTION__); */
1189         
1190 }
1191
1192 void
1193 modest_ui_actions_on_msg_recpt_activated (ModestMsgView *msgview,
1194                                           const gchar *address,
1195                                           ModestWindow *win)
1196 {
1197         /* g_message ("%s %s", __FUNCTION__, address); */
1198 }
1199
1200 void
1201 modest_ui_actions_on_save_to_drafts (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1202 {
1203         TnyTransportAccount *transport_account;
1204         ModestMailOperation *mail_operation;
1205         MsgData *data;
1206         gchar *account_name, *from;
1207         ModestAccountMgr *account_mgr;
1208
1209         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1210         
1211         data = modest_msg_edit_window_get_msg_data (edit_window);
1212
1213         account_mgr = modest_runtime_get_account_mgr();
1214         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1215         if (!account_name) 
1216                 account_name = modest_account_mgr_get_default_account (account_mgr);
1217         if (!account_name) {
1218                 g_printerr ("modest: no account found\n");
1219                 modest_msg_edit_window_free_msg_data (edit_window, data);
1220                 return;
1221         }
1222         transport_account =
1223                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_tny_account_by_account
1224                                       (modest_runtime_get_account_store(),
1225                                        account_name,
1226                                        TNY_ACCOUNT_TYPE_TRANSPORT));
1227         if (!transport_account) {
1228                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1229                 g_free (account_name);
1230                 modest_msg_edit_window_free_msg_data (edit_window, data);
1231                 return;
1232         }
1233         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1234
1235         /* Create the mail operation */         
1236         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO, G_OBJECT(edit_window));
1237         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1238
1239         modest_mail_operation_save_to_drafts (mail_operation,
1240                                               transport_account,
1241                                               from,
1242                                               data->to, 
1243                                               data->cc, 
1244                                               data->bcc,
1245                                               data->subject, 
1246                                               data->plain_body, 
1247                                               data->html_body,
1248                                               data->attachments,
1249                                               data->priority_flags);
1250         /* Frees */
1251         g_free (from);
1252         g_free (account_name);
1253         g_object_unref (G_OBJECT (transport_account));
1254         g_object_unref (G_OBJECT (mail_operation));
1255
1256         modest_msg_edit_window_free_msg_data (edit_window, data);
1257
1258         /* Save settings and close the window */
1259         gtk_widget_destroy (GTK_WIDGET (edit_window));
1260 }
1261 void
1262 modest_ui_actions_on_send (GtkWidget *widget, ModestMsgEditWindow *edit_window)
1263 {
1264         TnyTransportAccount *transport_account;
1265         ModestMailOperation *mail_operation;
1266         MsgData *data;
1267         gchar *account_name, *from;
1268         ModestAccountMgr *account_mgr;
1269
1270         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW(edit_window));
1271
1272         if (!modest_msg_edit_window_check_names (edit_window))
1273                 return;
1274         
1275         data = modest_msg_edit_window_get_msg_data (edit_window);
1276
1277         /* FIXME: Code added just for testing. The final version will
1278            use the send queue provided by tinymail and some
1279            classifier */
1280         account_mgr = modest_runtime_get_account_mgr();
1281         account_name = g_strdup(modest_window_get_active_account (MODEST_WINDOW(edit_window)));
1282         if (!account_name) 
1283                 account_name = modest_account_mgr_get_default_account (account_mgr);
1284         if (!account_name) {
1285                 g_printerr ("modest: no account found\n");
1286                 modest_msg_edit_window_free_msg_data (edit_window, data);
1287                 return;
1288         }
1289         transport_account =
1290                 TNY_TRANSPORT_ACCOUNT(modest_tny_account_store_get_transport_account_for_open_connection
1291                                       (modest_runtime_get_account_store(),
1292                                        account_name));
1293         if (!transport_account) {
1294                 g_printerr ("modest: no transport account found for '%s'\n", account_name);
1295                 g_free (account_name);
1296                 modest_msg_edit_window_free_msg_data (edit_window, data);
1297                 return;
1298         }
1299         from = modest_account_mgr_get_from_string (account_mgr, account_name);
1300
1301         /* Create the mail operation */         
1302         mail_operation = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_SEND, G_OBJECT(edit_window));
1303         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), mail_operation);
1304
1305         modest_mail_operation_send_new_mail (mail_operation,
1306                                              transport_account,
1307                                              from,
1308                                              data->to, 
1309                                              data->cc, 
1310                                              data->bcc,
1311                                              data->subject, 
1312                                              data->plain_body, 
1313                                              data->html_body,
1314                                              data->attachments,
1315                                              data->priority_flags);
1316         /* Frees */
1317         g_free (from);
1318         g_free (account_name);
1319         g_object_unref (G_OBJECT (transport_account));
1320         g_object_unref (G_OBJECT (mail_operation));
1321
1322         modest_msg_edit_window_free_msg_data (edit_window, data);
1323
1324         /* Save settings and close the window */
1325         gtk_widget_destroy (GTK_WIDGET (edit_window));
1326 }
1327
1328 void 
1329 modest_ui_actions_on_toggle_bold (GtkToggleAction *action,
1330                                   ModestMsgEditWindow *window)
1331 {
1332         ModestMsgEditFormatState *format_state = NULL;
1333
1334         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1335         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1336
1337         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1338                 return;
1339
1340         format_state = modest_msg_edit_window_get_format_state (window);
1341         g_return_if_fail (format_state != NULL);
1342
1343         format_state->bold = gtk_toggle_action_get_active (action);
1344         modest_msg_edit_window_set_format_state (window, format_state);
1345         g_free (format_state);
1346         
1347 }
1348
1349 void 
1350 modest_ui_actions_on_toggle_italics (GtkToggleAction *action,
1351                                      ModestMsgEditWindow *window)
1352 {
1353         ModestMsgEditFormatState *format_state = NULL;
1354
1355         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1356         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1357
1358         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1359                 return;
1360
1361         format_state = modest_msg_edit_window_get_format_state (window);
1362         g_return_if_fail (format_state != NULL);
1363
1364         format_state->italics = gtk_toggle_action_get_active (action);
1365         modest_msg_edit_window_set_format_state (window, format_state);
1366         g_free (format_state);
1367         
1368 }
1369
1370 void 
1371 modest_ui_actions_on_toggle_bullets (GtkToggleAction *action,
1372                                      ModestMsgEditWindow *window)
1373 {
1374         ModestMsgEditFormatState *format_state = NULL;
1375
1376         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1377         g_return_if_fail (GTK_IS_TOGGLE_ACTION (action));
1378
1379         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW (window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1380                 return;
1381
1382         format_state = modest_msg_edit_window_get_format_state (window);
1383         g_return_if_fail (format_state != NULL);
1384
1385         format_state->bullet = gtk_toggle_action_get_active (action);
1386         modest_msg_edit_window_set_format_state (window, format_state);
1387         g_free (format_state);
1388         
1389 }
1390
1391 void 
1392 modest_ui_actions_on_change_justify (GtkRadioAction *action,
1393                                      GtkRadioAction *selected,
1394                                      ModestMsgEditWindow *window)
1395 {
1396         ModestMsgEditFormatState *format_state = NULL;
1397         GtkJustification value;
1398
1399         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1400
1401         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1402                 return;
1403
1404         value = gtk_radio_action_get_current_value (selected);
1405
1406         format_state = modest_msg_edit_window_get_format_state (window);
1407         g_return_if_fail (format_state != NULL);
1408
1409         format_state->justification = value;
1410         modest_msg_edit_window_set_format_state (window, format_state);
1411         g_free (format_state);
1412 }
1413
1414 void 
1415 modest_ui_actions_on_select_editor_color (GtkAction *action,
1416                                           ModestMsgEditWindow *window)
1417 {
1418         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1419         g_return_if_fail (GTK_IS_ACTION (action));
1420
1421         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1422                 return;
1423
1424         modest_msg_edit_window_select_color (window);
1425 }
1426
1427 void 
1428 modest_ui_actions_on_select_editor_background_color (GtkAction *action,
1429                                                      ModestMsgEditWindow *window)
1430 {
1431         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1432         g_return_if_fail (GTK_IS_ACTION (action));
1433
1434         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1435                 return;
1436
1437         modest_msg_edit_window_select_background_color (window);
1438 }
1439
1440 void 
1441 modest_ui_actions_on_insert_image (GtkAction *action,
1442                                    ModestMsgEditWindow *window)
1443 {
1444         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1445         g_return_if_fail (GTK_IS_ACTION (action));
1446
1447         if (modest_msg_edit_window_get_format (MODEST_MSG_EDIT_WINDOW(window)) == MODEST_MSG_EDIT_FORMAT_TEXT)
1448                 return;
1449
1450         modest_msg_edit_window_insert_image (window);
1451 }
1452
1453 /*
1454  * Shows a dialog with an entry that asks for some text. The returned
1455  * value must be freed by the caller. The dialog window title will be
1456  * set to @title.
1457  */
1458 static gchar *
1459 ask_for_folder_name (GtkWindow *parent_window,
1460                      const gchar *title)
1461 {
1462         GtkWidget *dialog, *entry;
1463         gchar *folder_name = NULL;
1464
1465         /* Ask for folder name */
1466         dialog = gtk_dialog_new_with_buttons (_("New Folder Name"),
1467                                               parent_window,
1468                                               GTK_DIALOG_MODAL,
1469                                               GTK_STOCK_CANCEL,
1470                                               GTK_RESPONSE_REJECT,
1471                                               GTK_STOCK_OK,
1472                                               GTK_RESPONSE_ACCEPT,
1473                                               NULL);
1474         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1475                             gtk_label_new(title),
1476                             FALSE, FALSE, 0);
1477                 
1478         entry = gtk_entry_new_with_max_length (40);
1479         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), 
1480                             entry,
1481                             TRUE, FALSE, 0);    
1482         
1483         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1484         
1485         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)         
1486                 folder_name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry)));
1487
1488         gtk_widget_destroy (dialog);
1489
1490         return folder_name;
1491 }
1492
1493 void 
1494 modest_ui_actions_on_new_folder (GtkAction *action, ModestMainWindow *main_window)
1495 {
1496         TnyFolderStore *parent_folder;
1497         GtkWidget *folder_view;
1498         
1499         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1500
1501         folder_view = modest_main_window_get_child_widget (main_window,
1502                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1503         if (!folder_view)
1504                 return;
1505
1506         parent_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1507         
1508         if (parent_folder) {
1509                 gboolean finished = FALSE;
1510                 gint result;
1511                 gchar *folder_name = NULL, *suggested_name = NULL;
1512
1513                 /* Run the new folder dialog */
1514                 while (!finished) {
1515                         result = modest_platform_run_new_folder_dialog (GTK_WINDOW (main_window),
1516                                                                         parent_folder,
1517                                                                         suggested_name,
1518                                                                         &folder_name);
1519
1520                         if (result == GTK_RESPONSE_REJECT) {
1521                                 finished = TRUE;
1522                         } else {
1523                                 ModestMailOperation *mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO, G_OBJECT(main_window));
1524                                 TnyFolder *new_folder = NULL;
1525
1526                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
1527                                                                  mail_op);
1528                 
1529                                 new_folder = modest_mail_operation_create_folder (mail_op,
1530                                                                                   parent_folder,
1531                                                                                   (const gchar *) folder_name);
1532                                 if (new_folder) {
1533                                         g_object_unref (new_folder);
1534                                         finished = TRUE;
1535                                 } 
1536 /*                              else { */
1537 /*                                      /\* TODO: check error and follow proper actions *\/ */
1538 /* /\*                                  suggested_name = X; *\/ */
1539 /*                                      /\* Show error to the user *\/ */
1540 /*                                      modest_platform_run_information_dialog (GTK_WINDOW (main_window), */
1541 /*                                                                              MODEST_INFORMATION_CREATE_FOLDER); */
1542 /*                              } */
1543                                 g_object_unref (mail_op);
1544                         }
1545                         g_free (folder_name);
1546                         folder_name = NULL;
1547                 }
1548
1549                 g_object_unref (parent_folder);
1550         }
1551 }
1552
1553 void 
1554 modest_ui_actions_on_rename_folder (GtkAction *action,
1555                                      ModestMainWindow *main_window)
1556 {
1557         TnyFolderStore *folder;
1558         GtkWidget *folder_view;
1559         
1560         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1561
1562         folder_view = modest_main_window_get_child_widget (main_window,
1563                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1564         if (!folder_view)
1565                 return;
1566         
1567         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW(folder_view));
1568         
1569         if (folder && TNY_IS_FOLDER (folder)) {
1570                 gchar *folder_name;
1571                 folder_name = ask_for_folder_name (GTK_WINDOW (main_window),
1572                                                    _("Please enter a new name for the folder"));
1573
1574                 if (folder_name != NULL && strlen (folder_name) > 0) {
1575                         ModestMailOperation *mail_op;
1576
1577                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_INFO, G_OBJECT(main_window));
1578                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1579                                                          mail_op);
1580
1581                         modest_mail_operation_rename_folder (mail_op,
1582                                                              TNY_FOLDER (folder),
1583                                                              (const gchar *) folder_name);
1584
1585                         g_object_unref (mail_op);
1586                         g_free (folder_name);
1587                 }
1588                 g_object_unref (folder);
1589         }
1590 }
1591
1592 static void
1593 delete_folder (ModestMainWindow *main_window, gboolean move_to_trash) 
1594 {
1595         TnyFolderStore *folder;
1596         GtkWidget *folder_view;
1597         gint response;
1598         gchar *message;
1599         
1600         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1601
1602         folder_view = modest_main_window_get_child_widget (main_window,
1603                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
1604         if (!folder_view)
1605                 return;
1606
1607         folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1608
1609         /* Ask the user */      
1610         message =  g_strdup_printf (_("mcen_nc_delete_folder_text"), 
1611                                     tny_folder_get_name (TNY_FOLDER (folder)));
1612         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (main_window), 
1613                                                             (const gchar *) message);
1614         g_free (message);
1615
1616         if (response == GTK_RESPONSE_OK) {
1617                 ModestMailOperation *mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_DELETE, G_OBJECT(main_window));
1618
1619                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (),
1620                                                  mail_op);
1621                 modest_mail_operation_remove_folder (mail_op, TNY_FOLDER (folder), move_to_trash);
1622
1623                 /* Show error if happened */
1624                 if (modest_mail_operation_get_error (mail_op))
1625                         modest_platform_run_information_dialog (GTK_WINDOW (main_window),
1626                                                                 MODEST_INFORMATION_DELETE_FOLDER);
1627
1628                 g_object_unref (G_OBJECT (mail_op));
1629         }
1630
1631         g_object_unref (G_OBJECT (folder));
1632 }
1633
1634 void 
1635 modest_ui_actions_on_delete_folder (GtkAction *action,
1636                                      ModestMainWindow *main_window)
1637 {
1638         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1639
1640         delete_folder (main_window, FALSE);
1641 }
1642
1643 void 
1644 modest_ui_actions_on_move_folder_to_trash_folder (GtkAction *action, ModestMainWindow *main_window)
1645 {
1646         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
1647         
1648         delete_folder (main_window, TRUE);
1649 }
1650
1651 void
1652 modest_ui_actions_on_password_requested (TnyAccountStore *account_store, 
1653                                          const gchar* account_name,
1654                                          gchar **password, 
1655                                          gboolean *cancel, 
1656                                          gboolean *remember,
1657                                          ModestMainWindow *main_window)
1658 {
1659         gchar *txt;
1660         GtkWidget *dialog, *entry, *remember_pass_check;
1661
1662         dialog = gtk_dialog_new_with_buttons (_("Password requested"),
1663                                               NULL,
1664                                               GTK_DIALOG_MODAL,
1665                                               GTK_STOCK_CANCEL,
1666                                               GTK_RESPONSE_REJECT,
1667                                               GTK_STOCK_OK,
1668                                               GTK_RESPONSE_ACCEPT,
1669                                               NULL);
1670         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1671         
1672         txt = g_strdup_printf (_("Please enter your password for %s"), account_name);
1673         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1674                             FALSE, FALSE, 0);
1675         g_free (txt);
1676
1677         entry = gtk_entry_new_with_max_length (40);
1678         gtk_entry_set_visibility (GTK_ENTRY(entry), FALSE);
1679         gtk_entry_set_invisible_char (GTK_ENTRY(entry), 0x2022); /* bullet unichar */
1680         
1681         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry,
1682                             TRUE, FALSE, 0);    
1683
1684         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1685         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1686                             TRUE, FALSE, 0);
1687
1688         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1689         
1690         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1691                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry)));
1692                 *cancel   = FALSE;
1693         } else {
1694                 *password = NULL;
1695                 *cancel   = TRUE;
1696         }
1697
1698         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
1699                 *remember = TRUE;
1700         else
1701                 *remember = FALSE;
1702
1703         gtk_widget_destroy (dialog);
1704 }
1705
1706 void
1707 modest_ui_actions_on_cut (GtkAction *action,
1708                           ModestWindow *window)
1709 {
1710         GtkWidget *focused_widget;
1711
1712         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1713         if (GTK_IS_EDITABLE (focused_widget)) {
1714                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
1715         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1716                 GtkTextBuffer *buffer;
1717                 GtkClipboard *clipboard;
1718
1719                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1720                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1721                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
1722         }
1723 }
1724
1725 void
1726 modest_ui_actions_on_copy (GtkAction *action,
1727                            ModestWindow *window)
1728 {
1729         GtkClipboard *clipboard;
1730         GtkWidget *focused_widget;
1731
1732         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1733         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1734         if (GTK_IS_LABEL (focused_widget)) {
1735                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
1736         } else if (GTK_IS_EDITABLE (focused_widget)) {
1737                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
1738         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1739                 GtkTextBuffer *buffer;
1740
1741                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1742                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
1743         }
1744 }
1745
1746 void
1747 modest_ui_actions_on_undo (GtkAction *action,
1748                            ModestWindow *window)
1749 {
1750         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
1751                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
1752         } else {
1753                 g_return_if_reached ();
1754         }
1755 }
1756
1757 void
1758 modest_ui_actions_on_paste (GtkAction *action,
1759                             ModestWindow *window)
1760 {
1761         GtkWidget *focused_widget;
1762
1763         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1764         if (GTK_IS_EDITABLE (focused_widget)) {
1765                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
1766         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1767                 GtkTextBuffer *buffer;
1768                 GtkClipboard *clipboard;
1769
1770                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1771                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1772                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
1773         }
1774 }
1775
1776 void
1777 modest_ui_actions_on_select_all (GtkAction *action,
1778                                  ModestWindow *window)
1779 {
1780         GtkWidget *focused_widget;
1781
1782         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1783         if (GTK_IS_LABEL (focused_widget)) {
1784                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
1785         } else if (GTK_IS_EDITABLE (focused_widget)) {
1786                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
1787         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1788                 GtkTextBuffer *buffer;
1789                 GtkTextIter start, end;
1790
1791                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1792                 gtk_text_buffer_get_start_iter (buffer, &start);
1793                 gtk_text_buffer_get_end_iter (buffer, &end);
1794                 gtk_text_buffer_select_range (buffer, &start, &end);
1795         }
1796 }
1797
1798 void
1799 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
1800                                   GtkRadioAction *selected,
1801                                   ModestWindow *window)
1802 {
1803         gint value;
1804
1805         value = gtk_radio_action_get_current_value (selected);
1806         if (MODEST_IS_WINDOW (window)) {
1807                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
1808         }
1809 }
1810
1811 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
1812                                                         GtkRadioAction *selected,
1813                                                         ModestWindow *window)
1814 {
1815         TnyHeaderFlags flags;
1816         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1817
1818         flags = gtk_radio_action_get_current_value (selected);
1819         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
1820 }
1821
1822 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
1823                                                            GtkRadioAction *selected,
1824                                                            ModestWindow *window)
1825 {
1826         gint file_format;
1827
1828         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1829
1830         file_format = gtk_radio_action_get_current_value (selected);
1831         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
1832 }
1833
1834
1835 void     
1836 modest_ui_actions_on_zoom_plus (GtkAction *action,
1837                                 ModestWindow *window)
1838 {
1839         g_return_if_fail (MODEST_IS_WINDOW (window));
1840
1841         modest_window_zoom_plus (MODEST_WINDOW (window));
1842 }
1843
1844 void     
1845 modest_ui_actions_on_zoom_minus (GtkAction *action,
1846                                  ModestWindow *window)
1847 {
1848         g_return_if_fail (MODEST_IS_WINDOW (window));
1849
1850         modest_window_zoom_minus (MODEST_WINDOW (window));
1851 }
1852
1853 void     
1854 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
1855                                            ModestWindow *window)
1856 {
1857         ModestWindowMgr *mgr;
1858         gboolean fullscreen, active;
1859         g_return_if_fail (MODEST_IS_WINDOW (window));
1860
1861         mgr = modest_runtime_get_window_mgr ();
1862
1863         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
1864         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1865
1866         if (active != fullscreen) {
1867                 modest_window_mgr_set_fullscreen_mode (mgr, active);
1868                 gtk_window_present (GTK_WINDOW (window));
1869         }
1870 }
1871
1872 void
1873 modest_ui_actions_on_change_fullscreen (GtkAction *action,
1874                                         ModestWindow *window)
1875 {
1876         ModestWindowMgr *mgr;
1877         gboolean fullscreen;
1878
1879         g_return_if_fail (MODEST_IS_WINDOW (window));
1880
1881         mgr = modest_runtime_get_window_mgr ();
1882         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1883         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
1884
1885         gtk_window_present (GTK_WINDOW (window));
1886 }
1887
1888 /* 
1889  * Used by modest_ui_actions_on_details to call do_headers_action 
1890  */
1891 static void
1892 headers_action_show_details (TnyHeader *header, 
1893                              ModestWindow *window,
1894                              gpointer user_data)
1895
1896 {
1897         GtkWidget *dialog;
1898         
1899         /* Create dialog */
1900         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
1901
1902         /* Run dialog */
1903         gtk_widget_show_all (dialog);
1904         gtk_dialog_run (GTK_DIALOG (dialog));
1905
1906         gtk_widget_destroy (dialog);
1907 }
1908
1909 /*
1910  * Show the folder details in a ModestDetailsDialog widget
1911  */
1912 static void
1913 show_folder_details (TnyFolder *folder, 
1914                      GtkWindow *window)
1915 {
1916         GtkWidget *dialog;
1917         
1918         /* Create dialog */
1919         dialog = modest_details_dialog_new_with_folder (window, folder);
1920
1921         /* Run dialog */
1922         gtk_widget_show_all (dialog);
1923         gtk_dialog_run (GTK_DIALOG (dialog));
1924
1925         gtk_widget_destroy (dialog);
1926 }
1927
1928 /*
1929  * Show the header details in a ModestDetailsDialog widget
1930  */
1931 void     
1932 modest_ui_actions_on_details (GtkAction *action, 
1933                               ModestWindow *win)
1934 {
1935         TnyList * headers_list;
1936         TnyIterator *iter;
1937         TnyHeader *header;              
1938
1939         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1940                 TnyMsg *msg;
1941
1942                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
1943                 if (!msg) {
1944                         return;
1945                 } else {
1946                         headers_list = get_selected_headers (win);
1947                         if (!headers_list)
1948                                 return;
1949
1950                         iter = tny_list_create_iterator (headers_list);
1951
1952                         header = TNY_HEADER (tny_iterator_get_current (iter));
1953                         headers_action_show_details (header, win, NULL);
1954                         g_object_unref (header);
1955
1956                         g_object_unref (iter);
1957                 }
1958         } else if (MODEST_IS_MAIN_WINDOW (win)) {
1959                 GtkWidget *folder_view, *header_view;
1960
1961                 /* Check which widget has the focus */
1962                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1963                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
1964                 if (gtk_widget_is_focus (folder_view)) {
1965                         TnyFolder *folder;
1966
1967                         folder = (TnyFolder *) modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1968
1969                         /* Show only when it's a folder */
1970                         if (!folder || !TNY_IS_FOLDER (folder))
1971                                 return;
1972
1973                         show_folder_details (folder, GTK_WINDOW (win));
1974
1975                 } else {
1976                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1977                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1978                         /* Show details of each header */
1979                         do_headers_action (win, headers_action_show_details, header_view);
1980                 }
1981         }
1982 }
1983
1984 void     
1985 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
1986                                      ModestMsgEditWindow *window)
1987 {
1988         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1989
1990         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
1991 }
1992
1993 void     
1994 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
1995                                       ModestMsgEditWindow *window)
1996 {
1997         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1998
1999         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
2000 }
2001
2002 void
2003 modest_ui_actions_toggle_folders_view (GtkAction *action, 
2004                                        ModestMainWindow *main_window)
2005 {
2006         ModestConf *conf;
2007         
2008         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2009
2010         conf = modest_runtime_get_conf ();
2011         
2012         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
2013                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
2014         else
2015                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
2016 }
2017
2018 void 
2019 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
2020                                      ModestWindow *window)
2021 {
2022         gboolean active, fullscreen = FALSE;
2023         ModestWindowMgr *mgr;
2024
2025         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
2026
2027         /* Check if we want to toggle the toolbar vuew in fullscreen
2028            or normal mode */
2029         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
2030                      "ViewShowToolbarFullScreen")) {
2031                 fullscreen = TRUE;
2032         }
2033
2034         /* Toggle toolbar */
2035         mgr = modest_runtime_get_window_mgr ();
2036         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
2037 }
2038
2039 void     
2040 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
2041                                            ModestMsgEditWindow *window)
2042 {
2043         modest_msg_edit_window_select_font (window);
2044 }
2045
2046 void
2047 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
2048                                                   const gchar *display_name,
2049                                                   GtkWindow *window)
2050 {
2051         /* Do not change the application name if the widget has not
2052            the focus. This callback could be called even if the folder
2053            view has not the focus, because the handled signal could be
2054            emitted when the folder view is redrawn */
2055         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
2056                 if (display_name)
2057                         gtk_window_set_title (window, display_name);
2058                 else
2059                         gtk_window_set_title (window, " ");
2060         }
2061 }
2062
2063 void
2064 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
2065 {
2066         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2067         modest_msg_edit_window_select_contacts (window);
2068 }
2069
2070 void
2071 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
2072 {
2073         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2074         modest_msg_edit_window_check_names (window);
2075 }
2076
2077
2078 static GtkWidget*
2079 create_move_to_dialog (ModestWindow *win,
2080                        GtkWidget *folder_view,
2081                        GtkWidget **tree_view)
2082 {
2083         GtkWidget *dialog, *scroll;
2084
2085         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2086                                               GTK_WINDOW (win),
2087                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
2088                                               GTK_STOCK_OK,
2089                                               GTK_RESPONSE_ACCEPT,
2090                                               GTK_STOCK_CANCEL,
2091                                               GTK_RESPONSE_REJECT,
2092                                               NULL);
2093
2094         /* Create scrolled window */
2095         scroll = gtk_scrolled_window_new (NULL, NULL);
2096         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
2097                                          GTK_POLICY_AUTOMATIC,
2098                                          GTK_POLICY_AUTOMATIC);
2099
2100         /* Create folder view */
2101         *tree_view = modest_folder_view_new (NULL);
2102         gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
2103                                  gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
2104         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
2105
2106         /* Add scroll to dialog */
2107         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
2108                             scroll, FALSE, FALSE, 0);
2109
2110         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2111
2112         return dialog;
2113 }
2114
2115 /*
2116  * Returns TRUE if at least one of the headers of the list belongs to
2117  * a message that has been fully retrieved.
2118  */
2119 static gboolean
2120 has_retrieved_msgs (TnyList *list)
2121 {
2122         TnyIterator *iter;
2123         gboolean found = FALSE;
2124
2125         iter = tny_list_create_iterator (list);
2126         while (tny_iterator_is_done (iter) && !found) {
2127                 TnyHeader *header;
2128                 TnyHeaderFlags flags;
2129
2130                 header = TNY_HEADER (tny_iterator_get_current (iter));
2131                 flags = tny_header_get_flags (header);
2132                 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
2133                         found = TRUE;
2134
2135                 if (!found)
2136                         tny_iterator_next (iter);
2137         }
2138         g_object_unref (iter);
2139
2140         return found;
2141 }
2142
2143 /*
2144  * Shows a confirmation dialog to the user when we're moving messages
2145  * from a remote server to the local storage. Returns the dialog
2146  * response. If it's other kind of movement the it always returns
2147  * GTK_RESPONSE_OK
2148  */
2149 static gint
2150 msgs_move_to_confirmation (GtkWindow *win,
2151                            TnyFolder *dest_folder,
2152                            TnyList *headers)
2153 {
2154         gint response = GTK_RESPONSE_OK;
2155
2156         /* If the destination is a local folder */
2157         if (modest_tny_folder_is_local_folder (dest_folder)) {
2158                 TnyFolder *src_folder;
2159                 TnyIterator *iter;
2160                 TnyHeader *header;
2161
2162                 /* Get source folder */
2163                 iter = tny_list_create_iterator (headers);
2164                 header = TNY_HEADER (tny_iterator_get_current (iter));
2165                 src_folder = tny_header_get_folder (header);
2166                 g_object_unref (header);
2167                 g_object_unref (iter);
2168
2169                 /* If the source is a remote folder */
2170                 if (!modest_tny_folder_is_local_folder (src_folder)) {
2171                         const gchar *message;
2172                         
2173                         if (tny_list_get_length (headers) == 1)
2174                                 if (has_retrieved_msgs (headers))
2175                                         message = _("mcen_nc_move_retrieve");
2176                                 else
2177                                         message = _("mcen_nc_move_header");
2178                         else
2179                                 if (has_retrieved_msgs (headers))
2180                                         message = _("mcen_nc_move_retrieves");
2181                                 else
2182                                         message = _("mcen_nc_move_headers");
2183                         
2184                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
2185                                                                             (const gchar *) message);
2186                 }
2187         }
2188         return response;
2189 }
2190
2191 /*
2192  * UI handler for the "Move to" action when invoked from the
2193  * ModestMainWindow
2194  */
2195 static void 
2196 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
2197                                           ModestMainWindow *win)
2198 {
2199         GtkWidget *dialog, *folder_view, *tree_view = NULL;
2200         gint result;
2201         TnyFolderStore *folder_store;
2202         ModestMailOperation *mail_op = NULL;
2203
2204         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
2205
2206         /* Get the folder view */
2207         folder_view = modest_main_window_get_child_widget (win,
2208                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2209
2210         /* Create and run the dialog */
2211         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);
2212         result = gtk_dialog_run (GTK_DIALOG(dialog));
2213
2214         /* We do this to save an indentation level ;-) */
2215         if (result != GTK_RESPONSE_ACCEPT)
2216                 goto end;
2217
2218         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2219
2220         if (TNY_IS_ACCOUNT (folder_store))
2221                 goto end;
2222
2223         /* Get folder or messages to transfer */
2224         if (gtk_widget_is_focus (folder_view)) {
2225                 TnyFolderStore *src_folder;
2226                 src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2227
2228                 if (TNY_IS_FOLDER (src_folder)) {
2229                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
2230                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2231                                                          mail_op);
2232
2233                         modest_mail_operation_xfer_folder (mail_op, 
2234                                                            TNY_FOLDER (src_folder),
2235                                                            folder_store,
2236                                                            TRUE);
2237                         g_object_unref (G_OBJECT (mail_op));
2238                 }
2239
2240                 /* Frees */
2241                 g_object_unref (G_OBJECT (src_folder));
2242         } else {
2243                 GtkWidget *header_view;
2244                 header_view = modest_main_window_get_child_widget (win,
2245                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
2246                 if (gtk_widget_is_focus (header_view)) {
2247                         TnyList *headers;
2248                         gint response;
2249
2250                         headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
2251
2252                         /* Ask for user confirmation */
2253                         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2254                                                               TNY_FOLDER (folder_store), 
2255                                                               headers);
2256
2257                         /* Transfer messages */
2258                         if (response == GTK_RESPONSE_OK) {
2259                                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
2260                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2261                                                                  mail_op);
2262
2263                                 modest_mail_operation_xfer_msgs (mail_op, 
2264                                                                  headers,
2265                                                                  TNY_FOLDER (folder_store),
2266                                                                  TRUE);
2267                                 g_object_unref (G_OBJECT (mail_op));
2268                         }
2269                 }
2270         }
2271         g_object_unref (folder_store);
2272
2273  end:
2274         gtk_widget_destroy (dialog);
2275 }
2276
2277
2278 /*
2279  * UI handler for the "Move to" action when invoked from the
2280  * ModestMsgViewWindow
2281  */
2282 static void 
2283 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
2284                                               ModestMsgViewWindow *win)
2285 {
2286         GtkWidget *dialog, *folder_view, *tree_view = NULL;
2287         gint result;
2288         ModestMainWindow *main_window;
2289         TnyMsg *msg;
2290         TnyHeader *header;
2291         TnyList *headers;
2292
2293         /* Get the folder view */
2294         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2295         folder_view = modest_main_window_get_child_widget (main_window,
2296                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2297
2298         /* Create and run the dialog */
2299         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);  
2300         result = gtk_dialog_run (GTK_DIALOG(dialog));
2301
2302         if (result == GTK_RESPONSE_ACCEPT) {
2303                 TnyFolderStore *folder_store;
2304                 gint response;
2305
2306                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2307
2308                 /* Create header list */
2309                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
2310                 header = tny_msg_get_header (msg);
2311                 headers = tny_simple_list_new ();
2312                 tny_list_prepend (headers, G_OBJECT (header));
2313                 g_object_unref (header);
2314                 g_object_unref (msg);
2315
2316                 /* Ask user for confirmation. MSG-NOT404 */
2317                 response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2318                                                       TNY_FOLDER (folder_store), 
2319                                                       headers);
2320
2321                 /* Transfer current msg */
2322                 if (response == GTK_RESPONSE_OK) {
2323                         ModestMailOperation *mail_op;
2324
2325                         /* Create mail op */
2326                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
2327                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2328                                                          mail_op);
2329                         
2330                         /* Transfer messages */
2331                         modest_mail_operation_xfer_msgs (mail_op, 
2332                                                          headers,
2333                                                          TNY_FOLDER (folder_store),
2334                                                          TRUE);
2335                         g_object_unref (G_OBJECT (mail_op));
2336                 } else {
2337                         g_object_unref (headers);
2338                 }
2339                 g_object_unref (folder_store);
2340         }
2341         gtk_widget_destroy (dialog);
2342 }
2343
2344 void 
2345 modest_ui_actions_on_move_to (GtkAction *action, 
2346                               ModestWindow *win)
2347 {
2348         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
2349                           MODEST_IS_MSG_VIEW_WINDOW (win));
2350
2351         if (MODEST_IS_MAIN_WINDOW (win)) 
2352                 modest_ui_actions_on_main_window_move_to (action, 
2353                                                           MODEST_MAIN_WINDOW (win));
2354         else
2355                 modest_ui_actions_on_msg_view_window_move_to (action, 
2356                                                               MODEST_MSG_VIEW_WINDOW (win));
2357 }
2358
2359 /*
2360  * Calls #HeadersFunc for each header already selected in the main
2361  * window or the message currently being shown in the msg view window
2362  */
2363 static void
2364 do_headers_action (ModestWindow *win, 
2365                    HeadersFunc func,
2366                    gpointer user_data)
2367 {
2368         TnyList *headers_list;
2369         TnyIterator *iter;
2370
2371         /* Get headers */
2372         headers_list = get_selected_headers (win);
2373         if (!headers_list)
2374                 return;
2375
2376         /* Call the function for each header */
2377         iter = tny_list_create_iterator (headers_list);
2378         while (!tny_iterator_is_done (iter)) {
2379                 TnyHeader *header;
2380
2381                 header = TNY_HEADER (tny_iterator_get_current (iter));
2382                 func (header, win, user_data);
2383                 g_object_unref (header);
2384                 tny_iterator_next (iter);
2385         }
2386         g_object_unref (iter);
2387 }