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