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