56eb343b51c85512d950ceb053b2bb0afff8c15e
[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         /* printf("DEBUG: %s\n", __FUNCTION__); */
1660         gchar *txt;
1661         GtkWidget *dialog, *entry, *remember_pass_check;
1662
1663         dialog = gtk_dialog_new_with_buttons (_("Password requested"),
1664                                               NULL,
1665                                               GTK_DIALOG_MODAL,
1666                                               GTK_STOCK_CANCEL,
1667                                               GTK_RESPONSE_REJECT,
1668                                               GTK_STOCK_OK,
1669                                               GTK_RESPONSE_ACCEPT,
1670                                               NULL);
1671         gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(main_window));
1672         
1673         txt = g_strdup_printf (_("Please enter your password for %s"), account_name);
1674         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), gtk_label_new(txt),
1675                             FALSE, FALSE, 0);
1676         g_free (txt);
1677
1678         entry = gtk_entry_new_with_max_length (40);
1679         gtk_entry_set_visibility (GTK_ENTRY(entry), FALSE);
1680         gtk_entry_set_invisible_char (GTK_ENTRY(entry), 0x2022); /* bullet unichar */
1681         
1682         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), entry,
1683                             TRUE, FALSE, 0);    
1684
1685         remember_pass_check = gtk_check_button_new_with_label (_("Remember password"));
1686         gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), remember_pass_check,
1687                             TRUE, FALSE, 0);
1688
1689         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
1690         
1691         if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
1692                 *password = g_strdup (gtk_entry_get_text (GTK_ENTRY(entry)));
1693                 *cancel   = FALSE;
1694         } else {
1695                 *password = NULL;
1696                 *cancel   = TRUE;
1697         }
1698
1699         if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (remember_pass_check)))
1700                 *remember = TRUE;
1701         else
1702                 *remember = FALSE;
1703
1704         gtk_widget_destroy (dialog);
1705 }
1706
1707 void
1708 modest_ui_actions_on_cut (GtkAction *action,
1709                           ModestWindow *window)
1710 {
1711         GtkWidget *focused_widget;
1712
1713         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1714         if (GTK_IS_EDITABLE (focused_widget)) {
1715                 gtk_editable_cut_clipboard (GTK_EDITABLE(focused_widget));
1716         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1717                 GtkTextBuffer *buffer;
1718                 GtkClipboard *clipboard;
1719
1720                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1721                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1722                 gtk_text_buffer_cut_clipboard (buffer, clipboard, TRUE);
1723         }
1724 }
1725
1726 void
1727 modest_ui_actions_on_copy (GtkAction *action,
1728                            ModestWindow *window)
1729 {
1730         GtkClipboard *clipboard;
1731         GtkWidget *focused_widget;
1732
1733         clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1734         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1735         if (GTK_IS_LABEL (focused_widget)) {
1736                 gtk_clipboard_set_text (clipboard, gtk_label_get_text (GTK_LABEL (focused_widget)), -1);
1737         } else if (GTK_IS_EDITABLE (focused_widget)) {
1738                 gtk_editable_copy_clipboard (GTK_EDITABLE(focused_widget));
1739         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1740                 GtkTextBuffer *buffer;
1741
1742                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1743                 gtk_text_buffer_copy_clipboard (buffer, clipboard);
1744         }
1745 }
1746
1747 void
1748 modest_ui_actions_on_undo (GtkAction *action,
1749                            ModestWindow *window)
1750 {
1751         if (MODEST_IS_MSG_EDIT_WINDOW (window)) {
1752                 modest_msg_edit_window_undo (MODEST_MSG_EDIT_WINDOW (window));
1753         } else {
1754                 g_return_if_reached ();
1755         }
1756 }
1757
1758 void
1759 modest_ui_actions_on_paste (GtkAction *action,
1760                             ModestWindow *window)
1761 {
1762         GtkWidget *focused_widget;
1763
1764         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1765         if (GTK_IS_EDITABLE (focused_widget)) {
1766                 gtk_editable_paste_clipboard (GTK_EDITABLE(focused_widget));
1767         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1768                 GtkTextBuffer *buffer;
1769                 GtkClipboard *clipboard;
1770
1771                 clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
1772                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1773                 gtk_text_buffer_paste_clipboard (buffer, clipboard, NULL, TRUE);
1774         }
1775 }
1776
1777 void
1778 modest_ui_actions_on_select_all (GtkAction *action,
1779                                  ModestWindow *window)
1780 {
1781         GtkWidget *focused_widget;
1782
1783         focused_widget = gtk_window_get_focus (GTK_WINDOW (window));
1784         if (GTK_IS_LABEL (focused_widget)) {
1785                 gtk_label_select_region (GTK_LABEL (focused_widget), 0, -1);
1786         } else if (GTK_IS_EDITABLE (focused_widget)) {
1787                 gtk_editable_select_region (GTK_EDITABLE(focused_widget), 0, -1);
1788         } else if (GTK_IS_TEXT_VIEW (focused_widget)) {
1789                 GtkTextBuffer *buffer;
1790                 GtkTextIter start, end;
1791
1792                 buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (focused_widget));
1793                 gtk_text_buffer_get_start_iter (buffer, &start);
1794                 gtk_text_buffer_get_end_iter (buffer, &end);
1795                 gtk_text_buffer_select_range (buffer, &start, &end);
1796         }
1797 }
1798
1799 void
1800 modest_ui_actions_on_change_zoom (GtkRadioAction *action,
1801                                   GtkRadioAction *selected,
1802                                   ModestWindow *window)
1803 {
1804         gint value;
1805
1806         value = gtk_radio_action_get_current_value (selected);
1807         if (MODEST_IS_WINDOW (window)) {
1808                 modest_window_set_zoom (MODEST_WINDOW (window), ((gdouble)value)/100);
1809         }
1810 }
1811
1812 void     modest_ui_actions_msg_edit_on_change_priority (GtkRadioAction *action,
1813                                                         GtkRadioAction *selected,
1814                                                         ModestWindow *window)
1815 {
1816         TnyHeaderFlags flags;
1817         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1818
1819         flags = gtk_radio_action_get_current_value (selected);
1820         modest_msg_edit_window_set_priority_flags (MODEST_MSG_EDIT_WINDOW (window), flags);
1821 }
1822
1823 void     modest_ui_actions_msg_edit_on_change_file_format (GtkRadioAction *action,
1824                                                            GtkRadioAction *selected,
1825                                                            ModestWindow *window)
1826 {
1827         gint file_format;
1828
1829         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1830
1831         file_format = gtk_radio_action_get_current_value (selected);
1832         modest_msg_edit_window_set_file_format (MODEST_MSG_EDIT_WINDOW (window), file_format);
1833 }
1834
1835
1836 void     
1837 modest_ui_actions_on_zoom_plus (GtkAction *action,
1838                                 ModestWindow *window)
1839 {
1840         g_return_if_fail (MODEST_IS_WINDOW (window));
1841
1842         modest_window_zoom_plus (MODEST_WINDOW (window));
1843 }
1844
1845 void     
1846 modest_ui_actions_on_zoom_minus (GtkAction *action,
1847                                  ModestWindow *window)
1848 {
1849         g_return_if_fail (MODEST_IS_WINDOW (window));
1850
1851         modest_window_zoom_minus (MODEST_WINDOW (window));
1852 }
1853
1854 void     
1855 modest_ui_actions_on_toggle_fullscreen    (GtkToggleAction *toggle,
1856                                            ModestWindow *window)
1857 {
1858         ModestWindowMgr *mgr;
1859         gboolean fullscreen, active;
1860         g_return_if_fail (MODEST_IS_WINDOW (window));
1861
1862         mgr = modest_runtime_get_window_mgr ();
1863
1864         active = (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle)))?1:0;
1865         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1866
1867         if (active != fullscreen) {
1868                 modest_window_mgr_set_fullscreen_mode (mgr, active);
1869                 gtk_window_present (GTK_WINDOW (window));
1870         }
1871 }
1872
1873 void
1874 modest_ui_actions_on_change_fullscreen (GtkAction *action,
1875                                         ModestWindow *window)
1876 {
1877         ModestWindowMgr *mgr;
1878         gboolean fullscreen;
1879
1880         g_return_if_fail (MODEST_IS_WINDOW (window));
1881
1882         mgr = modest_runtime_get_window_mgr ();
1883         fullscreen = modest_window_mgr_get_fullscreen_mode (mgr);
1884         modest_window_mgr_set_fullscreen_mode (mgr, !fullscreen);
1885
1886         gtk_window_present (GTK_WINDOW (window));
1887 }
1888
1889 /* 
1890  * Used by modest_ui_actions_on_details to call do_headers_action 
1891  */
1892 static void
1893 headers_action_show_details (TnyHeader *header, 
1894                              ModestWindow *window,
1895                              gpointer user_data)
1896
1897 {
1898         GtkWidget *dialog;
1899         
1900         /* Create dialog */
1901         dialog = modest_details_dialog_new_with_header (GTK_WINDOW (window), header);
1902
1903         /* Run dialog */
1904         gtk_widget_show_all (dialog);
1905         gtk_dialog_run (GTK_DIALOG (dialog));
1906
1907         gtk_widget_destroy (dialog);
1908 }
1909
1910 /*
1911  * Show the folder details in a ModestDetailsDialog widget
1912  */
1913 static void
1914 show_folder_details (TnyFolder *folder, 
1915                      GtkWindow *window)
1916 {
1917         GtkWidget *dialog;
1918         
1919         /* Create dialog */
1920         dialog = modest_details_dialog_new_with_folder (window, folder);
1921
1922         /* Run dialog */
1923         gtk_widget_show_all (dialog);
1924         gtk_dialog_run (GTK_DIALOG (dialog));
1925
1926         gtk_widget_destroy (dialog);
1927 }
1928
1929 /*
1930  * Show the header details in a ModestDetailsDialog widget
1931  */
1932 void     
1933 modest_ui_actions_on_details (GtkAction *action, 
1934                               ModestWindow *win)
1935 {
1936         TnyList * headers_list;
1937         TnyIterator *iter;
1938         TnyHeader *header;              
1939
1940         if (MODEST_IS_MSG_VIEW_WINDOW (win)) {
1941                 TnyMsg *msg;
1942
1943                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
1944                 if (!msg) {
1945                         return;
1946                 } else {
1947                         headers_list = get_selected_headers (win);
1948                         if (!headers_list)
1949                                 return;
1950
1951                         iter = tny_list_create_iterator (headers_list);
1952
1953                         header = TNY_HEADER (tny_iterator_get_current (iter));
1954                         headers_action_show_details (header, win, NULL);
1955                         g_object_unref (header);
1956
1957                         g_object_unref (iter);
1958                 }
1959         } else if (MODEST_IS_MAIN_WINDOW (win)) {
1960                 GtkWidget *folder_view, *header_view;
1961
1962                 /* Check which widget has the focus */
1963                 folder_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1964                                                                     MODEST_WIDGET_TYPE_FOLDER_VIEW);
1965                 if (gtk_widget_is_focus (folder_view)) {
1966                         TnyFolder *folder;
1967
1968                         folder = (TnyFolder *) modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
1969
1970                         /* Show only when it's a folder */
1971                         if (!folder || !TNY_IS_FOLDER (folder))
1972                                 return;
1973
1974                         show_folder_details (folder, GTK_WINDOW (win));
1975
1976                 } else {
1977                         header_view = modest_main_window_get_child_widget (MODEST_MAIN_WINDOW (win),
1978                                                                            MODEST_WIDGET_TYPE_HEADER_VIEW);
1979                         /* Show details of each header */
1980                         do_headers_action (win, headers_action_show_details, header_view);
1981                 }
1982         }
1983 }
1984
1985 void     
1986 modest_ui_actions_on_toggle_show_cc (GtkToggleAction *toggle,
1987                                      ModestMsgEditWindow *window)
1988 {
1989         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1990
1991         modest_msg_edit_window_show_cc (window, gtk_toggle_action_get_active (toggle));
1992 }
1993
1994 void     
1995 modest_ui_actions_on_toggle_show_bcc (GtkToggleAction *toggle,
1996                                       ModestMsgEditWindow *window)
1997 {
1998         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
1999
2000         modest_msg_edit_window_show_bcc (window, gtk_toggle_action_get_active (toggle));
2001 }
2002
2003 void
2004 modest_ui_actions_toggle_folders_view (GtkAction *action, 
2005                                        ModestMainWindow *main_window)
2006 {
2007         ModestConf *conf;
2008         
2009         g_return_if_fail (MODEST_IS_MAIN_WINDOW(main_window));
2010
2011         conf = modest_runtime_get_conf ();
2012         
2013         if (modest_main_window_get_style (main_window) == MODEST_MAIN_WINDOW_STYLE_SPLIT)
2014                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SIMPLE);
2015         else
2016                 modest_main_window_set_style (main_window, MODEST_MAIN_WINDOW_STYLE_SPLIT);
2017 }
2018
2019 void 
2020 modest_ui_actions_on_toggle_toolbar (GtkToggleAction *toggle, 
2021                                      ModestWindow *window)
2022 {
2023         gboolean active, fullscreen = FALSE;
2024         ModestWindowMgr *mgr;
2025
2026         active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (toggle));
2027
2028         /* Check if we want to toggle the toolbar vuew in fullscreen
2029            or normal mode */
2030         if (!strcmp (gtk_action_get_name (GTK_ACTION (toggle)), 
2031                      "ViewShowToolbarFullScreen")) {
2032                 fullscreen = TRUE;
2033         }
2034
2035         /* Toggle toolbar */
2036         mgr = modest_runtime_get_window_mgr ();
2037         modest_window_mgr_show_toolbars (mgr, active, fullscreen);
2038 }
2039
2040 void     
2041 modest_ui_actions_msg_edit_on_select_font (GtkAction *action,
2042                                            ModestMsgEditWindow *window)
2043 {
2044         modest_msg_edit_window_select_font (window);
2045 }
2046
2047 void
2048 modest_ui_actions_on_folder_display_name_changed (ModestFolderView *folder_view,
2049                                                   const gchar *display_name,
2050                                                   GtkWindow *window)
2051 {
2052         /* Do not change the application name if the widget has not
2053            the focus. This callback could be called even if the folder
2054            view has not the focus, because the handled signal could be
2055            emitted when the folder view is redrawn */
2056         if (gtk_widget_is_focus (GTK_WIDGET (folder_view))) {
2057                 if (display_name)
2058                         gtk_window_set_title (window, display_name);
2059                 else
2060                         gtk_window_set_title (window, " ");
2061         }
2062 }
2063
2064 void
2065 modest_ui_actions_on_select_contacts (GtkAction *action, ModestMsgEditWindow *window)
2066 {
2067         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2068         modest_msg_edit_window_select_contacts (window);
2069 }
2070
2071 void
2072 modest_ui_actions_on_check_names (GtkAction *action, ModestMsgEditWindow *window)
2073 {
2074         g_return_if_fail (MODEST_IS_MSG_EDIT_WINDOW (window));
2075         modest_msg_edit_window_check_names (window);
2076 }
2077
2078
2079 static GtkWidget*
2080 create_move_to_dialog (ModestWindow *win,
2081                        GtkWidget *folder_view,
2082                        GtkWidget **tree_view)
2083 {
2084         GtkWidget *dialog, *scroll;
2085
2086         dialog = gtk_dialog_new_with_buttons (_("mcen_ti_moveto_folders_title"),
2087                                               GTK_WINDOW (win),
2088                                               GTK_DIALOG_MODAL | GTK_DIALOG_NO_SEPARATOR | GTK_DIALOG_DESTROY_WITH_PARENT,
2089                                               GTK_STOCK_OK,
2090                                               GTK_RESPONSE_ACCEPT,
2091                                               GTK_STOCK_CANCEL,
2092                                               GTK_RESPONSE_REJECT,
2093                                               NULL);
2094
2095         /* Create scrolled window */
2096         scroll = gtk_scrolled_window_new (NULL, NULL);
2097         gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW (scroll),
2098                                          GTK_POLICY_AUTOMATIC,
2099                                          GTK_POLICY_AUTOMATIC);
2100
2101         /* Create folder view */
2102         *tree_view = modest_folder_view_new (NULL);
2103         gtk_tree_view_set_model (GTK_TREE_VIEW (*tree_view),
2104                                  gtk_tree_view_get_model (GTK_TREE_VIEW (folder_view)));
2105         gtk_container_add (GTK_CONTAINER (scroll), *tree_view);
2106
2107         /* Add scroll to dialog */
2108         gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), 
2109                             scroll, FALSE, FALSE, 0);
2110
2111         gtk_widget_show_all (GTK_WIDGET(GTK_DIALOG(dialog)->vbox));
2112
2113         return dialog;
2114 }
2115
2116 /*
2117  * Returns TRUE if at least one of the headers of the list belongs to
2118  * a message that has been fully retrieved.
2119  */
2120 static gboolean
2121 has_retrieved_msgs (TnyList *list)
2122 {
2123         TnyIterator *iter;
2124         gboolean found = FALSE;
2125
2126         iter = tny_list_create_iterator (list);
2127         while (tny_iterator_is_done (iter) && !found) {
2128                 TnyHeader *header;
2129                 TnyHeaderFlags flags;
2130
2131                 header = TNY_HEADER (tny_iterator_get_current (iter));
2132                 flags = tny_header_get_flags (header);
2133                 if (!(flags & TNY_HEADER_FLAG_PARTIAL))
2134                         found = TRUE;
2135
2136                 if (!found)
2137                         tny_iterator_next (iter);
2138         }
2139         g_object_unref (iter);
2140
2141         return found;
2142 }
2143
2144 /*
2145  * Shows a confirmation dialog to the user when we're moving messages
2146  * from a remote server to the local storage. Returns the dialog
2147  * response. If it's other kind of movement the it always returns
2148  * GTK_RESPONSE_OK
2149  */
2150 static gint
2151 msgs_move_to_confirmation (GtkWindow *win,
2152                            TnyFolder *dest_folder,
2153                            TnyList *headers)
2154 {
2155         gint response = GTK_RESPONSE_OK;
2156
2157         /* If the destination is a local folder */
2158         if (modest_tny_folder_is_local_folder (dest_folder)) {
2159                 TnyFolder *src_folder;
2160                 TnyIterator *iter;
2161                 TnyHeader *header;
2162
2163                 /* Get source folder */
2164                 iter = tny_list_create_iterator (headers);
2165                 header = TNY_HEADER (tny_iterator_get_current (iter));
2166                 src_folder = tny_header_get_folder (header);
2167                 g_object_unref (header);
2168                 g_object_unref (iter);
2169
2170                 /* If the source is a remote folder */
2171                 if (!modest_tny_folder_is_local_folder (src_folder)) {
2172                         const gchar *message;
2173                         
2174                         if (tny_list_get_length (headers) == 1)
2175                                 if (has_retrieved_msgs (headers))
2176                                         message = _("mcen_nc_move_retrieve");
2177                                 else
2178                                         message = _("mcen_nc_move_header");
2179                         else
2180                                 if (has_retrieved_msgs (headers))
2181                                         message = _("mcen_nc_move_retrieves");
2182                                 else
2183                                         message = _("mcen_nc_move_headers");
2184                         
2185                         response = modest_platform_run_confirmation_dialog (GTK_WINDOW (win),
2186                                                                             (const gchar *) message);
2187                 }
2188         }
2189         return response;
2190 }
2191
2192 /*
2193  * UI handler for the "Move to" action when invoked from the
2194  * ModestMainWindow
2195  */
2196 static void 
2197 modest_ui_actions_on_main_window_move_to (GtkAction *action, 
2198                                           ModestMainWindow *win)
2199 {
2200         GtkWidget *dialog, *folder_view, *tree_view = NULL;
2201         gint result;
2202         TnyFolderStore *folder_store;
2203         ModestMailOperation *mail_op = NULL;
2204
2205         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win));
2206
2207         /* Get the folder view */
2208         folder_view = modest_main_window_get_child_widget (win,
2209                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2210
2211         /* Create and run the dialog */
2212         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);
2213         result = gtk_dialog_run (GTK_DIALOG(dialog));
2214
2215         /* We do this to save an indentation level ;-) */
2216         if (result != GTK_RESPONSE_ACCEPT)
2217                 goto end;
2218
2219         folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2220
2221         if (TNY_IS_ACCOUNT (folder_store))
2222                 goto end;
2223
2224         /* Get folder or messages to transfer */
2225         if (gtk_widget_is_focus (folder_view)) {
2226                 TnyFolderStore *src_folder;
2227                 src_folder = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (folder_view));
2228
2229                 if (TNY_IS_FOLDER (src_folder)) {
2230                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
2231                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2232                                                          mail_op);
2233
2234                         modest_mail_operation_xfer_folder (mail_op, 
2235                                                            TNY_FOLDER (src_folder),
2236                                                            folder_store,
2237                                                            TRUE);
2238                         g_object_unref (G_OBJECT (mail_op));
2239                 }
2240
2241                 /* Frees */
2242                 g_object_unref (G_OBJECT (src_folder));
2243         } else {
2244                 GtkWidget *header_view;
2245                 header_view = modest_main_window_get_child_widget (win,
2246                                                                    MODEST_WIDGET_TYPE_HEADER_VIEW);
2247                 if (gtk_widget_is_focus (header_view)) {
2248                         TnyList *headers;
2249                         gint response;
2250
2251                         headers = modest_header_view_get_selected_headers (MODEST_HEADER_VIEW (header_view));
2252
2253                         /* Ask for user confirmation */
2254                         response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2255                                                               TNY_FOLDER (folder_store), 
2256                                                               headers);
2257
2258                         /* Transfer messages */
2259                         if (response == GTK_RESPONSE_OK) {
2260                                 mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
2261                                 modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2262                                                                  mail_op);
2263
2264                                 modest_mail_operation_xfer_msgs (mail_op, 
2265                                                                  headers,
2266                                                                  TNY_FOLDER (folder_store),
2267                                                                  TRUE);
2268                                 g_object_unref (G_OBJECT (mail_op));
2269                         }
2270                 }
2271         }
2272         g_object_unref (folder_store);
2273
2274  end:
2275         gtk_widget_destroy (dialog);
2276 }
2277
2278
2279 /*
2280  * UI handler for the "Move to" action when invoked from the
2281  * ModestMsgViewWindow
2282  */
2283 static void 
2284 modest_ui_actions_on_msg_view_window_move_to (GtkAction *action, 
2285                                               ModestMsgViewWindow *win)
2286 {
2287         GtkWidget *dialog, *folder_view, *tree_view = NULL;
2288         gint result;
2289         ModestMainWindow *main_window;
2290         TnyMsg *msg;
2291         TnyHeader *header;
2292         TnyList *headers;
2293
2294         /* Get the folder view */
2295         main_window = MODEST_MAIN_WINDOW (modest_window_mgr_get_main_window (modest_runtime_get_window_mgr ()));
2296         folder_view = modest_main_window_get_child_widget (main_window,
2297                                                            MODEST_WIDGET_TYPE_FOLDER_VIEW);
2298
2299         /* Create and run the dialog */
2300         dialog = create_move_to_dialog (MODEST_WINDOW (win), folder_view, &tree_view);  
2301         result = gtk_dialog_run (GTK_DIALOG(dialog));
2302
2303         if (result == GTK_RESPONSE_ACCEPT) {
2304                 TnyFolderStore *folder_store;
2305                 gint response;
2306
2307                 folder_store = modest_folder_view_get_selected (MODEST_FOLDER_VIEW (tree_view));
2308
2309                 /* Create header list */
2310                 msg = modest_msg_view_window_get_message (MODEST_MSG_VIEW_WINDOW (win));
2311                 header = tny_msg_get_header (msg);
2312                 headers = tny_simple_list_new ();
2313                 tny_list_prepend (headers, G_OBJECT (header));
2314                 g_object_unref (header);
2315                 g_object_unref (msg);
2316
2317                 /* Ask user for confirmation. MSG-NOT404 */
2318                 response = msgs_move_to_confirmation (GTK_WINDOW (win), 
2319                                                       TNY_FOLDER (folder_store), 
2320                                                       headers);
2321
2322                 /* Transfer current msg */
2323                 if (response == GTK_RESPONSE_OK) {
2324                         ModestMailOperation *mail_op;
2325
2326                         /* Create mail op */
2327                         mail_op = modest_mail_operation_new (MODEST_MAIL_OPERATION_ID_RECEIVE, G_OBJECT(win));
2328                         modest_mail_operation_queue_add (modest_runtime_get_mail_operation_queue (), 
2329                                                          mail_op);
2330                         
2331                         /* Transfer messages */
2332                         modest_mail_operation_xfer_msgs (mail_op, 
2333                                                          headers,
2334                                                          TNY_FOLDER (folder_store),
2335                                                          TRUE);
2336                         g_object_unref (G_OBJECT (mail_op));
2337                 } else {
2338                         g_object_unref (headers);
2339                 }
2340                 g_object_unref (folder_store);
2341         }
2342         gtk_widget_destroy (dialog);
2343 }
2344
2345 void 
2346 modest_ui_actions_on_move_to (GtkAction *action, 
2347                               ModestWindow *win)
2348 {
2349         g_return_if_fail (MODEST_IS_MAIN_WINDOW (win) ||
2350                           MODEST_IS_MSG_VIEW_WINDOW (win));
2351
2352         if (MODEST_IS_MAIN_WINDOW (win)) 
2353                 modest_ui_actions_on_main_window_move_to (action, 
2354                                                           MODEST_MAIN_WINDOW (win));
2355         else
2356                 modest_ui_actions_on_msg_view_window_move_to (action, 
2357                                                               MODEST_MSG_VIEW_WINDOW (win));
2358 }
2359
2360 /*
2361  * Calls #HeadersFunc for each header already selected in the main
2362  * window or the message currently being shown in the msg view window
2363  */
2364 static void
2365 do_headers_action (ModestWindow *win, 
2366                    HeadersFunc func,
2367                    gpointer user_data)
2368 {
2369         TnyList *headers_list;
2370         TnyIterator *iter;
2371
2372         /* Get headers */
2373         headers_list = get_selected_headers (win);
2374         if (!headers_list)
2375                 return;
2376
2377         /* Call the function for each header */
2378         iter = tny_list_create_iterator (headers_list);
2379         while (!tny_iterator_is_done (iter)) {
2380                 TnyHeader *header;
2381
2382                 header = TNY_HEADER (tny_iterator_get_current (iter));
2383                 func (header, win, user_data);
2384                 g_object_unref (header);
2385                 tny_iterator_next (iter);
2386         }
2387         g_object_unref (iter);
2388 }